Initial Commit
This commit is contained in:
205
database/perl/vendor/lib/Crypt/RSA/DataFormat.pm
vendored
Normal file
205
database/perl/vendor/lib/Crypt/RSA/DataFormat.pm
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
package Crypt::RSA::DataFormat;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
## Crypt::RSA::DataFormat -- Functions for converting, shaping and
|
||||
## creating and reporting data formats.
|
||||
##
|
||||
## Copyright (c) 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.
|
||||
|
||||
use vars qw(@ISA);
|
||||
use Math::BigInt try => 'GMP, Pari';
|
||||
use Math::Prime::Util qw/random_bytes/;
|
||||
use Digest::SHA qw(sha1);
|
||||
use Carp;
|
||||
|
||||
use base qw(Exporter);
|
||||
our @EXPORT_OK = qw(i2osp os2ip h2osp octet_xor octet_len bitsize
|
||||
generate_random_octet mgf1 steak);
|
||||
|
||||
|
||||
sub i2osp {
|
||||
my ($num, $l) = @_;
|
||||
$num = 0 if !defined $num;
|
||||
$l = 0 if !defined $l;
|
||||
my $result;
|
||||
|
||||
if (ref($num) ne 'Math::BigInt' && $num <= ~0) {
|
||||
$result = '';
|
||||
do {
|
||||
$result = chr($num & 0xFF) . $result;
|
||||
$num >>= 8;
|
||||
} while $num;
|
||||
} else {
|
||||
$num = Math::BigInt->new("$num") unless ref($num) eq 'Math::BigInt';
|
||||
my $hex = $num->as_hex;
|
||||
# Remove the 0x and any leading zeros (shouldn't be any)
|
||||
$hex =~ s/^0x0*//;
|
||||
# Add a leading zero if needed to line up bytes correctly.
|
||||
substr($hex, 0, 0, '0') if length($hex) % 2;
|
||||
# Pack hex string into a octet string.
|
||||
$result = pack("H*", $hex);
|
||||
}
|
||||
|
||||
if ($l) {
|
||||
my $rlen = length($result);
|
||||
# Return undef if too large to fit
|
||||
return if $l < $rlen;
|
||||
# Zero pad the front if they want a longer string
|
||||
substr( $result, 0, 0, chr(0) x ($l-$rlen) ) if $rlen < $l;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
sub os2ip {
|
||||
my $string = shift;
|
||||
my($hex) = unpack('H*', $string);
|
||||
return Math::BigInt->new("0x$hex");
|
||||
}
|
||||
|
||||
|
||||
sub h2osp {
|
||||
my $hex = shift;
|
||||
$hex =~ s/\s//g;
|
||||
$hex =~ s/^0x0*//;
|
||||
# Add a leading zero if needed to line up bytes correctly.
|
||||
substr($hex, 0, 0, '0') if length($hex) % 2;
|
||||
# Pack into a string.
|
||||
my $result = pack("H*", $hex);
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
sub generate_random_octet {
|
||||
my $l = shift; # Ignore the strength parameter, if any
|
||||
return random_bytes($l);
|
||||
}
|
||||
|
||||
|
||||
sub bitsize {
|
||||
my $n = shift;
|
||||
my $bits = 0;
|
||||
if (ref($n) eq 'Math::BigInt') {
|
||||
$bits = length($n->as_bin) - 2;
|
||||
} else {
|
||||
while ($n) { $bits++; $n >>= 1; }
|
||||
}
|
||||
$bits;
|
||||
}
|
||||
|
||||
|
||||
sub octet_len {
|
||||
return int( (bitsize(shift) + 7) / 8 );
|
||||
}
|
||||
|
||||
|
||||
# This could be made even faster doing 4 bytes at a time
|
||||
sub octet_xor {
|
||||
my ($a, $b) = @_;
|
||||
|
||||
# Ensure length($a) >= length($b)
|
||||
($a, $b) = ($b, $a) if length($b) > length($a);
|
||||
my $alen = length($a);
|
||||
# Prepend null bytes to the beginning of $b to make the lengths equal
|
||||
substr($b, 0, 0, chr(0) x ($alen-length($b))) if $alen > length($b);
|
||||
|
||||
# xor all bytes
|
||||
my $r = '';
|
||||
$r .= chr( ord(substr($a,$_,1)) ^ ord(substr($b,$_,1)) ) for 0 .. $alen-1;
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
||||
# http://rfc-ref.org/RFC-TEXTS/3447/chapter11.html
|
||||
sub mgf1 {
|
||||
my ($seed, $l) = @_;
|
||||
my $hlen = 20; # SHA-1 is 160 bits
|
||||
my $imax = int(($l + $hlen - 1) / $hlen) - 1;
|
||||
my $T = "";
|
||||
foreach my $i (0 .. $imax) {
|
||||
$T .= sha1($seed . i2osp ($i, 4));
|
||||
}
|
||||
my ($output) = unpack "a$l", $T;
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
sub steak {
|
||||
my ($text, $blocksize) = @_;
|
||||
my $textsize = length($text);
|
||||
my $chunkcount = $textsize % $blocksize
|
||||
? int($textsize/$blocksize) + 1 : $textsize/$blocksize;
|
||||
my @segments = unpack "a$blocksize"x$chunkcount, $text;
|
||||
return @segments;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Crypt::RSA::DataFormat - Data creation, conversion and reporting primitives.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module implements several data creation, conversion and reporting
|
||||
primitives used throughout the Crypt::RSA implementation. Primitives are
|
||||
available as exportable functions.
|
||||
|
||||
=head1 FUNCTIONS
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<i2osp> Integer, Length
|
||||
|
||||
Integer To Octet String Primitive. Converts an integer into its
|
||||
equivalent octet string representation of length B<Length>. If
|
||||
necessary, the resulting string is prefixed with nulls. If
|
||||
B<Length> is not provided, returns an octet string of shortest
|
||||
possible length.
|
||||
|
||||
=item B<h2osp> Hex String
|
||||
|
||||
Hex To Octet String Primitive. Converts a I<hex string> into its
|
||||
equivalent octet string representation and returns an octet
|
||||
string of shortest possible length. The hex string is not
|
||||
prefixed with C<0x>, etc.
|
||||
|
||||
=item B<os2ip> String
|
||||
|
||||
Octet String to Integer Primitive. Converts an octet string into its
|
||||
equivalent integer representation.
|
||||
|
||||
=item B<generate_random_octet> Length
|
||||
|
||||
Generates a random octet string of length B<Length>.
|
||||
|
||||
=item B<bitsize> Integer
|
||||
|
||||
Returns the length of the B<Integer> in bits.
|
||||
|
||||
=item B<octet_len> Integer
|
||||
|
||||
Returns the octet length of the integer. If the length is not a whole
|
||||
number, the fractional part is dropped to make it whole.
|
||||
|
||||
=item B<octet_xor> String1, String2
|
||||
|
||||
Returns the result of B<String1> XOR B<String2>.
|
||||
|
||||
=item B<steak> String, Length
|
||||
|
||||
Returns an array of segments of length B<Length> from B<String>. The final
|
||||
segment can be smaller than B<Length>.
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Vipul Ved Prakash, E<lt>mail@vipul.netE<gt>
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
82
database/perl/vendor/lib/Crypt/RSA/Debug.pm
vendored
Normal file
82
database/perl/vendor/lib/Crypt/RSA/Debug.pm
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
package Crypt::RSA::Debug;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
## Crypt::RSA::Debug
|
||||
##
|
||||
## Copyright (c) 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.
|
||||
|
||||
use vars qw(@ISA @EXPORT_OK);
|
||||
require Exporter;
|
||||
@ISA = qw(Exporter);
|
||||
|
||||
@EXPORT_OK = qw(debug debuglevel);
|
||||
|
||||
my $DEBUG = 0;
|
||||
|
||||
sub debug{
|
||||
return unless $DEBUG;
|
||||
my ($caller, undef) = caller;
|
||||
my (undef,undef,$line,$sub) = caller(1); $sub =~ s/.*://;
|
||||
$sub = sprintf "%12s()%4d", $sub, $line;
|
||||
$sub .= " | " . (shift);
|
||||
$sub =~ s/\x00/[0]/g;
|
||||
$sub =~ s/\x01/[1]/g;
|
||||
$sub =~ s/\x02/[2]/g;
|
||||
$sub =~ s/\x04/[4]/g;
|
||||
$sub =~ s/\x05/[5]/g;
|
||||
$sub =~ s/\xff/[-]/g;
|
||||
$sub =~ s/[\x00-\x1f]/\./g;
|
||||
$sub =~ s/[\x7f-\xfe]/_/g;
|
||||
print "$sub\n";
|
||||
}
|
||||
|
||||
|
||||
sub debuglevel {
|
||||
|
||||
my ($level) = shift;
|
||||
$DEBUG = $level;
|
||||
|
||||
}
|
||||
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Crypt::RSA::Debug - Debug routine for Crypt::RSA.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Crypt::RSA::Debug qw(debug);
|
||||
debug ("oops!");
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The module provides support for the I<print> method of debugging!
|
||||
|
||||
=head1 FUNCTION
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<debug> String
|
||||
|
||||
Prints B<String> on STDOUT, along with caller's function name and line number.
|
||||
|
||||
=item B<debuglevel> Integer
|
||||
|
||||
Sets the class data I<debuglevel> to specified value. The value
|
||||
defaults to 0. Callers can use the debuglevel facility by
|
||||
comparing $Crypt::RSA::DEBUG to the desired debug level before
|
||||
generating a debug statement.
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Vipul Ved Prakash, E<lt>mail@vipul.netE<gt>
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
||||
|
||||
286
database/perl/vendor/lib/Crypt/RSA/ES/OAEP.pm
vendored
Normal file
286
database/perl/vendor/lib/Crypt/RSA/ES/OAEP.pm
vendored
Normal file
@@ -0,0 +1,286 @@
|
||||
package Crypt::RSA::ES::OAEP;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
## Crypt::RSA::ES::OAEP
|
||||
##
|
||||
## Copyright (c) 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.
|
||||
|
||||
use base 'Crypt::RSA::Errorhandler';
|
||||
use Math::Prime::Util qw/random_bytes/;
|
||||
use Crypt::RSA::DataFormat qw(bitsize os2ip i2osp octet_xor mgf1 octet_len);
|
||||
use Crypt::RSA::Primitives;
|
||||
use Crypt::RSA::Debug qw(debug);
|
||||
use Digest::SHA qw(sha1);
|
||||
use Sort::Versions qw(versioncmp);
|
||||
use Carp;
|
||||
|
||||
$Crypt::RSA::ES::OAEP::VERSION = '1.99';
|
||||
|
||||
sub new {
|
||||
my ($class, %params) = @_;
|
||||
my $self = bless { primitives => new Crypt::RSA::Primitives,
|
||||
P => "",
|
||||
hlen => 20,
|
||||
VERSION => $Crypt::RSA::ES::OAEP::VERSION,
|
||||
}, $class;
|
||||
if ($params{Version}) {
|
||||
if (versioncmp($params{Version}, '1.15') == -1) {
|
||||
$$self{P} = "Crypt::RSA";
|
||||
$$self{VERSION} = $params{Version};
|
||||
} elsif (versioncmp($params{Version}, $$self{VERSION}) == 1) {
|
||||
croak "Required version ($params{Version}) greater than installed version ($$self{VERSION}) of $class.\n";
|
||||
}
|
||||
}
|
||||
return $self;
|
||||
}
|
||||
|
||||
|
||||
sub encrypt {
|
||||
my ($self, %params) = @_;
|
||||
my $key = $params{Key}; my $M = $params{Message} || $params{Plaintext};
|
||||
return $self->error ("Missing Message or Plaintext parameter", \$key, \%params) unless $M;
|
||||
return $self->error ($key->errstr, \$M, $key, \%params) unless $key->check;
|
||||
my $k = octet_len ($key->n); debug ("octet_len of modulus: $k");
|
||||
my $em = $self->encode ($M, $self->{P}, $k-1) ||
|
||||
return $self->error ($self->errstr, \$M, $key, \%params);
|
||||
my $m = os2ip ($em);
|
||||
my $c = $self->{primitives}->core_encrypt ( Plaintext => $m, Key => $key );
|
||||
my $ec = i2osp ($c, $k); debug ("ec: $ec");
|
||||
return $ec;
|
||||
}
|
||||
|
||||
|
||||
sub decrypt {
|
||||
my ($self, %params) = @_;
|
||||
my $key = $params{Key}; my $C = $params{Cyphertext} || $params{Ciphertext};
|
||||
return $self->error ("Missing Cyphertext or Ciphertext parameter", \$key, \%params) unless $C;
|
||||
return $self->error ($key->errstr, $key, \%params) unless $key->check;
|
||||
my $k = octet_len ($key->n);
|
||||
my $c = os2ip ($C);
|
||||
if (bitsize($c) > bitsize($key->n)) {
|
||||
return $self->error ("Decryption error.", $key, \%params)
|
||||
}
|
||||
my $m = $self->{primitives}->core_decrypt (Cyphertext => $c, Key => $key) ||
|
||||
return $self->error ("Decryption error.", $key, \%params);
|
||||
my $em = i2osp ($m, $k-1) ||
|
||||
return $self->error ("Decryption error.", $key, \%params);
|
||||
my $M; $self->errstrrst; # reset the errstr
|
||||
unless ($M = $self->decode ($em, $$self{P})) {
|
||||
return $self->error ("Decryption error.", $key, \%params) if $self->errstr();
|
||||
return $M;
|
||||
}
|
||||
return $M;
|
||||
}
|
||||
|
||||
|
||||
sub encode {
|
||||
my ($self, $M, $P, $emlen) = @_;
|
||||
my $hlen = $$self{hlen};
|
||||
my $mlen = length($M);
|
||||
return $self->error ("Message too long.", \$P, \$M) if $mlen > $emlen-(2*$hlen)-1;
|
||||
my ($PS, $pslen) = ("", 0);
|
||||
if ($pslen = $emlen-(2*$hlen+1+$mlen)) {
|
||||
$PS = chr(0)x$pslen;
|
||||
}
|
||||
my $phash = $self->hash ($P);
|
||||
my $db = $phash . $PS . chr(1) . $M;
|
||||
my $seed = random_bytes($hlen);
|
||||
my $dbmask = $self->mgf ($seed, $emlen-$hlen);
|
||||
my $maskeddb = octet_xor ($db, $dbmask);
|
||||
my $seedmask = $self->mgf ($maskeddb, $hlen);
|
||||
my $maskedseed = octet_xor ($seed, $seedmask);
|
||||
my $em = $maskedseed . $maskeddb;
|
||||
|
||||
debug ("emlen == $emlen");
|
||||
debug ("M == $M [" . length($M) . "]");
|
||||
debug ("PS == $PS [$pslen]");
|
||||
debug ("phash == $phash [" . length($phash) . "]");
|
||||
debug ("seed == $seed [" . length($seed) . "]");
|
||||
debug ("seedmask == $seedmask [" . length($seedmask) . "]");
|
||||
debug ("db == $db [" . length($db) . "]");
|
||||
debug ("dbmask == $dbmask [" . length($dbmask) . "]");
|
||||
debug ("maskeddb == $maskeddb [" . length($maskeddb) . "]");
|
||||
debug ("em == $em [" . length($em) . "]");
|
||||
|
||||
return $em;
|
||||
}
|
||||
|
||||
|
||||
sub decode {
|
||||
my ($self, $em, $P) = @_;
|
||||
my $hlen = $$self{hlen};
|
||||
|
||||
debug ("P == $P");
|
||||
return $self->error ("Decoding error.", \$P) if length($em) < 2*$hlen+1;
|
||||
my $maskedseed = substr $em, 0, $hlen;
|
||||
my $maskeddb = substr $em, $hlen;
|
||||
my $seedmask = $self->mgf ($maskeddb, $hlen);
|
||||
my $seed = octet_xor ($maskedseed, $seedmask);
|
||||
my $dbmask = $self->mgf ($seed, length($em) - $hlen);
|
||||
my $db = octet_xor ($maskeddb, $dbmask);
|
||||
my $phash = $self->hash ($P);
|
||||
|
||||
debug ("em == $em [" . length($em) . "]");
|
||||
debug ("phash == $phash [" . length($phash) . "]");
|
||||
debug ("seed == $seed [" . length($seed) . "]");
|
||||
debug ("seedmask == $seedmask [" . length($seedmask) . "]");
|
||||
debug ("maskedseed == $maskedseed [" . length($maskedseed) . "]");
|
||||
debug ("db == $db [" . length($db) . "]");
|
||||
debug ("maskeddb == $maskeddb [" . length($maskeddb) . "]");
|
||||
debug ("dbmask == $dbmask [" . length($dbmask) . "]");
|
||||
|
||||
my ($phashorig) = substr $db, 0, $hlen;
|
||||
debug ("phashorig == $phashorig [" . length($phashorig) . "]");
|
||||
return $self->error ("Decoding error.", \$P) unless $phashorig eq $phash;
|
||||
$db = substr $db, $hlen;
|
||||
my ($chr0, $chr1) = (chr(0), chr(1));
|
||||
my ($ps, $m);
|
||||
debug ("db == $db [" . length($db) . "]");
|
||||
unless ( ($ps, undef, $m) = $db =~ /^($chr0*)($chr1)(.*)$/s ) {
|
||||
return $self->error ("Decoding error.", \$P);
|
||||
}
|
||||
|
||||
return $m;
|
||||
}
|
||||
|
||||
|
||||
sub hash {
|
||||
my ($self, $data) = @_;
|
||||
return sha1 ($data);
|
||||
}
|
||||
|
||||
|
||||
sub mgf {
|
||||
my ($self, @data) = @_;
|
||||
return mgf1 (@data);
|
||||
}
|
||||
|
||||
|
||||
sub encryptblock {
|
||||
my ($self, %params) = @_;
|
||||
return octet_len ($params{Key}->n) - 42;
|
||||
}
|
||||
|
||||
|
||||
sub decryptblock {
|
||||
my ($self, %params) = @_;
|
||||
return octet_len ($params{Key}->n);
|
||||
}
|
||||
|
||||
|
||||
# should be able to call this as a class method.
|
||||
sub version {
|
||||
my $self = shift;
|
||||
return $self->{VERSION};
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Crypt::RSA::ES::OAEP - Plaintext-aware encryption with RSA.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $oaep = new Crypt::RSA::ES::OAEP;
|
||||
|
||||
my $ct = $oaep->encrypt( Key => $key, Message => $message ) ||
|
||||
die $oaep->errstr;
|
||||
|
||||
my $pt = $oaep->decrypt( Key => $key, Cyphertext => $ct ) ||
|
||||
die $oaep->errstr;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module implements Optimal Asymmetric Encryption, a plaintext-aware
|
||||
encryption scheme based on RSA. The notion of plaintext-aware implies it's
|
||||
computationally infeasible to obtain full or partial information about a
|
||||
message from a cyphertext, and computationally infeasible to generate a
|
||||
valid cyphertext without knowing the corresponding message.
|
||||
Plaintext-aware schemes, such as OAEP, are semantically secure,
|
||||
non-malleable and secure against chosen-ciphertext attack. For more
|
||||
information on OAEP and plaintext-aware encryption, see [3], [9] & [13].
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 B<new()>
|
||||
|
||||
Constructor.
|
||||
|
||||
=head2 B<version()>
|
||||
|
||||
Returns the version number of the module.
|
||||
|
||||
=head2 B<encrypt()>
|
||||
|
||||
Encrypts a string with a public key and returns the encrypted string
|
||||
on success. encrypt() takes a hash argument with the following
|
||||
mandatory keys:
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<Message>
|
||||
|
||||
A string to be encrypted. The length of this string should not exceed k-42
|
||||
octets, where k is the octet length of the RSA modulus. If Message is
|
||||
longer than k-42, the method will fail and set $self->errstr to "Message
|
||||
too long." This means the key must be at least _336_ bits long if you are
|
||||
to use OAEP.
|
||||
|
||||
=item B<Key>
|
||||
|
||||
Public key of the recipient, a Crypt::RSA::Key::Public object.
|
||||
|
||||
=back
|
||||
|
||||
=head2 B<decrypt()>
|
||||
|
||||
Decrypts cyphertext with a private key and returns plaintext on
|
||||
success. $self->errstr is set to "Decryption Error." or appropriate
|
||||
error on failure. decrypt() takes a hash argument with the following
|
||||
mandatory keys:
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<Cyphertext>
|
||||
|
||||
A string encrypted with encrypt(). The length of the cyphertext must be k
|
||||
octets, where k is the length of the RSA modulus.
|
||||
|
||||
=item B<Key>
|
||||
|
||||
Private key of the receiver, a Crypt::RSA::Key::Private object.
|
||||
|
||||
=item B<Version>
|
||||
|
||||
Version of the module that was used for creating the Cyphertext. This is
|
||||
an optional argument. When present, decrypt() will ensure before
|
||||
proceeding that the installed version of the module can successfully
|
||||
decrypt the Cyphertext.
|
||||
|
||||
=back
|
||||
|
||||
=head1 ERROR HANDLING
|
||||
|
||||
See ERROR HANDLING in Crypt::RSA(3) manpage.
|
||||
|
||||
=head1 BIBLIOGRAPHY
|
||||
|
||||
See BIBLIOGRAPHY in Crypt::RSA(3) manpage.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Vipul Ved Prakash, E<lt>mail@vipul.netE<gt>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Crypt::RSA(3), Crypt::RSA::Primitives(3), Crypt::RSA::Keys(3),
|
||||
Crypt::RSA::SSA::PSS(3)
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
215
database/perl/vendor/lib/Crypt/RSA/ES/PKCS1v15.pm
vendored
Normal file
215
database/perl/vendor/lib/Crypt/RSA/ES/PKCS1v15.pm
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
package Crypt::RSA::ES::PKCS1v15;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
## Crypt::RSA::ES::PKCS1v15
|
||||
##
|
||||
## Copyright (c) 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.
|
||||
|
||||
use base 'Crypt::RSA::Errorhandler';
|
||||
use Math::Prime::Util qw/random_bytes/;
|
||||
use Crypt::RSA::DataFormat qw(bitsize octet_len os2ip i2osp);
|
||||
use Crypt::RSA::Primitives;
|
||||
use Crypt::RSA::Debug qw(debug);
|
||||
use Carp;
|
||||
|
||||
$Crypt::RSA::ES::PKCS1v15::VERSION = '1.99';
|
||||
|
||||
sub new {
|
||||
my ($class, %params) = @_;
|
||||
my $self = bless { primitives => new Crypt::RSA::Primitives,
|
||||
VERSION => $Crypt::RSA::ES::PKCS1v15::VERSION,
|
||||
}, $class;
|
||||
if ($params{Version}) {
|
||||
# do versioning here.
|
||||
}
|
||||
return $self;
|
||||
}
|
||||
|
||||
|
||||
sub encrypt {
|
||||
my ($self, %params) = @_;
|
||||
my $key = $params{Key}; my $M = $params{Message} || $params{Plaintext};
|
||||
return $self->error ("No Message or Plaintext parameter", \$key, \%params) unless $M;
|
||||
return $self->error ($key->errstr, \$M, $key, \%params) unless $key->check;
|
||||
my $k = octet_len ($key->n); debug ("octet_len of modulus: $k");
|
||||
my $em = $self->encode ($M, $k-1) ||
|
||||
return $self->error ($self->errstr, \$M, $key, \%params);
|
||||
debug ("encoded: $em");
|
||||
my $m = os2ip ($em);
|
||||
my $c = $self->{primitives}->core_encrypt (Plaintext => $m, Key => $key);
|
||||
my $ec = i2osp ($c, $k); debug ("cyphertext: $ec");
|
||||
return $ec;
|
||||
}
|
||||
|
||||
|
||||
sub decrypt {
|
||||
my ($self, %params) = @_;
|
||||
my $key = $params{Key}; my $C = $params{Cyphertext} || $params{Ciphertext};
|
||||
return $self->error ("No Cyphertext or Ciphertext parameter", \$key, \%params) unless $C;
|
||||
return $self->error ($key->errstr, $key, \%params) unless $key->check;
|
||||
my $k = octet_len ($key->n);
|
||||
my $c = os2ip ($C);
|
||||
debug ("bitsize(c): " . bitsize($c));
|
||||
debug ("bitsize(n): " . bitsize($key->n));
|
||||
if (bitsize($c) > bitsize($key->n)) {
|
||||
return $self->error ("Decryption error.", $key, \%params)
|
||||
}
|
||||
my $m = $self->{primitives}->core_decrypt (Cyphertext => $c, Key => $key) ||
|
||||
return $self->error ("Decryption error.", $key, \%params);
|
||||
my $em = i2osp ($m, $k-1) ||
|
||||
return $self->error ("Decryption error.", $key, \%params);
|
||||
my $M; $self->errstrrst; # reset the errstr
|
||||
unless ($M = $self->decode ($em)) {
|
||||
return $self->error ("Decryption error.", $key, \%params) if $self->errstr();
|
||||
return $M;
|
||||
}
|
||||
return $M;
|
||||
}
|
||||
|
||||
|
||||
sub encode {
|
||||
my ($self, $M, $emlen) = @_;
|
||||
$M = $M || ""; my $mlen = length($M);
|
||||
return $self->error ("Message too long.", \$M) if $mlen > $emlen-10;
|
||||
|
||||
my $pslen = $emlen-$mlen-2;
|
||||
# my $PS = join('', map { chr( 1+urandomm(255) ) } 1 .. $pslen);
|
||||
my $PS = '';
|
||||
while (length($PS) < $pslen) {
|
||||
$PS .= random_bytes( $pslen - length($PS) );
|
||||
$PS =~ s/\x00//g;
|
||||
}
|
||||
my $em = chr(2).$PS.chr(0).$M;
|
||||
return $em;
|
||||
}
|
||||
|
||||
|
||||
sub decode {
|
||||
my ($self, $em) = @_;
|
||||
|
||||
return $self->error ("Decoding error.") if length($em) < 10;
|
||||
|
||||
debug ("to decode: $em");
|
||||
my ($chr0, $chr2) = (chr(0), chr(2));
|
||||
my ($ps, $M);
|
||||
unless ( ($ps, $M) = $em =~ /^$chr2(.*?)$chr0(.*)$/s ) {
|
||||
return $self->error ("Decoding error.");
|
||||
}
|
||||
return $self->error ("Decoding error.") if length($ps) < 8;
|
||||
return $M;
|
||||
}
|
||||
|
||||
|
||||
sub encryptblock {
|
||||
my ($self, %params) = @_;
|
||||
return octet_len ($params{Key}->n) - 11;
|
||||
}
|
||||
|
||||
|
||||
sub decryptblock {
|
||||
my ($self, %params) = @_;
|
||||
return octet_len ($params{Key}->n);
|
||||
}
|
||||
|
||||
|
||||
sub version {
|
||||
my $self = shift;
|
||||
return $self->{VERSION};
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Crypt::RSA::ES::PKCS1v15 - PKCS #1 v1.5 padded encryption scheme based on RSA.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $pkcs = new Crypt::RSA::ES::PKCS1v15;
|
||||
|
||||
my $ct = $pkcs->encrypt( Key => $key, Message => $message ) ||
|
||||
die $pkcs->errstr;
|
||||
|
||||
my $pt = $pkcs->decrypt( Key => $key, Cyphertext => $ct ) ||
|
||||
die $pkcs->errstr;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module implements PKCS #1 v1.5 padded encryption scheme based on RSA.
|
||||
See [13] for details on the encryption scheme.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 B<new()>
|
||||
|
||||
Constructor.
|
||||
|
||||
=head2 B<version()>
|
||||
|
||||
Returns the version number of the module.
|
||||
|
||||
=head2 B<encrypt()>
|
||||
|
||||
Encrypts a string with a public key and returns the encrypted string
|
||||
on success. encrypt() takes a hash argument with the following
|
||||
mandatory keys:
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<Message>
|
||||
|
||||
A string to be encrypted. The length of this string should not exceed k-10
|
||||
octets, where k is the octet length of the RSA modulus. If Message is
|
||||
longer than k-10, the method will fail and set $self->errstr to "Message
|
||||
too long."
|
||||
|
||||
=item B<Key>
|
||||
|
||||
Public key of the recipient, a Crypt::RSA::Key::Public object.
|
||||
|
||||
=back
|
||||
|
||||
=head2 B<decrypt()>
|
||||
|
||||
Decrypts cyphertext with a private key and returns plaintext on
|
||||
success. $self->errstr is set to "Decryption Error." or appropriate
|
||||
error on failure. decrypt() takes a hash argument with the following
|
||||
mandatory keys:
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<Cyphertext>
|
||||
|
||||
A string encrypted with encrypt(). The length of the cyphertext must be k
|
||||
octets, where k is the length of the RSA modulus.
|
||||
|
||||
=item B<Key>
|
||||
|
||||
Private key of the receiver, a Crypt::RSA::Key::Private object.
|
||||
|
||||
=back
|
||||
|
||||
=head1 ERROR HANDLING
|
||||
|
||||
See ERROR HANDLING in Crypt::RSA(3) manpage.
|
||||
|
||||
=head1 BIBLIOGRAPHY
|
||||
|
||||
See BIBLIOGRAPHY in Crypt::RSA(3) manpage.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Vipul Ved Prakash, E<lt>mail@vipul.netE<gt>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Crypt::RSA(3), Crypt::RSA::Primitives(3), Crypt::RSA::Keys(3),
|
||||
Crypt::RSA::SSA::PSS(3)
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
132
database/perl/vendor/lib/Crypt/RSA/Errorhandler.pm
vendored
Normal file
132
database/perl/vendor/lib/Crypt/RSA/Errorhandler.pm
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
package Crypt::RSA::Errorhandler;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
## Crypt::RSA::Errorhandler -- Base class that provides error
|
||||
## handling functionality.
|
||||
##
|
||||
## Copyright (c) 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.
|
||||
|
||||
sub new {
|
||||
bless {}, shift
|
||||
}
|
||||
|
||||
|
||||
sub error {
|
||||
my ($self, $errstr, @towipe) = @_;
|
||||
$$self{errstr} = "$errstr\n";
|
||||
for (@towipe) {
|
||||
my $var = $_;
|
||||
if (ref($var) =~ /Crypt::RSA/) {
|
||||
$var->DESTROY();
|
||||
} elsif (ref($var) eq "SCALAR") {
|
||||
$$var = "";
|
||||
} elsif (ref($var) eq "ARRAY") {
|
||||
@$var = ();
|
||||
} elsif (ref($var) eq "HASH") {
|
||||
%$var = ();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
sub errstr {
|
||||
my $self = shift;
|
||||
return $$self{errstr};
|
||||
}
|
||||
|
||||
sub errstrrst {
|
||||
my $self = shift;
|
||||
$$self{errstr} = "";
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Crypt::RSA::Errorhandler - Error handling mechanism for Crypt::RSA.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
package Foo;
|
||||
|
||||
use Crypt::RSA::Errorhandler;
|
||||
@ISA = qw(Crypt::RSA::Errorhandler);
|
||||
|
||||
sub alive {
|
||||
..
|
||||
..
|
||||
return
|
||||
$self->error ("Awake, awake! Ring the alarum bell. \
|
||||
Murther and treason!", $dagger)
|
||||
if $self->murdered($king);
|
||||
}
|
||||
|
||||
|
||||
package main;
|
||||
|
||||
use Foo;
|
||||
my $foo = new Foo;
|
||||
$foo->alive($king) or print $foo->errstr();
|
||||
# prints "Awake, awake! ... "
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Crypt::RSA::Errorhandler encapsulates the error handling mechanism used
|
||||
by the modules in Crypt::RSA bundle. Crypt::RSA::Errorhandler doesn't
|
||||
have a constructor and is meant to be inherited. The derived modules use
|
||||
its two methods, error() and errstr(), to communicate error messages to
|
||||
the caller.
|
||||
|
||||
When a method of the derived module fails, it calls $self->error() and
|
||||
returns undef to the caller. The error message passed to error() is made
|
||||
available to the caller through the errstr() accessor. error() also
|
||||
accepts a list of sensitive data that it wipes out (undef'es) before
|
||||
returning.
|
||||
|
||||
The caller should B<never> call errstr() to check for errors. errstr()
|
||||
should be called only when a method indicates (usually through an undef
|
||||
return value) that an error has occurred. This is because errstr() is
|
||||
never overwritten and will always contain a value after the occurence of
|
||||
first error.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<new()>
|
||||
|
||||
Barebones constructor.
|
||||
|
||||
=item B<error($mesage, ($wipeme, $wipemetoo))>
|
||||
|
||||
The first argument to error() is $message which is placed in $self-
|
||||
>{errstr} and the remaining arguments are interpreted as
|
||||
variables containing sensitive data that are wiped out from the
|
||||
memory. error() always returns undef.
|
||||
|
||||
=item B<errstr()>
|
||||
|
||||
errstr() is an accessor method for $self->{errstr}.
|
||||
|
||||
=item B<errstrrst()>
|
||||
|
||||
This method sets $self->{errstr} to an empty string.
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Vipul Ved Prakash, E<lt>mail@vipul.netE<gt>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Crypt::RSA(3)
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
258
database/perl/vendor/lib/Crypt/RSA/Key.pm
vendored
Normal file
258
database/perl/vendor/lib/Crypt/RSA/Key.pm
vendored
Normal file
@@ -0,0 +1,258 @@
|
||||
package Crypt::RSA::Key;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
## Crypt::RSA::Keys
|
||||
##
|
||||
## Copyright (c) 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.
|
||||
|
||||
use base 'Class::Loader';
|
||||
use base 'Crypt::RSA::Errorhandler';
|
||||
use Math::Prime::Util qw(random_nbit_prime miller_rabin_random is_frobenius_khashin_pseudoprime);
|
||||
use Crypt::RSA::DataFormat qw(bitsize);
|
||||
use Math::BigInt try => 'GMP, Pari';
|
||||
use Crypt::RSA::Key::Private;
|
||||
use Crypt::RSA::Key::Public;
|
||||
use Carp;
|
||||
|
||||
$Crypt::RSA::Key::VERSION = '1.99';
|
||||
|
||||
my %MODMAP = (
|
||||
Native_PKF => { Module => "Crypt::RSA::Key::Public" },
|
||||
Native_SKF => { Module => "Crypt::RSA::Key::Private" },
|
||||
SSH_PKF => { Module => "Crypt::RSA::Key::Public::SSH" },
|
||||
SSH_SKF => { Module => "Crypt::RSA::Key::Private::SSH" },
|
||||
);
|
||||
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my $self = {};
|
||||
bless $self, $class;
|
||||
$self->_storemap ( %MODMAP );
|
||||
return $self;
|
||||
}
|
||||
|
||||
|
||||
sub generate {
|
||||
|
||||
my ($self, %params) = @_;
|
||||
|
||||
my $key;
|
||||
unless ($params{q} && $params{p} && $params{e}) {
|
||||
|
||||
return $self->error ("Missing argument.") unless $params{Size};
|
||||
|
||||
return $self->error ("Keysize too small.") if
|
||||
$params{Size} < 48;
|
||||
|
||||
return $self->error ("Odd keysize.") if
|
||||
$params{Size} % 2;
|
||||
|
||||
my $size = int($params{Size}/2);
|
||||
my $verbosity = $params{Verbosity} || 0;
|
||||
|
||||
# Switch from Maurer prime to nbit prime, then add some more primality
|
||||
# testing. This is faster and gives us a wider set of possible primes.
|
||||
|
||||
# We really ought to consider the distribution. See:
|
||||
# https://crocs.fi.muni.cz/_media/public/papers/usenixsec16_1mrsakeys_trfimu_201603.pdf
|
||||
# for comments on p/q selection.
|
||||
|
||||
while (1) {
|
||||
my $p = random_nbit_prime($size);
|
||||
my $q = random_nbit_prime($size);
|
||||
$p = Math::BigInt->new("$p") unless ref($p) eq 'Math::BigInt';
|
||||
$q = Math::BigInt->new("$q") unless ref($q) eq 'Math::BigInt';
|
||||
|
||||
# For unbiased rejection sampling, generate both p/q if size too small.
|
||||
next unless bitsize($p * $q) == $params{Size};
|
||||
|
||||
# Verify primes aren't too close together.
|
||||
if ($params{Size} >= 256) {
|
||||
my $threshold = Math::BigInt->new(2)->bpow($params{Size}/2 - 100);
|
||||
my $diff = $p->copy->bsub($q)->babs;
|
||||
next if $diff <= $threshold;
|
||||
}
|
||||
|
||||
# We could check p-1 and q-1 smoothness.
|
||||
|
||||
# p and q have passed the strong BPSW test, so it would be shocking
|
||||
# if they were not prime. We'll add a few more tests because they're
|
||||
# cheap and we want to be extra careful, but also don't want to spend
|
||||
# the time doing a full primality proof.
|
||||
|
||||
do { carp "$p passes BPSW but fails Frobenius test!"; next; }
|
||||
unless is_frobenius_khashin_pseudoprime($p);
|
||||
do { carp "$q passes BPSW but fails Frobenius test!"; next; }
|
||||
unless is_frobenius_khashin_pseudoprime($q);
|
||||
|
||||
do { carp "$p fails Miller-Rabin testing!"; next; }
|
||||
unless miller_rabin_random($p,3);
|
||||
do { carp "$q fails Miller-Rabin testing!"; next; }
|
||||
unless miller_rabin_random($q,3);
|
||||
|
||||
$key = { p => $p, q => $q, e => Math::BigInt->new(65537) };
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
if ($params{KF}) {
|
||||
$params{PKF} = { Name => "$params{KF}_PKF" };
|
||||
$params{SKF} = { Name => "$params{KF}_SKF" }
|
||||
}
|
||||
|
||||
my $pubload = $params{PKF} ? $params{PKF} : { Name => "Native_PKF" };
|
||||
my $priload = $params{SKF} ? $params{SKF} : { Name => "Native_SKF" };
|
||||
|
||||
my $pubkey = $self->_load (%$pubload) ||
|
||||
return $self->error ("Couldn't load the public key module: $@");
|
||||
my $prikey = $self->_load ((%$priload), Args => ['Cipher' => $params{Cipher}, 'Password' => $params{Password} ]) ||
|
||||
return $self->error ("Couldn't load the private key module: $@");
|
||||
$pubkey->Identity ($params{Identity});
|
||||
$prikey->Identity ($params{Identity});
|
||||
|
||||
$pubkey->e ($$key{e} || $params{e});
|
||||
$prikey->e ($$key{e} || $params{e});
|
||||
$prikey->p ($$key{p} || $params{p});
|
||||
$prikey->q ($$key{q} || $params{q});
|
||||
|
||||
$prikey->phi ( ($prikey->p - 1) * ($prikey->q - 1) );
|
||||
|
||||
$prikey->d ( ($pubkey->e)->copy->bmodinv($prikey->phi) );
|
||||
$prikey->n ( $prikey->p * $prikey->q );
|
||||
$pubkey->n ( $prikey->n );
|
||||
|
||||
$prikey->dp ($prikey->d % ($prikey->p - 1));
|
||||
$prikey->dq ($prikey->d % ($prikey->q - 1));
|
||||
$prikey->u ( ($prikey->p)->copy->bmodinv($prikey->q) );
|
||||
|
||||
return $self->error ("d is too small. Regenerate.") if
|
||||
bitsize($prikey->d) < 0.25 * bitsize($prikey->n);
|
||||
|
||||
$$key{p} = 0; $$key{q} = 0; $$key{e} = 0;
|
||||
|
||||
if ($params{Filename}) {
|
||||
$pubkey->write (Filename => "$params{Filename}.public");
|
||||
$prikey->write (Filename => "$params{Filename}.private");
|
||||
}
|
||||
|
||||
return ($pubkey, $prikey);
|
||||
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Crypt::RSA::Key - RSA Key Pair Generator.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $keychain = new Crypt::RSA::Key;
|
||||
my ($public, $private) = $keychain->generate (
|
||||
Identity => 'Lord Macbeth <macbeth@glamis.com>',
|
||||
Size => 2048,
|
||||
Password => 'A day so foul & fair',
|
||||
Verbosity => 1,
|
||||
) or die $keychain->errstr();
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module provides a method to generate an RSA key pair.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 new()
|
||||
|
||||
Constructor.
|
||||
|
||||
=head2 generate()
|
||||
|
||||
generate() generates an RSA key of specified bitsize. It returns a list of
|
||||
two elements, a Crypt::RSA::Key::Public object that holds the public part
|
||||
of the key pair and a Crypt::RSA::Key::Private object that holds that
|
||||
private part. On failure, it returns undef and sets $self->errstr to
|
||||
appropriate error string. generate() takes a hash argument with the
|
||||
following keys:
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<Size>
|
||||
|
||||
Bitsize of the key to be generated. This should be an even integer > 48.
|
||||
Bitsize is a mandatory argument.
|
||||
|
||||
=item B<Password>
|
||||
|
||||
String with which the private key will be encrypted. If Password is not
|
||||
provided the key will be stored unencrypted.
|
||||
|
||||
=item B<Identity>
|
||||
|
||||
A string that identifies the owner of the key. This string usually takes
|
||||
the form of a name and an email address. The identity is not bound to the
|
||||
key with a signature. However, a future release or another module will
|
||||
provide this facility.
|
||||
|
||||
=item B<Cipher>
|
||||
|
||||
The block cipher which is used for encrypting the private key. Defaults to
|
||||
`Blowfish'. Cipher could be set to any value that works with Crypt::CBC(3)
|
||||
and Tie::EncryptedHash(3).
|
||||
|
||||
=item B<Verbosity>
|
||||
|
||||
When set to 1, generate() will draw a progress display on STDOUT.
|
||||
|
||||
=item B<Filename>
|
||||
|
||||
The generated key pair will be written to disk, in $Filename.public and
|
||||
$Filename.private files, if this argument is provided. Disk writes can be
|
||||
deferred by skipping this argument and achieved later with the write()
|
||||
method of Crypt::RSA::Key::Public(3) and Crypt::RSA::Key::Private(3).
|
||||
|
||||
=item B<KF>
|
||||
|
||||
A string that specifies the key format. As of this writing, two key
|
||||
formats, `Native' and `SSH', are supported. KF defaults to `Native'.
|
||||
|
||||
=item B<SKF>
|
||||
|
||||
Secret (Private) Key Format. Instead of specifying KF, the user could
|
||||
choose to specify secret and public key formats separately. The value for
|
||||
SKF can be a string ("Native" or "SSH") or a hash reference that specifies
|
||||
a module name, its constructor and constructor arguments. The specified
|
||||
module is loaded with Class::Loader(3) and must be interface compatible
|
||||
with Crypt::RSA::Key::Private(3).
|
||||
|
||||
=item B<PKF>
|
||||
|
||||
Public Key Format. This option is like SKF but for the public key.
|
||||
|
||||
=back
|
||||
|
||||
=head1 ERROR HANDLING
|
||||
|
||||
See B<ERROR HANDLING> in Crypt::RSA(3) manpage.
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
There's an inefficiency in the way generate() ensures the key pair is
|
||||
exactly Size bits long. This will be fixed in a future release.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Vipul Ved Prakash, E<lt>mail@vipul.netE<gt>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Crypt::RSA(3), Crypt::RSA::Key::Public(3), Crypt::RSA::Key::Private(3),
|
||||
Tie::EncryptedHash(3), Class::Loader(3),
|
||||
Math::Prime::Util(3)
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
348
database/perl/vendor/lib/Crypt/RSA/Key/Private.pm
vendored
Normal file
348
database/perl/vendor/lib/Crypt/RSA/Key/Private.pm
vendored
Normal file
@@ -0,0 +1,348 @@
|
||||
package Crypt::RSA::Key::Private;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
## Crypt::RSA::Key::Private
|
||||
##
|
||||
## Copyright (c) 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.
|
||||
|
||||
use vars qw($AUTOLOAD $VERSION);
|
||||
use base 'Crypt::RSA::Errorhandler';
|
||||
use Tie::EncryptedHash;
|
||||
use Data::Dumper;
|
||||
use Math::BigInt try => 'GMP, Pari';
|
||||
use Math::Prime::Util qw/is_prime/;
|
||||
use Carp;
|
||||
|
||||
$Crypt::RSA::Key::Private::VERSION = '1.99';
|
||||
|
||||
sub new {
|
||||
|
||||
my ($class, %params) = @_;
|
||||
my $self = { Version => $Crypt::RSA::Key::Private::VERSION };
|
||||
if ($params{Filename}) {
|
||||
bless $self, $class;
|
||||
$self = $self->read (%params);
|
||||
return bless $self, $class;
|
||||
} else {
|
||||
bless $self, $class;
|
||||
$self->Identity ($params{Identity}) if $params{Identity};
|
||||
$self->Cipher ($params{Cipher}||"Blowfish");
|
||||
$self->Password ($params{Password}) if $params{Password};
|
||||
return $self;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub AUTOLOAD {
|
||||
|
||||
my ($self, $value) = @_;
|
||||
my $key = $AUTOLOAD; $key =~ s/.*:://;
|
||||
if ($key =~ /^(e|n|d|p|q|dp|dq|u|phi)$/) {
|
||||
my $prikey = \$self->{private}{"_$key"};
|
||||
if (defined $value) {
|
||||
$self->{Checked} = 0;
|
||||
if (ref $value eq 'Math::BigInt') {
|
||||
$$prikey = $value;
|
||||
} elsif (ref $value eq 'Math::Pari') {
|
||||
$$prikey = Math::BigInt->new($value->pari2pv);
|
||||
} else {
|
||||
$$prikey = Math::BigInt->new("$value");
|
||||
}
|
||||
}
|
||||
if (defined $$prikey) {
|
||||
$$prikey = Math::BigInt->new("$$prikey") unless ref($$prikey) eq 'Math::BigInt';
|
||||
return $$prikey;
|
||||
}
|
||||
return $self->{private_encrypted}{"_$key"} if defined $self->{private_encrypted}{"_$key"};
|
||||
return;
|
||||
} elsif ($key =~ /^Identity|Cipher|Password$/) {
|
||||
$self->{$key} = $value if $value;
|
||||
return $self->{$key};
|
||||
} elsif ($key =~ /^Checked$/) {
|
||||
my ($package) = caller();
|
||||
$self->{Checked} = $value if ($value && $package eq "Crypt::RSA::Key::Private") ;
|
||||
return $self->{Checked};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub hide {
|
||||
|
||||
my ($self) = @_;
|
||||
|
||||
return unless $$self{Password};
|
||||
|
||||
$self->{private_encrypted} = new Tie::EncryptedHash
|
||||
__password => $self->{Password},
|
||||
__cipher => $self->{Cipher};
|
||||
|
||||
for (keys %{$$self{private}}) {
|
||||
$$self{private_encrypted}{$_} = $$self{private}{$_}->bstr;
|
||||
}
|
||||
|
||||
my $private = $self->{private_encrypted};
|
||||
delete $private->{__password};
|
||||
delete $$self{private};
|
||||
delete $$self{Password};
|
||||
|
||||
# Mark ourselves as hidden
|
||||
$self->{Hidden} = 1;
|
||||
}
|
||||
|
||||
|
||||
sub reveal {
|
||||
|
||||
my ($self, %params) = @_;
|
||||
$$self{Password} = $params{Password} if $params{Password};
|
||||
return unless $$self{Password};
|
||||
$$self{private_encrypted}{__password} = $params{Password};
|
||||
for (keys %{$$self{private_encrypted}}) {
|
||||
$$self{private}{$_} = Math::BigInt->new("$$self{private_encrypted}{$_}");
|
||||
}
|
||||
$self->{Hidden} = 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub check {
|
||||
|
||||
my ($self) = @_;
|
||||
|
||||
return 1 if $self->{Checked};
|
||||
|
||||
return $self->error ("Cannot check hidden key - call reveal first.")
|
||||
if $self->{Hidden};
|
||||
|
||||
return $self->error ("Incomplete key.") unless
|
||||
($self->n && $self->d) || ($self->n && $self->p && $self->q);
|
||||
|
||||
if ($self->p && $self->q) {
|
||||
return $self->error ("n is not a number.") if $self->n =~ /\D/;
|
||||
return $self->error ("p is not a number.") if $self->p =~ /\D/;
|
||||
return $self->error ("q is not a number.") if $self->q =~ /\D/;
|
||||
return $self->error ("n is not p*q." ) unless $self->n == $self->p * $self->q;
|
||||
return $self->error ("p is not prime.") unless is_prime( $self->p );
|
||||
return $self->error ("q is not prime.") unless is_prime( $self->q );
|
||||
}
|
||||
|
||||
if ($self->e) {
|
||||
# d * e == 1 mod lcm(p-1, q-1)
|
||||
return $self->error ("e is not a number.") if $self->e =~ /\D/;
|
||||
my $k = Math::BigInt::blcm($self->p-1, $self->q-1);
|
||||
my $KI = ($self->e)->copy->bmul($self->d)->bmodinv($k);
|
||||
return $self->error ("Bad `d'.") unless $KI == 1;
|
||||
}
|
||||
|
||||
if ($self->dp) {
|
||||
# dp == d mod (p-1)
|
||||
return $self->error ("Bad `dp'.") unless $self->dp == $self->d % ($self->p - 1);
|
||||
}
|
||||
|
||||
if ($self->dq) {
|
||||
# dq == d mod (q-1)
|
||||
return $self->error ("Bad `dq'.") unless $self->dq == $self->d % ($self->q - 1);
|
||||
}
|
||||
|
||||
if ($self->u && $self->q && $self->p) {
|
||||
my $m = ($self->p)->copy->bmodinv($self->q);
|
||||
return $self->error ("Bad `u'.") unless $self->u == $m;
|
||||
}
|
||||
|
||||
$self->Checked(1);
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub DESTROY {
|
||||
|
||||
my $self = shift;
|
||||
delete $$self{private_encrypted}{__password};
|
||||
delete $$self{private_encrypted};
|
||||
delete $$self{private};
|
||||
delete $$self{Password};
|
||||
undef $self;
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub write {
|
||||
|
||||
my ($self, %params) = @_;
|
||||
$self->hide();
|
||||
my $string = $self->serialize (%params);
|
||||
open(my $disk, '>', $params{Filename}) or
|
||||
croak "Can't open $params{Filename} for writing.";
|
||||
binmode $disk;
|
||||
print $disk $string;
|
||||
close $disk;
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub read {
|
||||
my ($self, %params) = @_;
|
||||
open(my $disk, '<', $params{Filename}) or
|
||||
croak "Can't open $params{Filename} to read.";
|
||||
binmode $disk;
|
||||
my @key = <$disk>;
|
||||
close $disk;
|
||||
$self = $self->deserialize (String => \@key);
|
||||
$self->reveal(%params);
|
||||
return $self;
|
||||
}
|
||||
|
||||
|
||||
sub serialize {
|
||||
|
||||
my ($self, %params) = @_;
|
||||
if ($$self{private}) { # this is an unencrypted key
|
||||
for (keys %{$$self{private}}) {
|
||||
$$self{private}{$_} = ($$self{private}{$_})->bstr;
|
||||
}
|
||||
}
|
||||
return Dumper $self;
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub deserialize {
|
||||
|
||||
my ($self, %params) = @_;
|
||||
my $string = join'', @{$params{String}};
|
||||
$string =~ s/\$VAR1 =//;
|
||||
$self = eval $string;
|
||||
if ($$self{private}) { # the key is unencrypted
|
||||
for (keys %{$$self{private}}) {
|
||||
$$self{private}{$_} = Math::BigInt->new("$$self{private}{$_}");
|
||||
}
|
||||
return $self;
|
||||
}
|
||||
my $private = new Tie::EncryptedHash;
|
||||
%$private = %{$$self{private_encrypted}};
|
||||
$self->{private_encrypted} = $private;
|
||||
return $self;
|
||||
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Crypt::RSA::Key::Private -- RSA Private Key Management.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
$key = new Crypt::RSA::Key::Private (
|
||||
Identity => 'Lord Banquo <banquo@lochaber.com>',
|
||||
Password => 'The earth hath bubbles',
|
||||
);
|
||||
|
||||
$key->hide();
|
||||
|
||||
$key->write( Filename => 'rsakeys/banquo.private' );
|
||||
|
||||
$akey = new Crypt::RSA::Key::Private (
|
||||
Filename => 'rsakeys/banquo.private'
|
||||
);
|
||||
|
||||
$akey->reveal ( Password => 'The earth hath bubbles' );
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Crypt::RSA::Key::Private provides basic private key management
|
||||
functionality for Crypt::RSA private keys. Following methods are
|
||||
available:
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<new()>
|
||||
|
||||
The constructor. Takes a hash, usually with two arguments: C<Filename> and
|
||||
C<Password>. C<Filename> indicates a file from which the private key
|
||||
should be read. More often than not, private keys are kept encrypted with
|
||||
a symmetric cipher and MUST be decrypted before use. When a C<Password>
|
||||
argument is provided, the key is also decrypted before it is returned by
|
||||
C<new()>. Here's a complete list of arguments accepted by C<new()> (all of
|
||||
which are optional):
|
||||
|
||||
=over 4
|
||||
|
||||
=item Identity
|
||||
|
||||
A string identifying the owner of the key. Canonically, a name and
|
||||
email address.
|
||||
|
||||
=item Filename
|
||||
|
||||
Name of the file that contains the private key.
|
||||
|
||||
=item Password
|
||||
|
||||
Password with which the private key is encrypted, or should be encrypted
|
||||
(in case of a new key).
|
||||
|
||||
=item Cipher
|
||||
|
||||
Name of the symmetric cipher in which the private key is encrypted (or
|
||||
should be encrypted). The default is "Blowfish" and possible values
|
||||
include DES, IDEA, Twofish and other ciphers supported by Crypt::CBC.
|
||||
|
||||
=back
|
||||
|
||||
=item B<reveal()>
|
||||
|
||||
If the key is not decrypted at C<new()>, it can be decrypted by
|
||||
calling C<reveal()> with a C<Password> argument.
|
||||
|
||||
=item B<hide()>
|
||||
|
||||
C<hide()> causes the key to be encrypted by the chosen symmetric cipher
|
||||
and password.
|
||||
|
||||
=item B<write()>
|
||||
|
||||
Causes the key to be written to a disk file specified by the
|
||||
C<Filename> argument. C<write()> will call C<hide()> before
|
||||
writing the key to disk. If you wish to store the key in plain,
|
||||
don't specify a password at C<new()>.
|
||||
|
||||
=item B<read()>
|
||||
|
||||
Causes the key to be read from a disk file specified by
|
||||
C<Filename> into the object. If C<Password> is provided, the
|
||||
method automatically calls reveal() to decrypt the key.
|
||||
|
||||
=item B<serialize()>
|
||||
|
||||
Creates a Data::Dumper(3) serialization of the private key and
|
||||
returns the string representation.
|
||||
|
||||
=item B<deserialize()>
|
||||
|
||||
Accepts a serialized key under the C<String> parameter and
|
||||
coverts it into the perl representation stored in the object.
|
||||
|
||||
=item C<check()>
|
||||
|
||||
Check the consistency of the key. If the key checks out, it sets
|
||||
$self->{Checked} = 1. Returns undef on failure.
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Vipul Ved Prakash, E<lt>mail@vipul.netE<gt>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Crypt::RSA::Key(3), Crypt::RSA::Public(3)
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
271
database/perl/vendor/lib/Crypt/RSA/Key/Private/SSH.pm
vendored
Normal file
271
database/perl/vendor/lib/Crypt/RSA/Key/Private/SSH.pm
vendored
Normal file
@@ -0,0 +1,271 @@
|
||||
package Crypt::RSA::Key::Private::SSH::Buffer;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
## Crypt::RSA::Key::Private::SSH
|
||||
##
|
||||
## Copyright (c) 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.
|
||||
|
||||
use Crypt::RSA::DataFormat qw( os2ip bitsize i2osp );
|
||||
use Data::Buffer;
|
||||
use base qw( Data::Buffer );
|
||||
|
||||
sub get_mp_int {
|
||||
my $buf = shift;
|
||||
my $off = $buf->{offset};
|
||||
my $bits = unpack "n", $buf->bytes($off, 2);
|
||||
my $bytes = int(($bits+7)/8);
|
||||
my $p = os2ip( $buf->bytes($off+2, $bytes) );
|
||||
$buf->{offset} += 2 + $bytes;
|
||||
$p;
|
||||
}
|
||||
|
||||
sub put_mp_int {
|
||||
my $buf = shift;
|
||||
my $int = shift;
|
||||
my $bits = bitsize($int);
|
||||
$buf->put_int16($bits);
|
||||
$buf->put_chars( i2osp($int) );
|
||||
}
|
||||
|
||||
|
||||
package Crypt::RSA::Key::Private::SSH;
|
||||
use strict;
|
||||
use warnings;
|
||||
use constant PRIVKEY_ID => "SSH PRIVATE KEY FILE FORMAT 1.1\n";
|
||||
use vars qw( %CIPHERS %CIPHERS_TEXT );
|
||||
|
||||
# Having to name all the ciphers here is not extensible, but we're stuck
|
||||
# with it given the RSA1 format. I don't think any of this is standardized.
|
||||
# OpenSSH supports only: none, des, 3des, and blowfish here. This set of
|
||||
# numbers below 10 match. Values above 10 are well supported by Perl modules.
|
||||
BEGIN {
|
||||
# CIPHERS : Used by deserialize to map numbers to modules.
|
||||
%CIPHERS = (
|
||||
# 0 = none
|
||||
1 => [ 'IDEA' ],
|
||||
2 => [ 'DES', 'DES_PP' ],
|
||||
3 => [ 'DES_EDE3' ],
|
||||
# From what I can see, none of the 3+ RC4 modules are CBC compatible
|
||||
# 5 => [ 'RC4' ],
|
||||
6 => [ 'Blowfish', 'Blowfish_PP' ],
|
||||
10 => [ 'Twofish2' ],
|
||||
11 => [ 'CAST5', 'CAST5_PP' ],
|
||||
12 => [ 'Rijndael', 'OpenSSL::AES' ],
|
||||
13 => [ 'RC6' ],
|
||||
14 => [ 'Camellia', 'Camellia_PP' ],
|
||||
# Crypt::Serpent is broken and abandonded.
|
||||
);
|
||||
# CIPHERS_TEXT : Used by serialize to map names to modules to numbers
|
||||
%CIPHERS_TEXT = (
|
||||
'NONE' => 0,
|
||||
'IDEA' => 1,
|
||||
'DES' => 2,
|
||||
'DES_EDE3' => 3,
|
||||
'DES3' => 3,
|
||||
'3DES' => 3,
|
||||
'TRIPLEDES' => 3,
|
||||
# 'RC4' => 5,
|
||||
# 'ARC4' => 5,
|
||||
# 'ARCFOUR' => 5,
|
||||
'BLOWFISH' => 6,
|
||||
'TWOFISH' => 10,
|
||||
'TWOFISH2' => 10,
|
||||
'CAST5' => 11,
|
||||
'CAST5_PP' => 11,
|
||||
'CAST5PP' => 11,
|
||||
'CAST-5' => 11,
|
||||
'CAST-128' => 11,
|
||||
'CAST128' => 11,
|
||||
'RIJNDAEL' => 12,
|
||||
'AES' => 12,
|
||||
'OPENSSL::AES'=>12,
|
||||
'RC6' => 13,
|
||||
'CAMELLIA' => 14,
|
||||
);
|
||||
}
|
||||
|
||||
use Carp qw( croak );
|
||||
use Data::Buffer;
|
||||
use Crypt::CBC 2.17; # We want a good version
|
||||
use Crypt::RSA::Key::Private;
|
||||
use base qw( Crypt::RSA::Key::Private );
|
||||
|
||||
sub deserialize {
|
||||
my($key, %params) = @_;
|
||||
my $passphrase = defined $params{Password} ? $params{Password}
|
||||
: defined $key->Password ? $key->Password
|
||||
: '';
|
||||
my $string = $params{String};
|
||||
croak "Must supply String=>'blob' to deserialize" unless defined $string;
|
||||
$string = join('', @$string) if ref($string) eq 'ARRAY';
|
||||
|
||||
croak "Cowardly refusing to deserialize on top of a hidden key"
|
||||
if $key->{Hidden};
|
||||
|
||||
my $buffer = new Crypt::RSA::Key::Private::SSH::Buffer;
|
||||
$buffer->append($string);
|
||||
|
||||
my $id = $buffer->bytes(0, length(PRIVKEY_ID), '');
|
||||
croak "Bad key file format" unless $id eq PRIVKEY_ID;
|
||||
$buffer->bytes(0, 1, '');
|
||||
|
||||
my $cipher_type = $buffer->get_int8;
|
||||
$buffer->get_int32; ## Reserved data.
|
||||
|
||||
$buffer->get_int32; ## Private key bits.
|
||||
$key->n( $buffer->get_mp_int );
|
||||
$key->e( $buffer->get_mp_int );
|
||||
|
||||
$key->Identity( $buffer->get_str ); ## Comment.
|
||||
|
||||
if ($cipher_type != 0) {
|
||||
my $cipher_names = $CIPHERS{$cipher_type} or
|
||||
croak "Unknown cipher '$cipher_type' used in key file";
|
||||
my $cipher_name;
|
||||
foreach my $name (@$cipher_names) {
|
||||
my $class = "Crypt::$name";
|
||||
(my $file = $class) =~ s=::|'=/=g;
|
||||
if ( eval { require "$file.pm"; 1 } ) {
|
||||
$cipher_name = $name; last;
|
||||
}
|
||||
}
|
||||
if (!defined $cipher_name) {
|
||||
croak "Unsupported cipher '$cipher_names->[0]': $@";
|
||||
}
|
||||
|
||||
my $cipher = Crypt::CBC->new( -key => $passphrase,
|
||||
-cipher => $cipher_name );
|
||||
my $decrypted =
|
||||
$cipher->decrypt($buffer->bytes($buffer->offset));
|
||||
$buffer->empty;
|
||||
$buffer->append($decrypted);
|
||||
}
|
||||
|
||||
my $check1 = $buffer->get_int8;
|
||||
my $check2 = $buffer->get_int8;
|
||||
unless ($check1 == $buffer->get_int8 &&
|
||||
$check2 == $buffer->get_int8) {
|
||||
croak "Bad passphrase supplied for key file";
|
||||
}
|
||||
|
||||
$key->d( $buffer->get_mp_int );
|
||||
$key->u( $buffer->get_mp_int );
|
||||
$key->p( $buffer->get_mp_int );
|
||||
$key->q( $buffer->get_mp_int );
|
||||
|
||||
# Restore other variables.
|
||||
$key->phi( ($key->p - 1) * ($key->q - 1) );
|
||||
$key->dp( $key->d % ($key->p - 1) );
|
||||
$key->dq( $key->d % ($key->q - 1) );
|
||||
# Our passphrase may be just temporary for the serialization, and have
|
||||
# nothing to do with the key. So don't store it.
|
||||
#$key->{Password} = $passphrase unless defined $key->{Password};
|
||||
|
||||
$key;
|
||||
}
|
||||
|
||||
|
||||
sub serialize {
|
||||
my($key, %params) = @_;
|
||||
|
||||
# We could reveal it, but (1) what if it was hidden with a different
|
||||
# password, and (2) they may not want to revealed (even if hidden after).
|
||||
croak "Cowardly refusing to serialize a hidden key"
|
||||
if $key->{Hidden};
|
||||
|
||||
my $passphrase = defined $params{Password} ? $params{Password}
|
||||
: defined $key->Password ? $key->Password
|
||||
: '';
|
||||
my $cipher_name = defined $params{Cipher} ? $params{Cipher}
|
||||
: defined $key->Cipher ? $key->Cipher
|
||||
: 'Blowfish';
|
||||
|
||||
# If they've given us no passphrase, we will be unencrypted.
|
||||
my $cipher_type = 0;
|
||||
|
||||
if ($passphrase ne '') {
|
||||
$cipher_type = $CIPHERS_TEXT{ uc $cipher_name };
|
||||
croak "Unknown cipher: '$cipher_name'" unless defined $cipher_type;
|
||||
}
|
||||
|
||||
my $buffer = new Crypt::RSA::Key::Private::SSH::Buffer;
|
||||
my($check1, $check2);
|
||||
$buffer->put_int8($check1 = int rand 255);
|
||||
$buffer->put_int8($check2 = int rand 255);
|
||||
$buffer->put_int8($check1);
|
||||
$buffer->put_int8($check2);
|
||||
|
||||
$buffer->put_mp_int($key->d);
|
||||
$buffer->put_mp_int($key->u);
|
||||
$buffer->put_mp_int($key->p);
|
||||
$buffer->put_mp_int($key->q);
|
||||
|
||||
$buffer->put_int8(0)
|
||||
while $buffer->length % 8;
|
||||
|
||||
my $encrypted = new Crypt::RSA::Key::Private::SSH::Buffer;
|
||||
$encrypted->put_chars(PRIVKEY_ID);
|
||||
$encrypted->put_int8(0);
|
||||
$encrypted->put_int8($cipher_type);
|
||||
$encrypted->put_int32(0);
|
||||
|
||||
$encrypted->put_int32(Crypt::RSA::DataFormat::bitsize($key->n));
|
||||
$encrypted->put_mp_int($key->n);
|
||||
$encrypted->put_mp_int($key->e);
|
||||
$encrypted->put_str($key->Identity || '');
|
||||
|
||||
if ($cipher_type) {
|
||||
my $cipher_names = $CIPHERS{$cipher_type};
|
||||
my $cipher_name;
|
||||
foreach my $name (@$cipher_names) {
|
||||
my $class = "Crypt::$name";
|
||||
(my $file = $class) =~ s=::|'=/=g;
|
||||
if ( eval { require "$file.pm"; 1 } ) {
|
||||
$cipher_name = $name; last;
|
||||
}
|
||||
}
|
||||
if (!defined $cipher_name) {
|
||||
croak "Unsupported cipher '$cipher_names->[0]': $@";
|
||||
}
|
||||
|
||||
my $cipher = Crypt::CBC->new( -key => $passphrase,
|
||||
-cipher => $cipher_name );
|
||||
$encrypted->append( $cipher->encrypt($buffer->bytes) );
|
||||
}
|
||||
else {
|
||||
$encrypted->append($buffer->bytes);
|
||||
}
|
||||
|
||||
$encrypted->bytes;
|
||||
}
|
||||
|
||||
|
||||
sub hide {}
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Crypt::RSA::Key::Private::SSH - SSH Private Key Import
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
Crypt::RSA::Key::Private::SSH is a class derived from
|
||||
Crypt::RSA::Key::Private that provides serialize() and
|
||||
deserialize() methods for SSH keys in the SSH1 format.
|
||||
|
||||
Alternative formats (SSH2, PEM) are not implemented.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Vipul Ved Prakash, E<lt>mail@vipul.netE<gt> wrote the original version.
|
||||
|
||||
Dana Jacobsen E<lt>dana@acm.orgE<gt> wrote the new version.
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
|
||||
|
||||
1;
|
||||
190
database/perl/vendor/lib/Crypt/RSA/Key/Public.pm
vendored
Normal file
190
database/perl/vendor/lib/Crypt/RSA/Key/Public.pm
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
package Crypt::RSA::Key::Public;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
## Crypt::RSA::Key::Public
|
||||
##
|
||||
## Copyright (c) 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.
|
||||
|
||||
use vars qw($AUTOLOAD);
|
||||
use Carp;
|
||||
use Data::Dumper;
|
||||
use base 'Crypt::RSA::Errorhandler';
|
||||
use Math::BigInt try => 'GMP, Pari';
|
||||
|
||||
$Crypt::RSA::Key::Public::VERSION = '1.99';
|
||||
|
||||
sub new {
|
||||
|
||||
my ($class, %params) = @_;
|
||||
my $self = { Version => $Crypt::RSA::Key::Public::VERSION };
|
||||
if ($params{Filename}) {
|
||||
bless $self, $class;
|
||||
$self = $self->read (%params);
|
||||
return bless $self, $class;
|
||||
} else {
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub AUTOLOAD {
|
||||
my ($self, $value) = @_;
|
||||
my $key = $AUTOLOAD; $key =~ s/.*:://;
|
||||
if ($key =~ /^n|e$/) {
|
||||
if (defined $value) {
|
||||
if (ref $value eq 'Math::BigInt') {
|
||||
$self->{$key} = $value;
|
||||
} elsif (ref $value eq 'Math::Pari') {
|
||||
$self->{$key} = Math::BigInt->new($value->pari2pv);
|
||||
} else {
|
||||
$self->{$key} = Math::BigInt->new("$value");
|
||||
}
|
||||
}
|
||||
if (defined $self->{$key}) {
|
||||
$self->{$key} = Math::BigInt->new("$self->{$key}") unless ref($self->{$key}) eq 'Math::BigInt';
|
||||
return $self->{$key};
|
||||
}
|
||||
return;
|
||||
} elsif ($key =~ /^Identity$/) {
|
||||
$self->{$key} = $value if $value;
|
||||
return $self->{$key};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub DESTROY {
|
||||
|
||||
my $self = shift;
|
||||
undef $self;
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub check {
|
||||
|
||||
my $self = shift;
|
||||
return $self->error ("Incomplete key.")
|
||||
unless defined $self->n && defined $self->e;
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub write {
|
||||
|
||||
my ($self, %params) = @_;
|
||||
$self->hide();
|
||||
my $string = $self->serialize (%params);
|
||||
open(my $disk, '>', $params{Filename}) or
|
||||
croak "Can't open $params{Filename} for writing.";
|
||||
binmode $disk;
|
||||
print $disk $string;
|
||||
close $disk;
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub read {
|
||||
my ($self, %params) = @_;
|
||||
open(my $disk, '<', $params{Filename}) or
|
||||
croak "Can't open $params{Filename} to read.";
|
||||
binmode $disk;
|
||||
my @key = <$disk>;
|
||||
close $disk;
|
||||
$self = $self->deserialize (String => \@key);
|
||||
return $self;
|
||||
}
|
||||
|
||||
|
||||
sub serialize {
|
||||
|
||||
my ($self, %params) = @_;
|
||||
# Convert bigints to strings
|
||||
foreach my $key (qw/n e/) {
|
||||
$self->{$key} = $self->{$key}->bstr if ref($self->{$key}) eq 'Math::BigInt';
|
||||
}
|
||||
return Dumper $self;
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub deserialize {
|
||||
|
||||
my ($self, %params) = @_;
|
||||
my $string = join'', @{$params{String}};
|
||||
$string =~ s/\$VAR1 =//;
|
||||
$self = eval $string;
|
||||
return $self;
|
||||
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Crypt::RSA::Key::Public -- RSA Public Key Management.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
$key = new Crypt::RSA::Key::Public;
|
||||
$key->write ( Filename => 'rsakeys/banquo.public' );
|
||||
|
||||
$akey = new Crypt::RSA::Key::Public (
|
||||
Filename => 'rsakeys/banquo.public'
|
||||
);
|
||||
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Crypt::RSA::Key::Public provides basic key management functionality for
|
||||
Crypt::RSA public keys. Following methods are available:
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<new()>
|
||||
|
||||
The constructor. Reads the public key from a disk file when
|
||||
called with a C<Filename> argument.
|
||||
|
||||
=item B<write()>
|
||||
|
||||
Causes the key to be written to a disk file specified by the
|
||||
C<Filename> argument.
|
||||
|
||||
=item B<read()>
|
||||
|
||||
Causes the key to be read from a disk file specified by
|
||||
C<Filename> into the object.
|
||||
|
||||
=item B<serialize()>
|
||||
|
||||
Creates a Data::Dumper(3) serialization of the private key and
|
||||
returns the string representation.
|
||||
|
||||
=item B<deserialize()>
|
||||
|
||||
Accepts a serialized key under the C<String> parameter and
|
||||
coverts it into the perl representation stored in the object.
|
||||
|
||||
=item C<check()>
|
||||
|
||||
Check the consistency of the key. Returns undef on failure.
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Vipul Ved Prakash, E<lt>mail@vipul.netE<gt>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Crypt::RSA::Key(3), Crypt::RSA::Key::Private(3)
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
53
database/perl/vendor/lib/Crypt/RSA/Key/Public/SSH.pm
vendored
Normal file
53
database/perl/vendor/lib/Crypt/RSA/Key/Public/SSH.pm
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
package Crypt::RSA::Key::Public::SSH;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
## Crypt::RSA::Key::Private::SSH
|
||||
##
|
||||
## Copyright (c) 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.
|
||||
|
||||
use Carp qw/croak/;
|
||||
use Crypt::RSA::DataFormat qw(bitsize);
|
||||
use Crypt::RSA::Key::Public;
|
||||
use base qw( Crypt::RSA::Key::Public );
|
||||
|
||||
sub deserialize {
|
||||
my ($self, %params) = @_;
|
||||
my $string = $params{String};
|
||||
croak "Must supply String=>'blob' to deserialize" unless defined $string;
|
||||
$string = join('', @$string) if ref($string) eq 'ARRAY';
|
||||
my ($bitsize, $e, $n, $ident) = split /\s/, $string, 4;
|
||||
$self->n ($n);
|
||||
$self->e ($e);
|
||||
$self->Identity ($ident);
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub serialize {
|
||||
my ($self, %params) = @_;
|
||||
my $bitsize = bitsize ($self->n);
|
||||
my $string = join ' ', $bitsize, $self->e, $self->n, $self->Identity;
|
||||
return $string;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Crypt::RSA::Key::Public::SSH - SSH Public Key Import
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
Crypt::RSA::Key::Public::SSH is a class derived from
|
||||
Crypt::RSA::Key::Public that provides serialize() and
|
||||
deserialze() methods for SSH 2.x keys.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Vipul Ved Prakash, E<lt>mail@vipul.netE<gt>
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
140
database/perl/vendor/lib/Crypt/RSA/Primitives.pm
vendored
Normal file
140
database/perl/vendor/lib/Crypt/RSA/Primitives.pm
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
package Crypt::RSA::Primitives;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
## Crypt::RSA::Primitives -- Cryptography and encoding primitives
|
||||
## used by Crypt::RSA.
|
||||
##
|
||||
## Copyright (c) 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.
|
||||
|
||||
use base 'Crypt::RSA::Errorhandler';
|
||||
use Crypt::RSA::Debug qw(debug);
|
||||
use Math::BigInt try => 'GMP, Pari';
|
||||
use Carp;
|
||||
|
||||
sub new {
|
||||
return bless {}, shift;
|
||||
}
|
||||
|
||||
|
||||
sub core_encrypt {
|
||||
|
||||
# procedure:
|
||||
# c = (m ** e) mod n
|
||||
|
||||
my ($self, %params) = @_;
|
||||
my $key = $params{Key};
|
||||
$self->error ("Bad key.", \%params, $key) unless $key->check();
|
||||
my $plaintext = (defined $params{Message}) ? $params{Message} : $params{Plaintext};
|
||||
$plaintext = Math::BigInt->new("$plaintext") if ref($plaintext) ne 'Math::BigInt';
|
||||
debug ("pt == $plaintext");
|
||||
|
||||
my $e = $key->e;
|
||||
my $n = $key->n;
|
||||
return $self->error ("Numeric representation of plaintext is out of bound.",
|
||||
\$plaintext, $key, \%params) if $plaintext > $n;
|
||||
my $c = $plaintext->bmodpow($e, $n);
|
||||
debug ("ct == $c");
|
||||
$n = undef;
|
||||
$e = undef;
|
||||
return $c;
|
||||
}
|
||||
|
||||
|
||||
sub core_decrypt {
|
||||
|
||||
# procedure:
|
||||
# p = (c ** d) mod n
|
||||
|
||||
my ($self, %params) = @_;
|
||||
my $key = $params{Key};
|
||||
$self->error ("Bad key.") unless $key->check();
|
||||
|
||||
my $cyphertext = defined $params{Cyphertext} ? $params{Cyphertext} : $params{Ciphertext};
|
||||
$cyphertext = Math::BigInt->new("$cyphertext") if ref($cyphertext) ne 'Math::BigInt';
|
||||
my $n = $key->n;
|
||||
my $d = $key->d;
|
||||
return $self->error ("Decryption error.") if $cyphertext > $n;
|
||||
|
||||
my $pt;
|
||||
if ($key->p && $key->q) {
|
||||
# Garner's CRT algorithm
|
||||
my $p = $key->p;
|
||||
my $q = $key->q;
|
||||
$key->u ($p->copy->bmodinv($q)) unless defined $key->u;
|
||||
$key->dp($d % ($p-1) ) unless defined $key->dp;
|
||||
$key->dq($d % ($q-1) ) unless defined $key->dq;
|
||||
my $u = $key->u;
|
||||
my $dp = $key->dp;
|
||||
my $dq = $key->dq;
|
||||
my $p2 = ($cyphertext % $p)->bmodpow($dp, $p);
|
||||
my $q2 = ($cyphertext % $q)->bmodpow($dq, $q);
|
||||
$pt = $p2 + ($p * ((($q2 - $p2) * $u) % $q));
|
||||
}
|
||||
else {
|
||||
$pt = $cyphertext->copy->bmodpow($d, $n);
|
||||
}
|
||||
|
||||
debug ("ct == $cyphertext");
|
||||
debug ("pt == $pt");
|
||||
return $pt;
|
||||
}
|
||||
|
||||
|
||||
sub core_sign {
|
||||
|
||||
my ($self, %params) = @_;
|
||||
$params{Cyphertext} = $params{Message} || $params{Plaintext};
|
||||
return $self->core_decrypt (%params);
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub core_verify {
|
||||
|
||||
my ($self, %params) = @_;
|
||||
$params{Plaintext} = $params{Signature};
|
||||
return $self->core_encrypt (%params);
|
||||
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Crypt::RSA::Primitives - RSA encryption, decryption, signature and verification primitives.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $prim = new Crypt::RSA::Primitives;
|
||||
my $ctxt = $prim->core_encrypt (Key => $key, Plaintext => $string);
|
||||
my $ptxt = $prim->core_decrypt (Key => $key, Cyphertext => $ctxt);
|
||||
my $sign = $prim->core_sign (Key => $key, Message => $string);
|
||||
my $vrfy = $prim->core_verify (Key => $key, Signature => $sig);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module implements RSA encryption, decryption, signature and
|
||||
verification primitives. These primitives should only be used in the
|
||||
context of an encryption or signing scheme. See Crypt::RSA::ES::OAEP(3),
|
||||
and Crypt::RSA::SS::PSS(3) for the implementation of two such schemes.
|
||||
|
||||
=head1 ERROR HANDLING
|
||||
|
||||
See B<ERROR HANDLING> in Crypt::RSA(3) manpage.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Vipul Ved Prakash, E<lt>mail@vipul.netE<gt>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Crypt::RSA(3), Crypt::RSA::Key(3), Crypt::RSA::ES::OAEP(3),
|
||||
Crypt::RSA::SS::PSS(3)
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
275
database/perl/vendor/lib/Crypt/RSA/SS/PKCS1v15.pm
vendored
Normal file
275
database/perl/vendor/lib/Crypt/RSA/SS/PKCS1v15.pm
vendored
Normal file
@@ -0,0 +1,275 @@
|
||||
package Crypt::RSA::SS::PKCS1v15;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
## Crypt::RSA::SS:PKCS1v15
|
||||
##
|
||||
## Copyright (c) 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.
|
||||
|
||||
use base 'Crypt::RSA::Errorhandler';
|
||||
use Crypt::RSA::DataFormat qw(octet_len os2ip i2osp h2osp);
|
||||
use Crypt::RSA::Primitives;
|
||||
use Crypt::RSA::Debug qw(debug);
|
||||
use Digest::SHA qw(sha1 sha224 sha256 sha384 sha512);
|
||||
use Digest::MD5 qw(md5);
|
||||
use Digest::MD2 qw(md2);
|
||||
|
||||
$Crypt::RSA::SS::PKCS1v15::VERSION = '1.99';
|
||||
|
||||
# See if we have a bug-fixed RIPEMD-160.
|
||||
my $ripe_hash = undef;
|
||||
if (eval { require Crypt::RIPEMD160; $Crypt::RIPEMD160::VERSION >= 0.05; }) {
|
||||
$ripe_hash = sub { my $r=new Crypt::RIPEMD160; $r->add(shift); $r->digest();};
|
||||
}
|
||||
|
||||
sub new {
|
||||
|
||||
my ($class, %params) = @_;
|
||||
my $self = bless {
|
||||
primitives => new Crypt::RSA::Primitives,
|
||||
digest => $params{Digest} || 'SHA1',
|
||||
encoding => {
|
||||
# See http://rfc-ref.org/RFC-TEXTS/3447/chapter9.html
|
||||
MD2 =>[\&md2, "30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 02 05 00 04 10"],
|
||||
MD5 =>[\&md5, "30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 05 05 00 04 10"],
|
||||
SHA1 =>[\&sha1, "30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14"],
|
||||
SHA224=>[\&sha224,"30 2d 30 0d 06 09 60 86 48 01 65 03 04 02 04 05 00 04 1c"],
|
||||
SHA256=>[\&sha256,"30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20"],
|
||||
SHA384=>[\&sha384,"30 41 30 0d 06 09 60 86 48 01 65 03 04 02 02 05 00 04 30"],
|
||||
SHA512=>[\&sha512,"30 51 30 0d 06 09 60 86 48 01 65 03 04 02 03 05 00 04 40"],
|
||||
RIPEMD160=>[$ripe_hash,"30 21 30 09 06 05 2B 24 03 02 01 05 00 04 14"],
|
||||
},
|
||||
VERSION => $Crypt::RSA::SS::PKCS1v15::VERSION,
|
||||
}, $class;
|
||||
# Allow "sha256", "sha-256", "RipeMD-160", etc.
|
||||
$self->{digest} =~ tr/a-z/A-Z/;
|
||||
$self->{digest} =~ s/[^A-Z0-9]//g;
|
||||
if ($params{Version}) {
|
||||
# do versioning here
|
||||
}
|
||||
return $self;
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub sign {
|
||||
|
||||
my ($self, %params) = @_;
|
||||
my $key = $params{Key};
|
||||
my $M = $params{Message} || $params{Plaintext};
|
||||
return $self->error ("No Message or Plaintext parameter", \$key, \%params) unless $M;
|
||||
return $self->error ("No Key parameter", \$M, \%params) unless $key;
|
||||
my $k = octet_len ($key->n);
|
||||
|
||||
my $em;
|
||||
unless ($em = $self->encode ($M, $k)) {
|
||||
return $self->error ($self->errstr, \$key, \%params, \$M)
|
||||
if $self->errstr eq "Message too long.";
|
||||
return $self->error ("Modulus too short.", \$key, \%params, \$M)
|
||||
if $self->errstr eq "Intended encoded message length too short";
|
||||
# Other error
|
||||
return $self->error ($self->errstr, \$key, \%params, \$M);
|
||||
}
|
||||
|
||||
my $m = os2ip ($em);
|
||||
my $sig = $self->{primitives}->core_sign (Key => $key, Message => $m);
|
||||
return i2osp ($sig, $k);
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub verify {
|
||||
|
||||
my ($self, %params) = @_;
|
||||
my $key = $params{Key}; my $M = $params{Message} || $params{Plaintext};
|
||||
my $S = $params{Signature};
|
||||
return $self->error ("No Message or Plaintext parameter", \$key, \%params) unless $M;
|
||||
return $self->error ("No Key parameter", \$M, \$S, \%params) unless $key;
|
||||
return $self->error ("No Signature parameter", \$key, \$M, \%params) unless $S;
|
||||
my $k = octet_len ($key->n);
|
||||
return $self->error ("Invalid signature.", \$key, \$M, \%params) if length($S) != $k;
|
||||
my $s = os2ip ($S);
|
||||
my $m = $self->{primitives}->core_verify (Key => $key, Signature => $s) ||
|
||||
$self->error ("Invalid signature.", \$M, $key, \%params);
|
||||
my $em = i2osp ($m, $k) ||
|
||||
return $self->error ("Invalid signature.", \$M, \$S, $key, \%params);
|
||||
my $em1;
|
||||
unless ($em1 = $self->encode ($M, $k)) {
|
||||
return $self->error ($self->errstr, \$key, \%params, \$M)
|
||||
if $self->errstr eq "Message too long.";
|
||||
return $self->error ("Modulus too short.", \$key, \%params, \$M)
|
||||
if $self->errstr eq "Intended encoded message length too short.";
|
||||
}
|
||||
|
||||
debug ("em: $em"); debug ("em1: $em1");
|
||||
|
||||
return 1 if $em eq $em1;
|
||||
return $self->error ("Invalid signature.", \$M, \$key, \%params);
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub encode {
|
||||
|
||||
my ($self, $M, $emlen) = @_;
|
||||
|
||||
my $encoding = $self->{encoding}->{$self->{digest}};
|
||||
return $self->error ("Invalid encoding: $self->{digest}") unless defined $encoding;
|
||||
my ($hashfunc, $digestinfo) = @$encoding;
|
||||
return $self->error ("encoding method $self->{digest} not supported") unless defined $hashfunc;
|
||||
|
||||
# Changed to match RFC 2313 (PKCS#1 v1.5) and 3447 (PKCS#1 v2.1).
|
||||
# There was apparently some confusion from XML documentation that
|
||||
# printed a different set of instructions here. See, for example:
|
||||
# http://osdir.com/ml/mozilla.crypto/2005-05/msg00300.htm
|
||||
# However, previously emlen was always k-1, so the result ended up
|
||||
# being identical anyway. One change is that we now return if there
|
||||
# is not enough padding. Previously the error string would be set
|
||||
# but processing would continue.
|
||||
#
|
||||
# Refs:
|
||||
# http://rfc-ref.org/RFC-TEXTS/3447/chapter9.html
|
||||
# https://tools.ietf.org/html/rfc2313
|
||||
my $H = $hashfunc->($M);
|
||||
my $alg = h2osp($digestinfo);
|
||||
return $self->error ("Invalid digest results: $self->{digest}") unless defined $H && length($H) > 0;
|
||||
|
||||
my $T = $alg . $H;
|
||||
return $self->error ("Intended encoded message length too short.", \$M) if $emlen < length($T) + 11;
|
||||
my $pslen = $emlen - length($T) - 3;
|
||||
my $PS = chr(0xff) x $pslen;
|
||||
my $em = chr(0) . chr(1) . $PS . chr(0) . $T;
|
||||
return $em;
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub version {
|
||||
my $self = shift;
|
||||
return $self->{VERSION};
|
||||
}
|
||||
|
||||
|
||||
sub signblock {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
sub verifyblock {
|
||||
my ($self, %params) = @_;
|
||||
return octet_len($params{Key}->n);
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Crypt::RSA::SS::PKCS1v15 - PKCS #1 v1.5 signatures.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $pkcs = new Crypt::RSA::SS::PKCS1v15 (
|
||||
Digest => 'MD5'
|
||||
);
|
||||
|
||||
my $signature = $pkcs->sign (
|
||||
Message => $message,
|
||||
Key => $private,
|
||||
) || die $pss->errstr;
|
||||
|
||||
my $verify = $pkcs->verify (
|
||||
Message => $message,
|
||||
Key => $key,
|
||||
Signature => $signature,
|
||||
) || die $pss->errstr;
|
||||
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module implements PKCS #1 v1.5 signatures based on RSA. See [13]
|
||||
for details on the scheme.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 B<new()>
|
||||
|
||||
Constructor. Takes a hash as argument with the following key:
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<Digest>
|
||||
|
||||
Name of the Message Digest algorithm. Three Digest algorithms are
|
||||
supported: MD2, MD5, SHA1, SHA224, SHA256, SHA384, and SHA512.
|
||||
Digest defaults to SHA1.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head2 B<version()>
|
||||
|
||||
Returns the version number of the module.
|
||||
|
||||
=head2 B<sign()>
|
||||
|
||||
Computes a PKCS #1 v1.5 signature on a message with the private key of the
|
||||
signer. sign() takes a hash argument with the following mandatory keys:
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<Message>
|
||||
|
||||
Message to be signed, a string of arbitrary length.
|
||||
|
||||
=item B<Key>
|
||||
|
||||
Private key of the signer, a Crypt::RSA::Key::Private object.
|
||||
|
||||
=back
|
||||
|
||||
=head2 B<verify()>
|
||||
|
||||
Verifies a signature generated with sign(). Returns a true value on
|
||||
success and false on failure. $self->errstr is set to "Invalid signature."
|
||||
or appropriate error on failure. verify() takes a hash argument with the
|
||||
following mandatory keys:
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<Key>
|
||||
|
||||
Public key of the signer, a Crypt::RSA::Key::Public object.
|
||||
|
||||
=item B<Message>
|
||||
|
||||
The original signed message, a string of arbitrary length.
|
||||
|
||||
=item B<Signature>
|
||||
|
||||
Signature computed with sign(), a string.
|
||||
|
||||
=back
|
||||
|
||||
=head1 ERROR HANDLING
|
||||
|
||||
See ERROR HANDLING in Crypt::RSA(3) manpage.
|
||||
|
||||
=head1 BIBLIOGRAPHY
|
||||
|
||||
See BIBLIOGRAPHY in Crypt::RSA(3) manpage.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Vipul Ved Prakash, E<lt>mail@vipul.netE<gt>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Crypt::RSA(3), Crypt::RSA::Primitives(3), Crypt::RSA::Keys(3),
|
||||
Crypt::RSA::EME::OAEP(3)
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
271
database/perl/vendor/lib/Crypt/RSA/SS/PSS.pm
vendored
Normal file
271
database/perl/vendor/lib/Crypt/RSA/SS/PSS.pm
vendored
Normal file
@@ -0,0 +1,271 @@
|
||||
package Crypt::RSA::SS::PSS;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
## Crypt::RSA::SS:PSS
|
||||
##
|
||||
## Copyright (c) 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.
|
||||
|
||||
use base 'Crypt::RSA::Errorhandler';
|
||||
use Math::Prime::Util qw/random_bytes/;
|
||||
use Crypt::RSA::DataFormat qw(octet_len os2ip i2osp octet_xor mgf1);
|
||||
use Crypt::RSA::Primitives;
|
||||
use Crypt::RSA::Debug qw(debug);
|
||||
use Digest::SHA qw(sha1);
|
||||
|
||||
$Crypt::RSA::SS::PSS::VERSION = '1.99';
|
||||
|
||||
sub new {
|
||||
my ($class, %params) = @_;
|
||||
my $self = bless { primitives => new Crypt::RSA::Primitives,
|
||||
hlen => 20,
|
||||
VERSION => $Crypt::RSA::SS::PSS::VERSION,
|
||||
}, $class;
|
||||
if ($params{Version}) {
|
||||
# do versioning here
|
||||
}
|
||||
return $self;
|
||||
}
|
||||
|
||||
|
||||
sub sign {
|
||||
my ($self, %params) = @_;
|
||||
my $key = $params{Key}; my $M = $params{Message} || $params{Plaintext};
|
||||
return $self->error("No Key parameter", \$M, \%params) unless $key;
|
||||
return $self->error("No Message or Plaintext parameter", \$key, \%params) unless $M;
|
||||
my $k = octet_len ($key->n);
|
||||
my $salt = random_bytes($self->{hlen});
|
||||
my $em = $self->encode ($M, $salt, $k-1);
|
||||
my $m = os2ip ($em);
|
||||
my $sig = $self->{primitives}->core_sign (Key => $key, Message => $m);
|
||||
my $S = i2osp ($sig, $k);
|
||||
return ($S, $salt) if wantarray;
|
||||
return $S;
|
||||
}
|
||||
|
||||
|
||||
sub verify_with_salt {
|
||||
my ($self, %params) = @_;
|
||||
my $key = $params{Key}; my $M = $params{Message} || $params{Plaintext};
|
||||
my $S = $params{Signature}; my $salt = $params{Salt};
|
||||
return $self->error("No Key parameter", \$S, \%params) unless $key;
|
||||
return $self->error("No Signature parameter", \$key, \%params) unless $S;
|
||||
my $k = octet_len ($key->n);
|
||||
my $em;
|
||||
unless ($em = $self->encode ($M, $salt, $k-1)) {
|
||||
return if $self->errstr eq "Message too long.";
|
||||
return $self->error ("Modulus too short.", \$M, \$S, \$key, \%params) if
|
||||
$self->errstr eq "Intended encoded message length too short.";
|
||||
}
|
||||
return $self->error ("Invalid signature.", \$M, \$S, $key, \%params) if length($S) < $k;
|
||||
my $s = os2ip ($S);
|
||||
my $m = $self->{primitives}->core_verify (Key => $key, Signature => $s) ||
|
||||
$self->error ("Invalid signature.", \$M, \$S, $key, \%params);
|
||||
my $em1 = i2osp ($m, $k-1) ||
|
||||
return $self->error ("Invalid signature.", \$M, \$S, $key, \%params);
|
||||
return 1 if $em eq $em1;
|
||||
return $self->error ("Invalid signature.", \$M, \$S, $key, \%params);
|
||||
}
|
||||
|
||||
|
||||
sub verify {
|
||||
my ($self, %params) = @_;
|
||||
my $key = $params{Key}; my $M = $params{Message} || $params{Plaintext};
|
||||
my $S = $params{Signature};
|
||||
return $self->error("No Key parameter", \$S, \$M, \%params) unless $key;
|
||||
return $self->error("No Signature parameter", \$key, \$M, \%params) unless $S;
|
||||
return $self->error("No Message or Plaintext parameter", \$key, \$S, \%params) unless $M;
|
||||
my $k = octet_len ($key->n);
|
||||
my $s = os2ip ($S);
|
||||
my $m = $self->{primitives}->core_verify (Key => $key, Signature => $s) ||
|
||||
$self->error ("Invalid signature.", \$M, \$S, $key, \%params);
|
||||
my $em1 = i2osp ($m, $k-1) ||
|
||||
return $self->error ("Invalid signature.", \$M, \$S, $key, \%params);
|
||||
return 1 if $self->verify_with_salt_recovery ($M, $em1);
|
||||
return $self->error ("Invalid signature.", \$M, \$S, $key, \%params);
|
||||
}
|
||||
|
||||
|
||||
sub encode {
|
||||
my ($self, $M, $salt, $emlen) = @_;
|
||||
return $self->error ("Intended encoded message length too short.", \$M, \$salt )
|
||||
if $emlen < 2 * $self->{hlen};
|
||||
my $H = $self->hash ("$salt$M");
|
||||
my $padlength = $emlen - (2*$$self{hlen});
|
||||
my $PS = chr(0)x$padlength;
|
||||
my $db = $salt . $PS;
|
||||
my $dbmask = $self->mgf ($H, $emlen - $self->{hlen});
|
||||
my $maskeddb = octet_xor ($db, $dbmask);
|
||||
my $em = $H . $maskeddb;
|
||||
return $em;
|
||||
}
|
||||
|
||||
|
||||
sub verify_with_salt_recovery {
|
||||
my ($self, $M, $EM) = @_;
|
||||
my $hlen = $$self{hlen};
|
||||
my $emlen = length ($EM);
|
||||
return $self->error ("Encoded message too short.", \$M, \$EM) if $emlen < (2*$hlen);
|
||||
my $H = substr $EM, 0, $hlen;
|
||||
my $maskeddb = substr $EM, $hlen;
|
||||
my $dbmask = $self->mgf ($H, $emlen-$hlen);
|
||||
my $db = octet_xor ($maskeddb, $dbmask);
|
||||
my $salt = substr $db, 0, $hlen;
|
||||
my $PS = substr $db, $hlen;
|
||||
my $check = chr(0) x ($emlen-(2*$hlen)); debug ("PS: $PS");
|
||||
return $self->error ("Inconsistent.") unless $check eq $PS;
|
||||
my $H1 = $self->hash ("$salt$M");
|
||||
return 1 if $H eq $H1;
|
||||
return $self->error ("Inconsistent.");
|
||||
}
|
||||
|
||||
|
||||
sub hash {
|
||||
my ($self, $data) = @_;
|
||||
return sha1 ($data);
|
||||
}
|
||||
|
||||
|
||||
sub mgf {
|
||||
my ($self, @data) = @_;
|
||||
return mgf1 (@data);
|
||||
}
|
||||
|
||||
|
||||
sub version {
|
||||
my $self = shift;
|
||||
return $self->{VERSION};
|
||||
}
|
||||
|
||||
|
||||
sub signblock {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
sub verifyblock {
|
||||
my ($self, %params) = @_;
|
||||
return octet_len($params{Key}->n);
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Crypt::RSA::SS::PSS - Probabilistic Signature Scheme based on RSA.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $pss = new Crypt::RSA::SS::PSS;
|
||||
|
||||
my $signature = $pss->sign (
|
||||
Message => $message,
|
||||
Key => $private,
|
||||
) || die $pss->errstr;
|
||||
|
||||
my $verify = $pss->verify (
|
||||
Message => $message,
|
||||
Key => $key,
|
||||
Signature => $signature,
|
||||
) || die $pss->errstr;
|
||||
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
PSS (Probabilistic Signature Scheme) is a provably secure method of
|
||||
creating digital signatures with RSA. "Provable" means that the
|
||||
difficulty of forging signatures can be directly related to inverting
|
||||
the RSA function. "Probabilistic" alludes to the randomly generated salt
|
||||
value included in the signature to enhance security. For more details
|
||||
on PSS, see [4] & [13].
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 B<new()>
|
||||
|
||||
Constructor.
|
||||
|
||||
=head2 B<version()>
|
||||
|
||||
Returns the version number of the module.
|
||||
|
||||
=head2 B<sign()>
|
||||
|
||||
Computes a PSS signature on a message with the private key of the signer.
|
||||
In scalar context, sign() returns the computed signature. In array
|
||||
context, it returns the signature and the random salt. The signature can
|
||||
verified with verify() or verify_with_salt(). sign() takes a hash argument
|
||||
with the following mandatory keys:
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<Message>
|
||||
|
||||
Message to be signed, a string of arbitrary length.
|
||||
|
||||
=item B<Key>
|
||||
|
||||
Private key of the signer, a Crypt::RSA::Key::Private object.
|
||||
|
||||
=back
|
||||
|
||||
=head2 B<verify()>
|
||||
|
||||
Verifies a signature generated with sign(). The salt is recovered from the
|
||||
signature and need not be passed. Returns a true value on success and
|
||||
false on failure. $self->errstr is set to "Invalid signature." or
|
||||
appropriate error on failure. verify() takes a hash argument with the
|
||||
following mandatory keys:
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<Key>
|
||||
|
||||
Public key of the signer, a Crypt::RSA::Key::Public object.
|
||||
|
||||
=item B<Message>
|
||||
|
||||
The original signed message, a string of arbitrary length.
|
||||
|
||||
=item B<Signature>
|
||||
|
||||
Signature computed with sign(), a string.
|
||||
|
||||
=item B<Version>
|
||||
|
||||
Version of the module that was used for creating the Signature. This is an
|
||||
optional argument. When present, verify() will ensure before proceeding
|
||||
that the installed version of the module can successfully verify the
|
||||
Signature.
|
||||
|
||||
=back
|
||||
|
||||
=head2 B<verify_with_salt()>
|
||||
|
||||
Verifies a signature given the salt. Takes the same arguments as verify()
|
||||
in addition to B<Salt>, which is a 20-byte string returned by sign() in
|
||||
array context.
|
||||
|
||||
=head1 ERROR HANDLING
|
||||
|
||||
See ERROR HANDLING in Crypt::RSA(3) manpage.
|
||||
|
||||
=head1 BIBLIOGRAPHY
|
||||
|
||||
See BIBLIOGRAPHY in Crypt::RSA(3) manpage.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Vipul Ved Prakash, E<lt>mail@vipul.netE<gt>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
Crypt::RSA(3), Crypt::RSA::Primitives(3), Crypt::RSA::Keys(3),
|
||||
Crypt::RSA::EME::OAEP(3)
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
Reference in New Issue
Block a user