File Coverage

blib/lib/Crypt/RSA/SS/PKCS1v15.pm
Criterion Covered Total %
statement 78 86 90.7
branch 15 36 41.6
condition 7 16 43.7
subroutine 14 16 87.5
pod 4 7 57.1
total 118 161 73.2


line stmt bran cond sub pod time code
1             package Crypt::RSA::SS::PKCS1v15;
2 2     2   726 use strict;
  2         4  
  2         47  
3 2     2   8 use warnings;
  2         4  
  2         45  
4              
5             ## Crypt::RSA::SS:PKCS1v15
6             ##
7             ## Copyright (c) 2001, Vipul Ved Prakash. All rights reserved.
8             ## This code is free software; you can redistribute it and/or modify
9             ## it under the same terms as Perl itself.
10              
11 2     2   10 use base 'Crypt::RSA::Errorhandler';
  2         2  
  2         124  
12 2     2   12 use Crypt::RSA::DataFormat qw(octet_len os2ip i2osp h2osp);
  2         4  
  2         100  
13 2     2   297 use Crypt::RSA::Primitives;
  2         5  
  2         48  
14 2     2   11 use Crypt::RSA::Debug qw(debug);
  2         6  
  2         74  
15 2     2   11 use Digest::SHA qw(sha1 sha224 sha256 sha384 sha512);
  2         3  
  2         95  
16 2     2   12 use Digest::MD5 qw(md5);
  2         3  
  2         62  
17 2     2   675 use Digest::MD2 qw(md2);
  2         938  
  2         1592  
