1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
|
#!/usr/bin/perl -sw
##
## Crypt::RSA - Pure-perl implementation of RSA encryption/signing
## algorithms.
##
## Copyright (c) 2000-2001, Vipul Ved Prakash. All rights reserved.
## This code is free software; you can redistribute it and/or modify
## it under the same terms as Perl itself.
##
## $Id: RSA.pm,v 1.48 2001/09/25 12:44:55 vipul Exp $
package Crypt::RSA;
use FindBin qw($Bin);
use lib "$Bin/../../lib";
use strict;
use base 'Class::Loader';
use base 'Crypt::RSA::Errorhandler';
use Crypt::RSA::Key;
use Crypt::RSA::DataFormat qw(steak octet_len);
use Convert::ASCII::Armour;
use Carp;
$Crypt::RSA::VERSION = '1.99'; # change this elsewhere too!
my %DEFAULTS = (
'ES' => { Name => 'OAEP_ES' },
'SS' => { Name => 'PSS_SS' },
'PP' => { Name => 'ASCII_PP' },
);
my %KNOWNMAP = (
# ENCRYPTION SCHEMES
OAEP_ES => { Module => "Crypt::RSA::ES::OAEP" },
PKCS1v21_ES => { Module => "Crypt::RSA::ES::OAEP" },
PKCS1v15_ES => { Module => "Crypt::RSA::ES::PKCS1v15" },
# SIGNATURE SCHEMES
PSS_SS => { Module => "Crypt::RSA::SS::PSS" },
PKCS1v21_SS => { Module => "Crypt::RSA::SS::PSS" },
PKCS1v15_SS => { Module => "Crypt::RSA::SS::PKCS1v15" },
# POST PROCESSORS
ASCII_PP => { Module => "Convert::ASCII::Armour" },
);
sub new {
my ($class, %params) = @_;
my %self = (%DEFAULTS, %params);
my $self = bless \%self, $class;
$self->_storemap (%KNOWNMAP);
for (qw(ES SS PP)) {
$$self{$_} = { Name => $$self{$_} . "_$_" } unless ref $$self{$_};
$$self{lc($_)} = $self->_load ( %{$$self{$_}} );
}
$$self{keychain} = new Crypt::RSA::Key;
return bless \%self, $class;
}
sub keygen {
my ($self, %params) = @_;
$params{KF} = $$self{KF} if $$self{KF};
my @keys;
return (@keys = $self->{keychain}->generate (%params))
? @keys
: $self->error ($self->{keychain}->errstr);
}
sub encrypt {
my ($self, %params) = @_;
my $plaintext = $params{Message} || $params{Plaintext};
my $key = $params{Key};
return $self->error ($key->errstr, \%params, $key, \$plaintext)
unless $key->check();
my $blocksize = blocksize ( $$self{es}->encryptblock (Key => $key),
length($plaintext)
);
return $self->error("Message too long.", \$key, \%params) if $blocksize <= 0;
my $cyphertext;
my @segments = steak ($plaintext, $blocksize);
for (@segments) {
$cyphertext .= $self->{es}->encrypt (Message => $_, Key => $key)
|| return $self->error ($self->{es}->errstr, \$key, \%params);
}
if ($params{Armour} || $params{Armor}) {
$cyphertext = $self->{pp}->armour (
Object => 'RSA ENCRYPTED MESSAGE',
Headers => {
Scheme => $$self{ES}{Module} || ${$KNOWNMAP{$$self{ES}{Name}}}{Module},
Version => $self->{es}->version()
},
Content => { Cyphertext => $cyphertext },
Compress => 1,
);
}
return $cyphertext;
}
sub decrypt {
my ($self , %params) = @_;
my $cyphertext = $params{Cyphertext} || $params{Ciphertext};
my $key = $params{Key};
return $self->error ($key->errstr, \%params, $key) unless $key->check();
if ($params{Armour} || $params{Armor}) {
my $decoded = $self->{pp}->unarmour ($cyphertext) ||
return $self->error ($self->{pp}->errstr());
$cyphertext = $$decoded{Content}{Cyphertext}
}
my $plaintext;
my $blocksize = blocksize ( $$self{es}->decryptblock (Key => $key),
length($cyphertext)
);
return $self->error("Message too long.") if $blocksize <= 0;
my @segments = steak ($cyphertext, $blocksize);
for (@segments) {
$plaintext .= $self->{es}->decrypt (Cyphertext=> $_, Key => $key)
|| return $self->error ($self->{es}->errstr, \$key, \%params);
}
return $plaintext;
}
sub sign {
my ($self, %params) = @_;
my $signature = $self->{ss}->sign (%params)
|| return $self->error ($self->{ss}->errstr,
$params{Key}, \%params);
if ($params{Armour} || $params{Armor}) {
$signature = $self->{pp}->armour (
Object => "RSA SIGNATURE",
Headers => {
Scheme => $$self{SS}{Module} || ${$KNOWNMAP{$$self{SS}{Name}}}{Module},
Version => $self->{ss}->version() },
Content => { Signature => $signature },
);
}
return $signature;
}
sub verify {
my ($self, %params) = @_;
if ($params{Armour} || $params{Armor}) {
my $decoded = $self->{pp}->unarmour ($params{Signature}) ||
return $self->error ($self->{pp}->errstr());
$params{Signature} = $$decoded{Content}{Signature}
}
my $verify = $self->{ss}->verify (%params) ||
return $self->error ($self->{ss}->errstr, $params{Key}, \%params);
return $verify;
}
sub blocksize {
my ($blocksize, $ptsize) = @_;
return $ptsize if $blocksize == -1;
return 0 if $blocksize < 1;
return $blocksize;
}
1;
=head1 NAME
Crypt::RSA - RSA public-key cryptosystem.
=head1 SYNOPSIS
my $rsa = new Crypt::RSA;
my ($public, $private) =
$rsa->keygen (
Identity => 'Lord Macbeth <macbeth@glamis.com>',
Size => 1024,
Password => 'A day so foul & fair',
Verbosity => 1,
) or die $rsa->errstr();
my $cyphertext =
$rsa->encrypt (
Message => $message,
Key => $public,
Armour => 1,
) || die $rsa->errstr();
my $plaintext =
$rsa->decrypt (
Cyphertext => $cyphertext,
Key => $private,
Armour => 1,
) || die $rsa->errstr();
my $signature =
$rsa->sign (
Message => $message,
Key => $private
) || die $rsa->errstr();
my $verify =
$rsa->verify (
Message => $message,
Signature => $signature,
Key => $public
) || die $rsa->errstr();
=head1 NOTE
This manual assumes familiarity with public-key cryptography and the RSA
algorithm. If you don't know what these are or how they work, please refer
to the sci.crypt FAQ[15]. A formal treatment of RSA can be found in [1].
=head1 DESCRIPTION
Crypt::RSA is a pure-perl, cleanroom implementation of the RSA public-key
cryptosystem. It uses Math::Pari(3), a perl interface to the blazingly
fast PARI library, for big integer arithmetic and number theoretic
computations.
Crypt::RSA provides arbitrary size key-pair generation, plaintext-aware
encryption (OAEP) and digital signatures with appendix (PSS). For
compatibility with SSLv3, RSAREF2, PGP and other applications that follow
the PKCS #1 v1.5 standard, it also provides PKCS #1 v1.5 encryption and
signatures.
Crypt::RSA is structured as bundle of modules that encapsulate different
parts of the RSA cryptosystem. The RSA algorithm is implemented in
Crypt::RSA::Primitives(3). Encryption schemes, located under
Crypt::RSA::ES, and signature schemes, located under Crypt::RSA::SS, use
the RSA algorithm to build encryption/signature schemes that employ secure
padding. (See the note on Security of Padding Schemes.)
The key generation engine and other functions that work on both components
of the key-pair are encapsulated in Crypt::RSA::Key(3).
Crypt::RSA::Key::Public(3) & Crypt::RSA::Key::Private(3) provide
mechanisms for storage & retrival of keys from disk, decoding & encoding
of keys in certain formats, and secure representation of keys in memory.
Finally, the Crypt::RSA module provides a convenient, DWIM wrapper around
the rest of the modules in the bundle.
=head1 SECURITY OF PADDING SCHEMES
It has been conclusively shown that textbook RSA is insecure[3,7]. Secure
RSA requires that plaintext is padded in a specific manner before
encryption and signing. There are four main standards for padding: PKCS
#1 v1.5 encryption & signatures, and OAEP encryption & PSS signatures.
Crypt::RSA implements these as four modules that
provide overloaded encrypt(), decrypt(), sign() and verify() methods that
add padding functionality to the basic RSA operations.
Crypt::RSA::ES::PKCS1v15(3) implements PKCS #1 v1.5 encryption,
Crypt::RSA::SS::PKCS1v15(3) implements PKCS #1 v1.5 signatures,
Crypt::RSA::ES::OAEP(3) implements Optimal Asymmetric Encryption and
Crypt::RSA::SS::PSS(3) Probabilistic Signatures.
PKCS #1 v1.5 schemes are older and hence more widely deployed, but PKCS #1
v1.5 encryption has certain flaws that make it vulnerable to
chosen-cyphertext attacks[9]. Even though Crypt::RSA works around these
vulnerabilities, it is recommended that new applications use OAEP and PSS,
both of which are provably secure[13]. In any event,
Crypt::RSA::Primitives (without padding) should never be used directly.
That said, there exists a scheme called Simple RSA[16] that provides
security without padding. However, Crypt::RSA doesn't implement this
scheme yet.
=head1 METHODS
=over 4
=item B<new()>
The constructor. When no arguments are provided, new() returns an object
loaded with default values. This object can be customized by specifying
encryption & signature schemes, key formats and post processors. For
details see the section on B<Customizing the Crypt::RSA
object> later in this manpage.
=item B<keygen()>
keygen() generates and returns an RSA key-pair of specified bitsize.
keygen() is a synonym for Crypt::RSA::Key::generate(). Parameters and
return values are described in the Crypt::RSA::Key(3) manpage.
=item B<encrypt()>
encrypt() performs RSA encryption on a string of arbitrary length with a
public key using the encryption scheme bound to the object. The default
scheme is OAEP. encrypt() returns cyphertext (a string) on success and
undef on failure. It takes a hash as argument with following keys:
=over 4
=item B<Message>
An arbitrary length string to be encrypted.
=item B<Key>
Public key of the recipient, a Crypt::RSA::Key::Public(3) or
compatible object.
=item B<Armour>
A boolean parameter that forces cyphertext through a post processor after
encrpytion. The default post processor is Convert::ASCII::Armour(3) that
encodes binary octets in 6-bit clean ASCII messages. The cyphertext is
returned as-is, when the Armour key is not present.
=back
=item B<decrypt()>
decrypt() performs RSA decryption with a private key using the encryption
scheme bound to the object. The default scheme is OAEP. decrypt() returns
plaintext on success and undef on failure. It takes a hash as argument
with following keys:
=over 4
=item B<Cyphertext>
Cyphertext of arbitrary length.
=item B<Key>
Private key, a Crypt::RSA::Key::Private(3) or compatible object.
=item B<Armour>
Boolean parameter that specifies whether the Cyphertext is encoded with a
post processor.
=back
=item B<sign()>
sign() creates an RSA signature on a string with a private key using the
signature scheme bound to the object. The default scheme is
PSS. sign() returns a signature on success and undef on failure. It takes
a hash as argument with following keys:
=over 4
=item B<Message>
A string of arbitrary length to be signed.
=item B<Key>
Private key of the sender, a Crypt::RSA::Key::Private(3) or
compatible object.
=item B<Armour>
A boolean parameter that forces the computed signature to be post
processed.
=back
=item B<verify()>
verify() verifies an RSA signature with a public key using the signature
scheme bound to the object. The default scheme is PSS. verify() returns a
true value on success and undef on failure. It takes a hash as argument
with following keys:
=over 4
=item B<Message>
A signed message, a string of arbitrary length.
=item B<Key>
Public key of the signer, a Crypt::RSA::Key::Public(3) or
compatible object.
=item B<Sign>
A signature computed with sign().
=item B<Armour>
Boolean parameter that specifies whether the Signature has been
post processed.
=back
=back
=head1 MODULES
Apart from Crypt::RSA, the following modules are intended for application
developer and end-user consumption:
=over 4
=item B<Crypt::RSA::Key>
RSA key pair generator.
=item B<Crypt::RSA::Key::Public>
RSA Public Key Management.
=item B<Crypt::RSA::Key::Private>
RSA Private Key Management.
=item B<Crypt::RSA::ES::OAEP>
Plaintext-aware encryption with RSA.
=item B<Crypt::RSA::SS::PSS>
Probabilistic Signature Scheme based on RSA.
=item B<Crypt::RSA::ES::PKCS1v15>
PKCS #1 v1.5 encryption scheme.
=item B<Crypt::RSA::SS::PKCS1v15>
PKCS #1 v1.5 signature scheme.
=back
=head1 CUSTOMISING A CRYPT::RSA OBJECT
A Crypt::RSA object can be customized by passing any of the following keys
in a hash to new(): ES to specify the encryption scheme, SS to specify the
signature scheme, PP to specify the post processor, and KF to specify the
key format. The value associated with these keys can either be a name (a
string) or a hash reference that specifies a module name, its constructor,
and constructor arguments. For example:
my $rsa = new Crypt::RSA ( ES => 'OAEP' );
or
my $rsa = new Crypt::RSA ( ES => { Module => 'Crypt::RSA::ES::OAEP' } );
A module thus specified need not be included in the Crypt::RSA bundle, but
it must be interface compatible with the ones provided with Crypt::RSA.
As of this writing, the following names are recognised:
=over 4
=item B<ES> (Encryption Scheme)
'OAEP', 'PKCS1v15'
=item B<SS> (Signature Scheme)
'PSS', 'PKCS1v15'
=item B<KF> (Key Format)
'Native', 'SSH'
=item B<PP> (Post Processor)
'ASCII'
=back
=head1 ERROR HANDLING
All modules in the Crypt::RSA bundle use a common error handling method
(implemented in Crypt::RSA::Errorhandler(3)). When a method fails it
returns undef and calls $self->error() with the error message. This error
message is available to the caller through the errstr() method. For more
details see the Crypt::RSA::Errorhandler(3) manpage.
=head1 AUTHOR
Vipul Ved Prakash, E<lt>mail@vipul.netE<gt>
=head1 ACKNOWLEDGEMENTS
Thanks to Ilya Zakharevich for help with Math::Pari, Benjamin Trott for
several patches including SSH key support, Genèche Ramanoudjame for
extensive testing and numerous bug reports, Shizukesa on #perl for
suggesting the error handling method used in this module, and Dave Paris
for good advice.
=head1 LICENSE
Copyright (c) 2000-2008, Vipul Ved Prakash. This code is free software;
it is distributed under the same license as Perl itself.
I have received requests for commercial licenses of
Crypt::RSA, from those who desire contractual support and
indemnification. I'd be happy to provide a commercial license
if you need one. Please send me mail at C<mail@vipul.net> with
the subject "Crypt::RSA license". Please don't send me mail
asking if you need a commercial license. You don't, if
Artistic of GPL suit you fine.
=head1 SEE ALSO
Crypt::RSA::Primitives(3), Crypt::RSA::DataFormat(3),
Crypt::RSA::Errorhandler(3), Crypt::RSA::Debug(3), Crypt::Primes(3),
Crypt::Random(3), Crypt::CBC(3), Crypt::Blowfish(3),
Tie::EncryptedHash(3), Convert::ASCII::Armour(3), Math::Pari(3),
Class::Loader(3), crypt-rsa-interoperability(3),
crypt-rsa-interoperability-table(3).
=head1 REPORTING BUGS
All bug reports related to Crypt::RSA should go to rt.cpan.org
at C<http://rt.cpan.org/Dist/Display.html?Queue=Crypt-RSA>
Crypt::RSA is considered to be stable. If you are running into a
problem, it's likely of your own making. Please check your code
and consult the documentation before posting a bug report. A
google search with the error message might also shed light if it
is a common mistake that you've made.
If the module installation fails with a "Segmentation Fault" or
"Bus Error", it is likely a Math::Pari issue. Please consult
Math::Pari bugs on rt.cpan.org or open a bug there. There have
been known issues on HP-UX and SunOS systems (with Math::Pari),
so if you are on those OSes, please consult Math::Pari
resources before opening a Crypt::RSA bug.
=head1 BIBLIOGRAPHY
Chronologically sorted (for the most part).
=over 4
=item 1 B<R. Rivest, A. Shamir, L. Aldeman.> A Method for Obtaining Digital Signatures and Public-Key Cryptosystems (1978).
=item 2 B<U. Maurer.> Fast Generation of Prime Numbers and Secure Public-Key Cryptographic Parameters (1994).
=item 3 B<M. Bellare, P. Rogaway.> Optimal Asymmetric Encryption - How to Encrypt with RSA (1995).
=item 4 B<M. Bellare, P. Rogaway.> The Exact Security of Digital Signatures - How to sign with RSA and Rabin (1996).
=item 5 B<B. Schneier.> Applied Cryptography, Second Edition (1996).
=item 6 B<A. Menezes, P. Oorschot, S. Vanstone.> Handbook of Applied Cryptography (1997).
=item 7 B<D. Boneh.> Twenty Years of Attacks on the RSA Cryptosystem (1998).
=item 8 B<D. Bleichenbacher, M. Joye, J. Quisquater.> A New and Optimal Chosen-message Attack on RSA-type Cryptosystems (1998).
=item 9 B<B. Kaliski, J. Staddon.> Recent Results on PKCS #1: RSA Encryption Standard, RSA Labs Bulletin Number 7 (1998).
=item 10 B<B. Kaliski, J. Staddon.> PKCS #1: RSA Cryptography Specifications v2.0, RFC 2437 (1998).
=item 11 B<SSH Communications Security.> SSH 1.2.7 source code (1998).
=item 12 B<S. Simpson.> PGP DH vs. RSA FAQ v1.5 (1999).
=item 13 B<RSA Laboratories.> Draft I, PKCS #1 v2.1: RSA Cryptography Standard (1999).
=item 14 B<E. Young, T. Hudson, OpenSSL Team.> OpenSSL 0.9.5a source code (2000).
=item 15 B<Several Authors.> The sci.crypt FAQ at
http://www.faqs.org/faqs/cryptography-faq/part01/index.html
=item 16 B<Victor Shoup.> A Proposal for an ISO Standard for Public Key Encryption (2001).
=cut
|