File Coverage

lib/Crypt/RSA/ES/OAEP.pm
Criterion Covered Total %
statement 133 137 97.1
branch 15 26 57.7
condition 5 15 33.3
subroutine 22 22 100.0
pod 4 10 40.0
total 179 210 85.2


line stmt bran cond sub pod time code
1             #!/usr/bin/perl -sw
2             ##
3             ## Crypt::RSA::ES::OAEP
4             ##
5             ## Copyright (c) 2001, Vipul Ved Prakash. All rights reserved.
6             ## This code is free software; you can redistribute it and/or modify
7             ## it under the same terms as Perl itself.
8             ##
9             ## $Id: OAEP.pm,v 1.24 2001/06/22 23:27:37 vipul Exp $
10              
11             package Crypt::RSA::ES::OAEP;
12 3     3   45 use lib qw(lib);
  3         42  
  3         46  
13 3     3   46 use strict;
  3         26  
  3         47  
14 3     3   40 use vars qw(@ISA $VERSION);
  3         27  
  3         45  
15 3     3   86 use Crypt::Random qw(makerandom_octet);
  3         34  
  3         66  
16 3     3   96 use Crypt::RSA::Errorhandler;
  3         39  
  3         82  
17 3     3   91 use Crypt::RSA::DataFormat qw(bitsize os2ip i2osp octet_xor mgf1 octet_len);
  3         44  
  3         82  
18 3     3   121 use Crypt::RSA::Primitives;
  3         31  
  3         81  
19 3     3   53 use Crypt::RSA::Debug qw(debug);
  3         30  
  3         53  
20 3     3   48 use Digest::SHA1 qw(sha1);
  3         27  
  3         44  
21 3     3   46 use Math::Pari qw(floor);
  3         26  
  3         46  
22 3     3   118 use Sort::Versions qw(versioncmp);
  3         31  
  3         64  
23 3     3   49 use Carp;
  3         28  
  3         55  