18              
19             $Crypt::RSA::SS::PKCS1v15::VERSION = '1.99';
20              
21             # See if we have a bug-fixed RIPEMD-160.
22             my $ripe_hash = undef;
23             if (eval { require Crypt::RIPEMD160; $Crypt::RIPEMD160::VERSION >= 0.05; }) {
24             $ripe_hash = sub { my $r=new Crypt::RIPEMD160; $r->add(shift); $r->digest();};
25             }
26              
27             sub new {
28              
29 8     8 1 4426 my ($class, %params) = @_;
30             my $self = bless {
31             primitives => new Crypt::RSA::Primitives,
32 8   100     47 digest => $params{Digest} || 'SHA1',
33             encoding => {
34             # See http://rfc-ref.org/RFC-TEXTS/3447/chapter9.html
35             MD2 =>[\&md2, "30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 02 05 00 04 10"],
36             MD5 =>[\&md5, "30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 05 05 00 04 10"],
37             SHA1 =>[\&sha1, "30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14"],
38             SHA224=>[\&sha224,"30 2d 30 0d 06 09 60 86 48 01 65 03 04 02 04 05 00 04 1c"],
39             SHA256=>[\&sha256,"30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20"],
40             SHA384=>[\&sha384,"30 41 30 0d 06 09 60 86 48 01 65 03 04 02 02 05 00 04 30"],
41             SHA512=>[\&sha512,"30 51 30 0d 06 09 60 86 48 01 65 03 04 02 03 05 00 04 40"],
42             RIPEMD160=>[$ripe_hash,"30 21 30 09 06 05 2B 24 03 02 01 05 00 04 14"],
43             },
44             VERSION => $Crypt::RSA::SS::PKCS1v15::VERSION,
45             }, $class;
46             # Allow "sha256", "sha-256", "RipeMD-160", etc.
47 8         45 $self->{digest} =~ tr/a-z/A-Z/;
48 8         29 $self->{digest} =~ s/[^A-Z0-9]//g;
49 8 50       32 if ($params{Version}) {
50             # do versioning here
51             }
52 8         26 return $self;
53              
54             }
55              
56              
57             sub sign {
58              
59 18     18 1 36145 my ($self, %params) = @_;
60 18         48 my $key = $params{Key};
61 18   33     69 my $M = $params{Message} || $params{Plaintext};
62 18 50       55 return $self->error ("No Message or Plaintext parameter", \$key, \%params) unless $M;
63 18 50       60 return $self->error ("No Key parameter", \$M, \%params) unless $key;
64 18         203 my $k = octet_len ($key->n);
65              
66 18         50 my $em;
67 18 50       90 unless ($em = $self->encode ($M, $k)) {
68 0 0       0 return $self->error ($self->errstr, \$key, \%params, \$M)
69             if $self->errstr eq "Message too long.";
70 0 0       0 return $self->error ("Modulus too short.", \$key, \%params, \$M)
71             if $self->errstr eq "Intended encoded message length too short";
72             # Other error
73 0         0 return $self->error ($self->errstr, \$key, \%params, \$M);
74             }
75              
76 18         73 my $m = os2ip ($em);
77 18         62074 my $sig = $self->{primitives}->core_sign (Key => $key, Message => $m);
78 18         127 return i2osp ($sig, $k);
79              
80             }
81              
82              
83             sub verify {
84              
85 17     17 1 29421 my ($self, %params) = @_;
86 17   33     45 my $key = $params{Key}; my $M = $params{Message} || $params{Plaintext};
  17         70  
87 17         38 my $S = $params{Signature};
88 17 50       58 return $self->error ("No Message or Plaintext parameter", \$key, \%params) unless $M;
89 17 50       62 return $self->error ("No Key parameter", \$M, \$S, \%params) unless $key;
90 17 50       54 return $self->error ("No Signature parameter", \$key, \$M, \%params) unless $S;
91 17         176 my $k = octet_len ($key->n);
92 17 50       70 return $self->error ("Invalid signature.", \$key, \$M, \%params) if length($S) != $k;
93 17         69 my $s = os2ip ($S);
94 17   33     60316 my $m = $self->{primitives}->core_verify (Key => $key, Signature => $s) ||
95             $self->error ("Invalid signature.", \$M, $key, \%params);
96 17   50     683 my $em = i2osp ($m, $k) ||
97             return $self->error ("Invalid signature.", \$M, \$S, $key, \%params);
98 17         41 my $em1;
99 17 50       87 unless ($em1 = $self->encode ($M, $k)) {
100 0 0       0 return $self->error ($self->errstr, \$key, \%params, \$M)
101             if $self->errstr eq "Message too long.";
102 0 0       0 return $self->error ("Modulus too short.", \$key, \%params, \$M)
103             if $self->errstr eq "Intended encoded message length too short.";
104             }
105              
106 17         83 debug ("em: $em"); debug ("em1: $em1");
  17         63  
107              
108 17 100       316 return 1 if $em eq $em1;
109 5         44 return $self->error ("Invalid signature.", \$M, \$key, \%params);
110              
111             }
112              
113              
114             sub encode {
115              
116 35     35 0 121 my ($self, $M, $emlen) = @_;
117              
118 35         145 my $encoding = $self->{encoding}->{$self->{digest}};
119 35 50       120 return $self->error ("Invalid encoding: $self->{digest}") unless defined $encoding;
120 35         110 my ($hashfunc, $digestinfo) = @$encoding;
121 35 50       124 return $self->error ("encoding method $self->{digest} not supported") unless defined $hashfunc;
122              
123             # Changed to match RFC 2313 (PKCS#1 v1.5) and 3447 (PKCS#1 v2.1).
124             # There was apparently some confusion from XML documentation that
125             # printed a different set of instructions here. See, for example:
126             # http://osdir.com/ml/mozilla.crypto/2005-05/msg00300.htm
127             # However, previously emlen was always k-1, so the result ended up
128             # being identical anyway. One change is that we now return if there
129             # is not enough padding. Previously the error string would be set
130             # but processing would continue.
131             #
132             # Refs:
133             # http://rfc-ref.org/RFC-TEXTS/3447/chapter9.html
134             # https://tools.ietf.org/html/rfc2313
135 35         735 my $H = $hashfunc->($M);
136 35         144 my $alg = h2osp($digestinfo);
137 35 50 33     278 return $self->error ("Invalid digest results: $self->{digest}") unless defined $H && length($H) > 0;
138              
139 35         95 my $T = $alg . $H;
140 35 50       119 return $self->error ("Intended encoded message length too short.", \$M) if $emlen < length($T) + 11;
141 35         77 my $pslen = $emlen - length($T) - 3;
142 35         97 my $PS = chr(0xff) x $pslen;
143 35         100 my $em = chr(0) . chr(1) . $PS . chr(0) . $T;
144 35         143 return $em;
145              
146             }
147              
148              
149             sub version {
150 0     0 1 0 my $self = shift;
151 0         0 return $self->{VERSION};
152             }
153              
154              
155             sub signblock {
156 0     0 0 0 return -1;
157             }
158              
159              
160             sub verifyblock {
161 7     7 0 79 my ($self, %params) = @_;
162 7         89 return octet_len($params{Key}->n);
163             }
164              
165              
166             1;
167              
168             =head1 NAME
169              
170             Crypt::RSA::SS::PKCS1v15 - PKCS #1 v1.5 signatures.
171              
172             =head1 SYNOPSIS
173              
174             my $pkcs = new Crypt::RSA::SS::PKCS1v15 (
175             Digest => 'MD5'
176             );
177              
178             my $signature = $pkcs->sign (
179             Message => $message,
180             Key => $private,
181             ) || die $pss->errstr;
182              
183             my $verify = $pkcs->verify (
184             Message => $message,
185             Key => $key,
186             Signature => $signature,
187             ) || die $pss->errstr;
188              
189              
190             =head1 DESCRIPTION
191              
192             This module implements PKCS #1 v1.5 signatures based on RSA. See [13]
193             for details on the scheme.
194              
195             =head1 METHODS
196              
197             =head2 B
198              
199             Constructor. Takes a hash as argument with the following key:
200              
201             =over 4
202              
203             =item B
204              
205             Name of the Message Digest algorithm. Three Digest algorithms are
206             supported: MD2, MD5, SHA1, SHA224, SHA256, SHA384, and SHA512.
207             Digest defaults to SHA1.
208              
209             =back
210              
211              
212             =head2 B
213              
214             Returns the version number of the module.
215              
216             =head2 B
217              
218             Computes a PKCS #1 v1.5 signature on a message with the private key of the
219             signer. sign() takes a hash argument with the following mandatory keys:
220              
221             =over 4
222              
223             =item B
224              
225             Message to be signed, a string of arbitrary length.
226              
227             =item B
228              
229             Private key of the signer, a Crypt::RSA::Key::Private object.
230              
231             =back
232              
233             =head2 B
234              
235             Verifies a signature generated with sign(). Returns a true value on
236             success and false on failure. $self->errstr is set to "Invalid signature."
237             or appropriate error on failure. verify() takes a hash argument with the
238             following mandatory keys:
239              
240             =over 4
241              
242             =item B
243              
244             Public key of the signer, a Crypt::RSA::Key::Public object.
245              
246             =item B
247              
248             The original signed message, a string of arbitrary length.
249              
250             =item B
251              
252             Signature computed with sign(), a string.
253              
254             =back
255              
256             =head1 ERROR HANDLING
257              
258             See ERROR HANDLING in Crypt::RSA(3) manpage.
259              
260             =head1 BIBLIOGRAPHY
261              
262             See BIBLIOGRAPHY in Crypt::RSA(3) manpage.
263              
264             =head1 AUTHOR
265              
266             Vipul Ved Prakash, Email@vipul.netE
267              
268             =head1 SEE ALSO
269              
270             Crypt::RSA(3), Crypt::RSA::Primitives(3), Crypt::RSA::Keys(3),
271             Crypt::RSA::EME::OAEP(3)
272              
273             =cut
274              
275