One Hat Cyber Team
Your IP :
172.16.0.254
Server IP :
58.26.163.33
Server :
Windows NT DGPENSV2LPKMN 10.0 build 14393 (Windows Server 2016) AMD64
Server Software :
Apache/2.4.46 (Win64) OpenSSL/1.1.1h PHP/7.3.25
PHP Version :
7.3.25
Buat File
|
Buat Folder
Eksekusi
Dir :
C:
/
xampp7
/
perl
/
vendor
/
lib
/
Crypt
/
DSA
/
GMP
/
View File Name :
KeyChain.pm
package Crypt::DSA::GMP::KeyChain; use strict; use warnings; BEGIN { $Crypt::DSA::GMP::KeyChain::AUTHORITY = 'cpan:DANAJ'; $Crypt::DSA::GMP::KeyChain::VERSION = '0.01'; } use Carp qw( croak ); use Math::BigInt lib => "GMP"; use Math::Prime::Util::GMP qw/is_prob_prime is_provable_prime miller_rabin_random/; use Digest::SHA qw( sha1 sha1_hex sha256_hex); use Crypt::DSA::GMP::Key; use Crypt::DSA::GMP::Util qw( bin2mp bitsize mod_exp makerandomrange randombytes ); sub new { my ($class, @params) = @_; return bless { @params }, $class; } sub generate_params { my ($keygen, %param) = @_; croak "Size parameter missing" unless defined $param{Size}; my $bits = int($param{Size}); my $v = $param{Verbosity}; my $proveq = $param{Prove} && $param{Prove} !~ /^p$/i; my $provep = $param{Prove} && $param{Prove} !~ /^q$/i; croak "Number of bits (Size => $bits) is too small (min 256)" unless $bits >= 256; # TODO: # - strict FIPS 186-2 compliance requires L to be a multiple # of 64 512 <= L <= 1024. # - strict FIPS 186-3/4 compliance requires L,N to be one of # the pairs: (1024,160) (2048,224) (2048,256) (3072,256) # - Can we use new generation method if seed is null? # OpenSSL was removed: # 1. It was a portability issue (7 RTs related to it). # 2. It removes module dependencies. # 2. Security issues with running a program in the path without # verifying it is the correct executable. # 3. We know the code here follows FIPS 186-4. OpenSSL does not. # 4. The behavior of OpenSSL has changed across different versions. # 5. This code is faster for key sizes larger than 1024 bits. # Time for key generations (without proofs, average of 1000) # 512-bit 47ms Perl 25ms OpenSSL # 768-bit 78ms Perl 69ms OpenSSL # 1024-bit 139ms Perl 144ms OpenSSL # 2048-bit 783ms Perl 1,144ms OpenSSL # 4096-bit 7,269ms Perl 12,888ms OpenSSL $param{Standard} = $keygen->{Standard} if defined $keygen->{Standard} && !defined $param{Standard}; my $standard = (defined $param{Standard} && $param{Standard} =~ /186-[34]/) ? 'FIPS 186-4' : 'FIPS 186-2'; # $mrseed is just a random number we give to the primality test to give us # a unique sequence of bases. It's not that important other than (1) we # don't want the same sequence each call, (2) we don't want to leak any # information about our state, and (3) we don't want to spend too much # time/entropy on it. A truncated hash of our seed should work well. my($counter, $q, $p, $seed, $seedp1, $mrseed); if ($standard eq 'FIPS 186-2') { croak "FIPS 186-2 does not support Q sizes other than 160" if defined $param{QSize} && $param{QSize} != 160; # See FIPS 186-4 A.1.1.1, non-approved method. delete $param{Seed} if defined $param{Seed} && length($param{Seed}) != 20; my $n = int(($bits+159)/160)-1; my $b = $bits-1-($n*160); my $p_test = Math::BigInt->new(2)->bpow($bits-1); # 2^(L-1) do { ## Generate q while (1) { print STDERR "." if $v; $seed = (defined $param{Seed}) ? delete $param{Seed} : randombytes(20); $seedp1 = _seed_plus_one($seed); my $md = sha1($seed) ^ sha1($seedp1); vec($md, 0, 8) |= 0x80; vec($md, 19, 8) |= 0x01; $q = bin2mp($md); $mrseed = '0x'.substr(sha256_hex($seed),0,16) unless defined $mrseed; last if ( $proveq && is_provable_prime($q)) || (!$proveq && is_prob_prime($q) && miller_rabin_random($q, 19, $mrseed)); } print STDERR "*\n" if $v; ## Generate p. $counter = 0; my $q2 = Math::BigInt->new(2)->bmul($q); while ($counter < 4096) { print STDERR "." if $v; my $Wstr = ''; for my $j (0 .. $n) { $seedp1 = _seed_plus_one($seedp1); $Wstr = sha1_hex($seedp1) . $Wstr; } my $W = Math::BigInt->from_hex('0x'.$Wstr)->bmod($p_test); my $X = $W + $p_test; $p = $X - ( ($X % $q2) - 1); if ($p >= $p_test) { last if ( $provep && is_provable_prime($p)) || (!$provep && is_prob_prime($p) && miller_rabin_random($p, 3, $mrseed)); } $counter++; } } while ($counter >= 4096); # /\ /\ /\ /\ FIPS 186-2 /\ /\ /\ /\ # } else { # \/ \/ \/ \/ FIPS 186-4 \/ \/ \/ \/ # my $L = $bits; my $N = (defined $param{QSize}) ? $param{QSize} : ($bits >= 2048) ? 256 : 160; croak "Invalid Q size, must be between 1 and 512" if $N < 1 || $N > 512; croak "Invalid Q size, must be >= Size+8" if $L < $N+8; # See NIST SP 800-57 rev 3, table 3. sha256 is ok for all sizes my $outlen = ($N <= 256) ? 256 : ($N <= 384) ? 384 : 512; my $sha = Digest::SHA->new($outlen); croak "No digest available for Q size $N" unless defined $sha; my $n = int(($L+$outlen-1)/$outlen)-1; my $b = $L-1-($n*$outlen); my $p_test = Math::BigInt->new(2)->bpow($L-1); # 2^(L-1) my $q_test = Math::BigInt->new(2)->bpow($N-1); # 2^(N-1) my $seedlen = int( ($N+7)/8 ); my $nptests = ($L <= 2048) ? 3 : 2; # See FIPS 186-4 table C.1 my $nqtests = ($N <= 160) ? 19 : 27; delete $param{Seed} if defined $param{Seed} && length($param{Seed}) < $seedlen; $param{Seed} = substr($param{Seed}, 0, $seedlen) if defined $param{Seed}; do { ## Generate q while (1) { print STDERR "." if $v; $seed = (defined $param{Seed}) ? delete $param{Seed} : randombytes($seedlen); my $digest = $sha->reset->add($seed)->hexdigest; my $U = Math::BigInt->from_hex('0x'.$digest)->bmod($q_test); $q = $q_test + $U + 1 - $U->is_odd(); $mrseed = '0x'.substr(sha256_hex($seed),0,16) unless defined $mrseed; last if ( $proveq && is_provable_prime($q)) || (!$proveq && is_prob_prime($q) && miller_rabin_random($q, $nqtests, $mrseed)); } print STDERR "*\n" if $v; $seedp1 = $seed; ## Generate p. $counter = 0; my $q2 = Math::BigInt->new(2)->bmul($q); while ($counter < 4*$L) { print STDERR "." if $v; my $Wstr = ''; for my $j (0 .. $n) { $seedp1 = _seed_plus_one($seedp1); $Wstr = $sha->reset->add($seedp1)->hexdigest . $Wstr; } my $W = Math::BigInt->from_hex('0x'.$Wstr)->bmod($p_test); my $X = $W + $p_test; $p = $X - ( ($X % $q2) - 1); if ($p >= $p_test) { last if ( $provep && is_provable_prime($p)) || (!$provep && is_prob_prime($p) && miller_rabin_random($p, $nptests, $mrseed)); } $counter++; } } while ($counter >= 4*$L); } print STDERR "*" if $v; my $e = ($p - 1) / $q; my $h = Math::BigInt->bone; my $g; do { $g = mod_exp(++$h, $e, $p); } while $g == 1; print STDERR "\n" if $v; my $key = Crypt::DSA::GMP::Key->new; $key->p($p); $key->q($q); $key->g($g); return wantarray ? ($key, $counter, "$h", $seed) : $key; } # Using FIPS 186-4 B.1.2 approved method. sub generate_keys { my ($keygen, $key, $nonblock) = @_; my $q = $key->q; # Generate private key 0 < x < q, using best randomness source. my $priv_key = makerandomrange( Max => $q-2, KeyGen => !$nonblock ) + 1; my $pub_key = mod_exp($key->g, $priv_key, $key->p); $key->priv_key($priv_key); $key->pub_key($pub_key); } sub _seed_plus_one { my($s) = @_; for (my $i = length($s)-1; $i >= 0; $i--) { vec($s, $i, 8)++; last unless vec($s, $i, 8) == 0; } return $s; } 1; =pod =head1 NAME Crypt::DSA::GMP::KeyChain - DSA key generation system =head1 SYNOPSIS use Crypt::DSA::GMP::KeyChain; my $keychain = Crypt::DSA::GMP::KeyChain->new; my $key = $keychain->generate_params( Size => 512, Seed => $seed, Verbosity => 1, ); $keychain->generate_keys($key); =head1 DESCRIPTION L<Crypt::DSA::GMP::KeyChain> is a lower-level interface to key generation than the L<Crypt::DSA::GMP/keygen> method. It allows you to separately generate the I<p>, I<q>, and I<g> key parameters, given an optional starting seed, bit sizes for I<p> and I<q>, and which standard to follow for construction. You can then call I<generate_keys> to generate the public and private portions of the key. =head1 USAGE =head2 $keychain = Crypt::DSA::GMP::KeyChain->new Constructs and returns a new L<Crypt::DSA::GMP::KeyChain> object. At the moment this isn't particularly useful in itself, other than being the object you need in order to call the other methods. The standard to follow may be given in this call, where it will be used in all methods unless overridden. =head2 $key = $keychain->generate_params(%arg) Generates a set of DSA parameters: the I<p>, I<q>, and I<g> values of the key. This involves finding primes, and as such it can be a relatively long process. When invoked in scalar context, returns a new I<Crypt::DSA::GMP::Key> object. In list context, returns the new I<Crypt::DSA::GMP::Key> object along with: the value of the internal counter when a suitable prime I<p> was found; the value of I<h> when I<g> was derived; and the value of the seed (a 20-byte or 32-byte string) when I<q> was found. These values aren't particularly useful in normal circumstances, but they could be useful. I<%arg> can contain: =over 4 =item * Standard Indicates which standard is to be followed. By default, FIPS 186-2 is used, which maintains backward compatibility with the L<Crypt::DSA> Perl code and old OpenSSL versions. If C<FIPS 186-3> or C<FIPS 186-4> is given, then the FIPS 186-4 key generation will be used. The important changes made: - Using SHA-2 rather than SHA-1 for the CSPRNG. This produces better quality random data for prime generation. - Allows I<N> to vary between 1 and 512 rather than fixed at 160. - The default size for I<N> when not specified is 256 if I<L> is 2048 or larger, 160 otherwise. - In L<Crypt::DSA::GMP>, the signing and verification will use SHA-2 256 for signing and verification when I<N> E<lt>= 256, and SHA-2 512 otherwise. The old standard used SHA-1. where I<N> is the bit size of I<q>, and I<L> is the bit size of I<p>. These correspond to the I<QSize> and I<Size> arguments. The recommended primality tests from FIPS 186-4 are always performed, since they are more stringent than the older standard and have no negative impact on the result. =item * Size The size in bits of the I<p> value to generate. The minimum allowable value is 256, and must also be at least 8 bits larger than the size of I<q> (defaults to 160, see I<QSize>). For any use where security is a concern, 1024 bits should be considered a minimum size. NIST SP800-57 (July 2012) considers 1024 bit DSA using SHA-1 to be deprecated, with 2048 or more bits using SHA-2 to be acceptable. This argument is mandatory. =item * QSize The size in bits of the I<q> value to generate. For the default FIPS 186-2 standard, this must always be 160. If the FIPS 186-4 standard is used, then this may be in the range 1 to 512 (values less than 160 are strongly discouraged). If not specified, I<q> will be 160 bits if either the default FIPS 186-2 standard is used or if I<Size> is less than 2048. If FIPS 186-4 is used and I<Size> is 2048 or larger, then I<q> will be 256. =item * Seed A seed with which I<q> generation will begin. If this seed does not lead to a suitable prime, it will be discarded, and a new random seed chosen in its place, until a suitable prime can be found. A seed that is shorter than the size of I<q> will be immediately discarded. This is entirely optional, and if not provided a random seed will be generated automatically. Do not use this option unless you have a specific need for a starting seed. =item * Verbosity Should be either 0 or 1. A value of 1 will give you a progress meter during I<p> and I<q> generation -- this can be useful, since the process can be relatively long. The default is 0. =item * Prove Should be 0, 1, I<P>, or I<Q>. If defined and true, then both the primes for I<p> and I<q> will be proven primes. Setting to the string I<P> or I<Q> will result in just that prime being proven. Using this flag will guarantee the values are prime, which is valuable if security is extremely important. The current implementation constructs random primes using the method A.1.1.1, then ensures they are prime by constructing and verifying a primality proof, rather than using a constructive method such as the Maurer or Shawe-Taylor algorithms. The time for proof will depend on the platform and the Size parameter. Proving I<q> should take 100 milliseconds or less, but I<p> can take a very long time if over 1024 bits. The default is 0, which means the standard FIPS 186-4 probable prime tests are done. =back =head2 $keychain->generate_keys($key) Generates the public and private portions of the key I<$key>, a I<Crypt::DSA::GMP::Key> object. =head1 AUTHOR & COPYRIGHT See L<Crypt::DSA::GMP> for author, copyright, and license information. =cut