File Coverage

lib/Crypt/RSA/ES/OAEP.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


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 2     2   9378 use strict;
  2         5  
  2         78  
13 2     2   9 use base 'Crypt::RSA::Errorhandler';
  2         3  
  2         1236  
14 2     2   3520 use Crypt::Random qw(makerandom_octet);
  0            
  0            
15             use Crypt::RSA::DataFormat qw(bitsize os2ip i2osp octet_xor mgf1 octet_len);
16             use Crypt::RSA::Primitives;
17             use Crypt::RSA::Debug qw(debug);
18             use Digest::SHA1 qw(sha1);
19             use Math::Pari qw(floor);
20             use Sort::Versions qw(versioncmp);
21             use Carp;
22              
23             $Crypt::RSA::ES::OAEP::VERSION = '1.99';
24              
25             sub new {
26             my ($class, %params) = @_;
27             my $self = bless { primitives => new Crypt::RSA::Primitives,
28             P => "",
29             hlen => 20,
30             VERSION => $Crypt::RSA::ES::OAEP::VERSION,
31             }, $class;
32             if ($params{Version}) {
33             if (versioncmp($params{Version}, '1.15') == -1) {
34             $$self{P} = "Crypt::RSA";
35             $$self{VERSION} = $params{Version};
36             } elsif (versioncmp($params{Version}, $$self{VERSION}) == 1) {
37             croak "Required version ($params{Version}) greater than installed version ($$self{VERSION}) of $class.\n";
38             }
39             }
40             return $self;
41             }
42              
43              
44             sub encrypt {
45             my ($self, %params) = @_;
46             my $key = $params{Key}; my $M = $params{Message} || $params{Plaintext};
47             return $self->error ("Missing Message or Plaintext parameter", \$key, \%params) unless $M;
48             return $self->error ($key->errstr, \$M, $key, \%params) unless $key->check;
49             my $k = octet_len ($key->n); debug ("octet_len of modulus: $k");
50             my $em = $self->encode ($M, $self->{P}, $k-1) ||
51             return $self->error ($self->errstr, \$M, $key, \%params);
52             my $m = os2ip ($em);
53             my $c = $self->{primitives}->core_encrypt ( Plaintext => $m, Key => $key );
54             my $ec = i2osp ($c, $k); debug ("ec: $ec");
55             return $ec;
56             }
57              
58              
59             sub decrypt {
60             my ($self, %params) = @_;
61             my $key = $params{Key}; my $C = $params{Cyphertext} || $params{Ciphertext};
62             return $self->error ("Missing Cyphertext or Ciphertext parameter", \$key, \%params) unless $C;
63             return $self->error ($key->errstr, $key, \%params) unless $key->check;
64             my $k = octet_len ($key->n);
65             my $c = os2ip ($C);
66             if (bitsize($c) > bitsize($key->n)) {
67             return $self->error ("Decryption error.", $key, \%params)
68             }
69             my $m = $self->{primitives}->core_decrypt (Cyphertext => $c, Key => $key) ||
70             return $self->error ("Decryption error.", $key, \%params);
71             my $em = i2osp ($m, $k-1) ||
72             return $self->error ("Decryption error.", $key, \%params);
73             my $M; $self->errstrrst; # reset the errstr
74             unless ($M = $self->decode ($em, $$self{P})) {
75             return $self->error ("Decryption error.", $key, \%params) if $self->errstr();
76             return $M;
77             }
78             return $M;
79             }
80              
81              
82             sub encode {
83             my ($self, $M, $P, $emlen) = @_;
84             my $hlen = $$self{hlen};
85             my $mlen = length($M);
86             return $self->error ("Message too long.", \$P, \$M) if $mlen > $emlen-(2*$hlen)-1;
87             my ($PS, $pslen) = ("", 0);
88             if ($pslen = $emlen-(2*$hlen+1+$mlen)) {
89             $PS = chr(0)x$pslen;
90             }
91             my $phash = $self->hash ($P);
92             my $db = $phash . $PS . chr(1) . $M;
93             my $seed = makerandom_octet (Length => $hlen);
94             my $dbmask = $self->mgf ($seed, $emlen-$hlen);
95             my $maskeddb = octet_xor ($db, $dbmask);
96             my $seedmask = $self->mgf ($maskeddb, $hlen);
97             my $maskedseed = octet_xor ($seed, $seedmask);
98             my $em = $maskedseed . $maskeddb;
99              
100             debug ("emlen == $emlen");
101             debug ("M == $M [" . length($M) . "]");
102             debug ("PS == $PS [$pslen]");
103             debug ("phash == $phash [" . length($phash) . "]");
104             debug ("seed == $seed [" . length($seed) . "]");
105             debug ("seedmask == $seedmask [" . length($seedmask) . "]");
106             debug ("db == $db [" . length($db) . "]");
107             debug ("dbmask == $dbmask [" . length($dbmask) . "]");
108             debug ("maskeddb == $maskeddb [" . length($maskeddb) . "]");
109             debug ("em == $em [" . length($em) . "]");
110              
111             return $em;
112             }
113              
114              
115             sub decode {
116             my ($self, $em, $P) = @_;
117             my $hlen = $$self{hlen};
118              
119             debug ("P == $P");
120             return $self->error ("Decoding error.", \$P) if length($em) < 2*$hlen+1;
121             my $maskedseed = substr $em, 0, $hlen;
122             my $maskeddb = substr $em, $hlen;
123             my $seedmask = $self->mgf ($maskeddb, $hlen);
124             my $seed = octet_xor ($maskedseed, $seedmask);
125             my $dbmask = $self->mgf ($seed, length($em) - $hlen);
126             my $db = octet_xor ($maskeddb, $dbmask);
127             my $phash = $self->hash ($P);
128              
129             debug ("em == $em [" . length($em) . "]");
130             debug ("phash == $phash [" . length($phash) . "]");
131             debug ("seed == $seed [" . length($seed) . "]");
132             debug ("seedmask == $seedmask [" . length($seedmask) . "]");
133             debug ("maskedseed == $maskedseed [" . length($maskedseed) . "]");
134             debug ("db == $db [" . length($db) . "]");
135             debug ("maskeddb == $maskeddb [" . length($maskeddb) . "]");
136             debug ("dbmask == $dbmask [" . length($dbmask) . "]");
137              
138             my ($phashorig) = substr $db, 0, $hlen;
139             debug ("phashorig == $phashorig [" . length($phashorig) . "]");
140             return $self->error ("Decoding error.", \$P) unless $phashorig eq $phash;
141             $db = substr $db, $hlen;
142             my ($chr0, $chr1) = (chr(0), chr(1));
143             my ($ps, $m);
144             debug ("db == $db [" . length($db) . "]");
145             unless ( ($ps, undef, $m) = $db =~ /^($chr0*)($chr1)(.*)$/s ) {
146             return $self->error ("Decoding error.", \$P);
147             }
148              
149             return $m;
150             }
151              
152              
153             sub hash {
154             my ($self, $data) = @_;
155             return sha1 ($data);
156             }
157              
158              
159             sub mgf {
160             my ($self, @data) = @_;
161             return mgf1 (@data);
162             }
163              
164              
165             sub encryptblock {
166             my ($self, %params) = @_;
167             return octet_len ($params{Key}->n) - 42;
168             }
169              
170              
171             sub decryptblock {
172             my ($self, %params) = @_;
173             return octet_len ($params{Key}->n);
174             }
175              
176              
177             # should be able to call this as a class method.
178             sub version {
179             my $self = shift;
180             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
214              
215             Constructor.
216              
217             =head2 B
218              
219             Returns the version number of the module.
220              
221             =head2 B
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
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
238              
239             Public key of the recipient, a Crypt::RSA::Key::Public object.
240              
241             =back
242              
243             =head2 B
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
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
258              
259             Private key of the receiver, a Crypt::RSA::Key::Private object.
260              
261             =item B
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, Email@vipul.netE
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