File Coverage

blib/lib/Crypt/RSA/ES/OAEP.pm
Criterion Covered Total %
statement 38 133 28.5
branch 4 30 13.3
condition 0 12 0.0
subroutine 11 20 55.0
pod 4 10 40.0
total 57 205 27.8


line stmt bran cond sub pod time code
1             package Crypt::RSA::ES::OAEP;
2 1     1   24986 use strict;
  1         3  
  1         38  
3 1     1   5 use warnings;
  1         3  
  1         38  
4              
5             ## Crypt::RSA::ES::OAEP
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 1     1   6 use base 'Crypt::RSA::Errorhandler';
  1         2  
  1         661  
12 1     1   1071 use Bytes::Random::Secure qw/random_bytes/;
  1         623895  
  1         90  
13 1     1   1212 use Crypt::RSA::DataFormat qw(bitsize os2ip i2osp octet_xor mgf1 octet_len);
  1         4  
  1         81  
14 1     1   546 use Crypt::RSA::Primitives;
  1         4  
  1         35  
15 1     1   6 use Crypt::RSA::Debug qw(debug);
  1         2  
  1         53  
16 1     1   6 use Digest::SHA qw(sha1);
  1         3  
  1         113  
17 1     1   756 use Sort::Versions qw(versioncmp);
  1         1299  
  1         56  
18 1     1   5 use Carp;
  1         2  
  1         1456  