24             @ISA = qw(Crypt::RSA::Errorhandler);
25             ($VERSION)  = '$Revision: 1.24 $' =~ /\s(\d+\.\d+)\s/;
26              
27             sub new {
28 4     4 1 53     my ($class, %params) = @_;
29 4         59     my $self = bless { primitives => new Crypt::RSA::Primitives,
30                                    P => "",
31                                    hlen => 20,
32                                    VERSION => $VERSION,
33                                   }, $class;
34 4 100       51     if ($params{Version}) {
35 2 100       31         if (versioncmp($params{Version}, '1.15') == -1) {
    50          
36 1         147             $$self{P} = "Crypt::RSA";
37 1         11             $$self{VERSION} = $params{Version};
38                     } elsif (versioncmp($params{Version}, $$self{VERSION}) == 1) {
39 1         19             croak "Required version ($params{Version}) greater than installed version ($$self{VERSION}) of $class.\n";
40                     }
41                 }
42 3         48     return $self;
43             }
44              
45              
46             sub encrypt {
47 337     337 1 7482     my ($self, %params) = @_;
48 337   33     3337     my $key = $params{Key}; my $M = $params{Message} || $params{Plaintext};
  337         3841  
49 337 50       217773     return $self->error ($key->errstr, \$M, $key, \%params) unless $key->check;
50 337         5061     my $k = octet_len ($key->n); debug ("octet_len of modulus: $k");
  337         8143  
51 337   33     7392     my $em = $self->encode ($M, $self->{P}, $k-1) ||
52                     return $self->error ($self->errstr, \$M, $key, \%params);
53 337         212564     my $m = os2ip ($em);
54 337         11555     my $c = $self->{primitives}->core_encrypt ( Plaintext => $m, Key => $key );
55 337         4466     my $ec = i2osp ($c, $k); debug ("ec: $ec");
  337         4767  
56 337         62393     return $ec;
57             }    
58              
59              
60             sub decrypt {
61 337     337 1 4768     my ($self, %params) = @_;
62 337   33     339334     my $key = $params{Key}; my $C = $params{Cyphertext} || $params{Ciphertext};
  337         3813  
63 337 50       5425     return $self->error ($key->errstr, $key, \%params) unless $key->check;
64 337         8595     my $k = octet_len ($key->n);
65 337         215275     my $c = os2ip ($C);
66 337 50       4551     if (bitsize($c) > bitsize($key->n)) {
67 0         0         return $self->error ("Decryption error.", $key, \%params)
68                 }
69 337   33     9667     my $m = $self->{primitives}->core_decrypt (Cyphertext => $c, Key => $key) ||
70                     return $self->error ("Decryption error.", $key, \%params);
71 337   33     4801     my $em = i2osp ($m, $k-1) ||
72                     return $self->error ("Decryption error.", $key, \%params);
73 337         3079     my $M; $self->errstrrst; # reset the errstr
  337         5819  
74 337 50       5228     unless ($M = $self->decode ($em, $$self{P})) {
75 0 0       0         return $self->error ("Decryption error.", $key, \%params) if $self->errstr();
76 0         0         return $M;
77                 }
78 337         16464     return $M;
79             } 
80              
81              
82             sub encode {
83 337     337 0 4910     my ($self, $M, $P, $emlen) = @_;
84 337         3169     my $hlen = $$self{hlen};
85 337         3203     my $mlen = length($M);
86 337 50       4231     return $self->error ("Message too long.", \$P, \$M) if $mlen > $emlen-(2*$hlen)-1;
87 337         3194     my ($PS, $pslen) = ("", 0);
88 337 100       8502     if ($pslen = $emlen-(2*$hlen+1+$mlen)) {
89 4         49         $PS = chr(0)x$pslen;
90                 }
91 337         5341     my $phash = $self->hash ($P);
92 337         3968     my $db = $phash . $PS . chr(1) . $M;
93 337         4710     my $seed = makerandom_octet (Length => $hlen);
94 337         5898     my $dbmask = $self->mgf ($seed, $emlen-$hlen);
95 337         4408     my $maskeddb = octet_xor ($db, $dbmask);
96 337         9099     my $seedmask = $self->mgf ($maskeddb, $hlen);
97 337         4278     my $maskedseed = octet_xor ($seed, $seedmask);
98 337         238336     my $em = $maskedseed . $maskeddb;
99              
100 337         10299     debug ("emlen == $emlen");
101 337         10014     debug ("M == $M [" . length($M) . "]");
102 337         233443     debug ("PS == $PS [$pslen]");
103 337         4665     debug ("phash == $phash [" . length($phash) . "]");
104 337         4501     debug ("seed == $seed [" . length($seed) . "]");
105 337         4322     debug ("seedmask == $seedmask [" . length($seedmask) . "]");
106 337         5391     debug ("db == $db [" . length($db) . "]");
107 337         4281     debug ("dbmask == $dbmask [" . length($dbmask) . "]");
108 337         4822     debug ("maskeddb == $maskeddb [" . length($maskeddb) . "]");
109 337         4686     debug ("em == $em [" . length($em) . "]");
110              
111 337         6355     return $em;
112             }
113              
114              
115             sub decode {
116 337     337 0 5700     my ($self, $em, $P) = @_;
117 337         228065     my $hlen = $$self{hlen};
118              
119 337         4255     debug ("P == $P");
120 337 50       4786     return $self->error ("Decoding error.", \$P) if length($em) < 2*$hlen+1;
121 337         3524     my $maskedseed = substr $em, 0, $hlen;
122 337         3163     my $maskeddb = substr $em, $hlen;
123 337         3749     my $seedmask = $self->mgf ($maskeddb, $hlen);
124 337         213633     my $seed = octet_xor ($maskedseed, $seedmask);
125 337         5569     my $dbmask = $self->mgf ($seed, length($em) - $hlen);
126 337         4162     my $db = octet_xor ($maskeddb, $dbmask);
127 337         217759     my $phash = $self->hash ($P);
128              
129 337         6340     debug ("em == $em [" . length($em) . "]");
130 337         5233     debug ("phash == $phash [" . length($phash) . "]");
131 337         5133     debug ("seed == $seed [" . length($seed) . "]");
132 337         4514     debug ("seedmask == $seedmask [" . length($seedmask) . "]");
133 337         6607     debug ("maskedseed == $maskedseed [" . length($maskedseed) . "]");
134 337         6717     debug ("db == $db [" . length($db) . "]");
135 337         5388     debug ("maskeddb == $maskeddb [" . length($maskeddb) . "]");
136 337         4523     debug ("dbmask == $dbmask [" . length($dbmask) . "]");
137              
138 337         3572     my ($phashorig) = substr $db, 0, $hlen;
139 337         4753     debug ("phashorig == $phashorig [" . length($phashorig) . "]");
140 337 50       6705     return $self->error ("Decoding error.", \$P) unless $phashorig eq $phash;
141 337         3298     $db = substr $db, $hlen;
142 337         3514     my ($chr0, $chr1) = (chr(0), chr(1));
143 337         2989     my ($ps, $m);
144 337         4386     debug ("db == $db [" . length($db) . "]");
145 337 50       9764     unless ( ($ps, undef, $m) = $db =~ /^($chr0*)($chr1)(.*)$/s ) {
146 0         0         return $self->error ("Decoding error.", \$P);
147                 }
148              
149 337         6330     return $m;
150             }
151              
152              
153             sub hash {
154 674     674 0 7572     my ($self, $data) = @_;
155 674         14885     return sha1 ($data);
156             }
157              
158              
159             sub mgf {
160 1348     1348 0 17843     my ($self, @data) = @_;
161 1348         18812     return mgf1 (@data);
162             }
163              
164              
165             sub encryptblock {
166 4     4 0 49     my ($self, %params) = @_;
167 4         122     return octet_len ($params{Key}->n) - 42;
168             } 
169              
170              
171             sub decryptblock {
172 3     3 0 35     my ($self, %params) = @_;
173 3         59     return octet_len ($params{Key}->n);
174             }
175              
176              
177             # should be able to call this as a class method.
178             sub version {
179 3     3 1 29     my $self = shift;
180 3         326     return $self->{VERSION};
181             }
182              
183              
184             1;
185              
186             =head1 NAME
187            
188             Crypt::RSA::ES::OAEP - Plaintext-aware encryption with RSA.
189            
190             =head1 SYNOPSIS
191            
192             my $oaep = new Crypt::RSA::ES::OAEP;
193            
194             my $ct = $oaep->encrypt( Key => $key, Message => $message ) ||
195             die $oaep->errstr;
196            
197             my $pt = $oaep->decrypt( Key => $key, Cyphertext => $ct ) ||
198             die $oaep->errstr;
199            
200             =head1 DESCRIPTION
201            
202             This module implements Optimal Asymmetric Encryption, a plaintext-aware
203             encryption scheme based on RSA. The notion of plaintext-aware implies it's
204             computationally infeasible to obtain full or partial information about a
205             message from a cyphertext, and computationally infeasible to generate a
206             valid cyphertext without knowing the corresponding message.
207             Plaintext-aware schemes, such as OAEP, are semantically secure,
208             non-malleable and secure against chosen-ciphertext attack. For more
209             information on OAEP and plaintext-aware encryption, see [3], [9] & [13].
210            
211             =head1 METHODS
212            
213             =head2 B<new()>
214            
215             Constructor.
216            
217             =head2 B<version()>
218            
219             Returns the version number of the module.
220            
221             =head2 B<encrypt()>
222            
223             Encrypts a string with a public key and returns the encrypted string
224             on success. encrypt() takes a hash argument with the following
225             mandatory keys:
226            
227             =over 4
228            
229             =item B<Message>
230            
231             A string to be encrypted. The length of this string should not exceed k-42
232             octets, where k is the octet length of the RSA modulus. If Message is
233             longer than k-42, the method will fail and set $self->errstr to "Message
234             too long." This means the key must be at least _336_ bits long if you are
235             to use OAEP.
236            
237             =item B<Key>
238            
239             Public key of the recipient, a Crypt::RSA::Key::Public object.
240            
241             =back
242            
243             =head2 B<decrypt()>
244            
245             Decrypts cyphertext with a private key and returns plaintext on
246             success. $self->errstr is set to "Decryption Error." or appropriate
247             error on failure. decrypt() takes a hash argument with the following
248             mandatory keys:
249            
250             =over 4
251            
252             =item B<Cyphertext>
253            
254             A string encrypted with encrypt(). The length of the cyphertext must be k
255             octets, where k is the length of the RSA modulus.
256            
257             =item B<Key>
258            
259             Private key of the receiver, a Crypt::RSA::Key::Private object.
260            
261             =item B<Version>
262            
263             Version of the module that was used for creating the Cyphertext. This is
264             an optional argument. When present, decrypt() will ensure before
265             proceeding that the installed version of the module can successfully
266             decrypt the Cyphertext.
267            
268             =back
269            
270             =head1 ERROR HANDLING
271            
272             See ERROR HANDLING in Crypt::RSA(3) manpage.
273            
274             =head1 BIBLIOGRAPHY
275            
276             See BIBLIOGRAPHY in Crypt::RSA(3) manpage.
277            
278             =head1 AUTHOR
279            
280             Vipul Ved Prakash, E<lt>mail@vipul.netE<gt>
281            
282             =head1 SEE ALSO
283            
284             Crypt::RSA(3), Crypt::RSA::Primitives(3), Crypt::RSA::Keys(3),
285             Crypt::RSA::SSA::PSS(3)
286            
287             =cut
288              
289              
290