19              
20             $Crypt::RSA::ES::OAEP::VERSION = '1.99';
21              
22             sub new {
23 2     2 1 1296 my ($class, %params) = @_;
24 2         14 my $self = bless { primitives => new Crypt::RSA::Primitives,
25             P => "",
26             hlen => 20,
27             VERSION => $Crypt::RSA::ES::OAEP::VERSION,
28             }, $class;
29 2 50       6 if ($params{Version}) {
30 2 100       8 if (versioncmp($params{Version}, '1.15') == -1) {
    50          
31 1         45 $$self{P} = "Crypt::RSA";
32 1         4 $$self{VERSION} = $params{Version};
33             } elsif (versioncmp($params{Version}, $$self{VERSION}) == 1) {
34 1         344 croak "Required version ($params{Version}) greater than installed version ($$self{VERSION}) of $class.\n";
35             }
36             }
37 1         3 return $self;
38             }
39              
40              
41             sub encrypt {
42 0     0 1   my ($self, %params) = @_;
43 0   0       my $key = $params{Key}; my $M = $params{Message} || $params{Plaintext};
  0            
44 0 0         return $self->error ("Missing Message or Plaintext parameter", \$key, \%params) unless $M;
45 0 0         return $self->error ($key->errstr, \$M, $key, \%params) unless $key->check;
46 0           my $k = octet_len ($key->n); debug ("octet_len of modulus: $k");
  0            
47 0   0       my $em = $self->encode ($M, $self->{P}, $k-1) ||
48             return $self->error ($self->errstr, \$M, $key, \%params);
49 0           my $m = os2ip ($em);
50 0           my $c = $self->{primitives}->core_encrypt ( Plaintext => $m, Key => $key );
51 0           my $ec = i2osp ($c, $k); debug ("ec: $ec");
  0            
52 0           return $ec;
53             }
54              
55              
56             sub decrypt {
57 0     0 1   my ($self, %params) = @_;
58 0   0       my $key = $params{Key}; my $C = $params{Cyphertext} || $params{Ciphertext};
  0            
59 0 0         return $self->error ("Missing Cyphertext or Ciphertext parameter", \$key, \%params) unless $C;
60 0 0         return $self->error ($key->errstr, $key, \%params) unless $key->check;
61 0           my $k = octet_len ($key->n);
62 0           my $c = os2ip ($C);
63 0 0         if (bitsize($c) > bitsize($key->n)) {
64 0           return $self->error ("Decryption error.", $key, \%params)
65             }
66 0   0       my $m = $self->{primitives}->core_decrypt (Cyphertext => $c, Key => $key) ||
67             return $self->error ("Decryption error.", $key, \%params);
68 0   0       my $em = i2osp ($m, $k-1) ||
69             return $self->error ("Decryption error.", $key, \%params);
70 0           my $M; $self->errstrrst; # reset the errstr
  0            
71 0 0         unless ($M = $self->decode ($em, $$self{P})) {
72 0 0         return $self->error ("Decryption error.", $key, \%params) if $self->errstr();
73 0           return $M;
74             }
75 0           return $M;
76             }
77              
78              
79             sub encode {
80 0     0 0   my ($self, $M, $P, $emlen) = @_;
81 0           my $hlen = $$self{hlen};
82 0           my $mlen = length($M);
83 0 0         return $self->error ("Message too long.", \$P, \$M) if $mlen > $emlen-(2*$hlen)-1;
84 0           my ($PS, $pslen) = ("", 0);
85 0 0         if ($pslen = $emlen-(2*$hlen+1+$mlen)) {
86 0           $PS = chr(0)x$pslen;
87             }
88 0           my $phash = $self->hash ($P);
89 0           my $db = $phash . $PS . chr(1) . $M;
90 0           my $seed = random_bytes($hlen);
91 0           my $dbmask = $self->mgf ($seed, $emlen-$hlen);
92 0           my $maskeddb = octet_xor ($db, $dbmask);
93 0           my $seedmask = $self->mgf ($maskeddb, $hlen);
94 0           my $maskedseed = octet_xor ($seed, $seedmask);
95 0           my $em = $maskedseed . $maskeddb;
96              
97 0           debug ("emlen == $emlen");
98 0           debug ("M == $M [" . length($M) . "]");
99 0           debug ("PS == $PS [$pslen]");
100 0           debug ("phash == $phash [" . length($phash) . "]");
101 0           debug ("seed == $seed [" . length($seed) . "]");
102 0           debug ("seedmask == $seedmask [" . length($seedmask) . "]");
103 0           debug ("db == $db [" . length($db) . "]");
104 0           debug ("dbmask == $dbmask [" . length($dbmask) . "]");
105 0           debug ("maskeddb == $maskeddb [" . length($maskeddb) . "]");
106 0           debug ("em == $em [" . length($em) . "]");
107              
108 0           return $em;
109             }
110              
111              
112             sub decode {
113 0     0 0   my ($self, $em, $P) = @_;
114 0           my $hlen = $$self{hlen};
115              
116 0           debug ("P == $P");
117 0 0         return $self->error ("Decoding error.", \$P) if length($em) < 2*$hlen+1;
118 0           my $maskedseed = substr $em, 0, $hlen;
119 0           my $maskeddb = substr $em, $hlen;
120 0           my $seedmask = $self->mgf ($maskeddb, $hlen);
121 0           my $seed = octet_xor ($maskedseed, $seedmask);
122 0           my $dbmask = $self->mgf ($seed, length($em) - $hlen);
123 0           my $db = octet_xor ($maskeddb, $dbmask);
124 0           my $phash = $self->hash ($P);
125              
126 0           debug ("em == $em [" . length($em) . "]");
127 0           debug ("phash == $phash [" . length($phash) . "]");
128 0           debug ("seed == $seed [" . length($seed) . "]");
129 0           debug ("seedmask == $seedmask [" . length($seedmask) . "]");
130 0           debug ("maskedseed == $maskedseed [" . length($maskedseed) . "]");
131 0           debug ("db == $db [" . length($db) . "]");
132 0           debug ("maskeddb == $maskeddb [" . length($maskeddb) . "]");
133 0           debug ("dbmask == $dbmask [" . length($dbmask) . "]");
134              
135 0           my ($phashorig) = substr $db, 0, $hlen;
136 0           debug ("phashorig == $phashorig [" . length($phashorig) . "]");
137 0 0         return $self->error ("Decoding error.", \$P) unless $phashorig eq $phash;
138 0           $db = substr $db, $hlen;
139 0           my ($chr0, $chr1) = (chr(0), chr(1));
140 0           my ($ps, $m);
141 0           debug ("db == $db [" . length($db) . "]");
142 0 0         unless ( ($ps, undef, $m) = $db =~ /^($chr0*)($chr1)(.*)$/s ) {
143 0           return $self->error ("Decoding error.", \$P);
144             }
145              
146 0           return $m;
147             }
148              
149              
150             sub hash {
151 0     0 0   my ($self, $data) = @_;
152 0           return sha1 ($data);
153             }
154              
155              
156             sub mgf {
157 0     0 0   my ($self, @data) = @_;
158 0           return mgf1 (@data);
159             }
160              
161              
162             sub encryptblock {
163 0     0 0   my ($self, %params) = @_;
164 0           return octet_len ($params{Key}->n) - 42;
165             }
166              
167              
168             sub decryptblock {
169 0     0 0   my ($self, %params) = @_;
170 0           return octet_len ($params{Key}->n);
171             }
172              
173              
174             # should be able to call this as a class method.
175             sub version {
176 0     0 1   my $self = shift;
177 0           return $self->{VERSION};
178             }
179              
180              
181             1;
182              
183             =head1 NAME
184              
185             Crypt::RSA::ES::OAEP - Plaintext-aware encryption with RSA.
186              
187             =head1 SYNOPSIS
188              
189             my $oaep = new Crypt::RSA::ES::OAEP;
190              
191             my $ct = $oaep->encrypt( Key => $key, Message => $message ) ||
192             die $oaep->errstr;
193              
194             my $pt = $oaep->decrypt( Key => $key, Cyphertext => $ct ) ||
195             die $oaep->errstr;
196              
197             =head1 DESCRIPTION
198              
199             This module implements Optimal Asymmetric Encryption, a plaintext-aware
200             encryption scheme based on RSA. The notion of plaintext-aware implies it's
201             computationally infeasible to obtain full or partial information about a
202             message from a cyphertext, and computationally infeasible to generate a
203             valid cyphertext without knowing the corresponding message.
204             Plaintext-aware schemes, such as OAEP, are semantically secure,
205             non-malleable and secure against chosen-ciphertext attack. For more
206             information on OAEP and plaintext-aware encryption, see [3], [9] & [13].
207              
208             =head1 METHODS
209              
210             =head2 B
211              
212             Constructor.
213              
214             =head2 B
215              
216             Returns the version number of the module.
217              
218             =head2 B
219              
220             Encrypts a string with a public key and returns the encrypted string
221             on success. encrypt() takes a hash argument with the following
222             mandatory keys:
223              
224             =over 4
225              
226             =item B
227              
228             A string to be encrypted. The length of this string should not exceed k-42
229             octets, where k is the octet length of the RSA modulus. If Message is
230             longer than k-42, the method will fail and set $self->errstr to "Message
231             too long." This means the key must be at least _336_ bits long if you are
232             to use OAEP.
233              
234             =item B
235              
236             Public key of the recipient, a Crypt::RSA::Key::Public object.
237              
238             =back
239              
240             =head2 B
241              
242             Decrypts cyphertext with a private key and returns plaintext on
243             success. $self->errstr is set to "Decryption Error." or appropriate
244             error on failure. decrypt() takes a hash argument with the following
245             mandatory keys:
246              
247             =over 4
248              
249             =item B
250              
251             A string encrypted with encrypt(). The length of the cyphertext must be k
252             octets, where k is the length of the RSA modulus.
253              
254             =item B
255              
256             Private key of the receiver, a Crypt::RSA::Key::Private object.
257              
258             =item B
259              
260             Version of the module that was used for creating the Cyphertext. This is
261             an optional argument. When present, decrypt() will ensure before
262             proceeding that the installed version of the module can successfully
263             decrypt the Cyphertext.
264              
265             =back
266              
267             =head1 ERROR HANDLING
268              
269             See ERROR HANDLING in Crypt::RSA(3) manpage.
270              
271             =head1 BIBLIOGRAPHY
272              
273             See BIBLIOGRAPHY in Crypt::RSA(3) manpage.
274              
275             =head1 AUTHOR
276              
277             Vipul Ved Prakash, Email@vipul.netE
278              
279             =head1 SEE ALSO
280              
281             Crypt::RSA(3), Crypt::RSA::Primitives(3), Crypt::RSA::Keys(3),
282             Crypt::RSA::SSA::PSS(3)
283              
284             =cut
285              
286