#!/usr/bin/perl -w use strict; use Getopt::Std; use ModToolkit qw(brand bprime mod_inverse gcd $bignumlib); use vars qw($opt_b $opt_f); getopts('b:f:'); # -b bits: number of bits (default 256) # -f file: write to file.pubkey and file.seckey, default is to print to STDOUT use integer; print STDERR "Bignumlib is $bignumlib\n"; my $two = $bignumlib->new(2); my $bits = $opt_b || 256; # determine number of bits for p my $pbits = $bits/4 + brand($bits/2); my $qbits = $bits - $pbits; print STDERR "p: "; my $p = bprime($two**$pbits); print $p, "\n" unless $opt_f; print STDERR "q: "; my $q = bprime($two**$qbits); print $q, "\n" unless $opt_f; my $n = $p * $q; my $p1q1 = ($p - 1) * ($q - 1); # choose $e as a small prime, make sure it is relatively prime to p1q1 my($d, $e); while ( 1 ) { print STDERR "e: "; $e = bprime(65536); # calculate private key $d = mod_inverse($e, $p1q1); if ( $d == 0 ) { print STDERR "e ($e) not prime to p1q1\n"; next; } if ( gcd($d, $n) != 1 ) { print STDERR "d ($d) and n not relatively prime\n"; next; } last; } if ( $opt_f ) { open(KEY, ">$opt_f.pubkey") or die "Write $opt_f.pubkey: $!\n"; print KEY "e: $e\n"; print KEY "n: $n\n"; close KEY; open(KEY, ">$opt_f.seckey") or die "Write $opt_f.seckey: $!\n"; print KEY "d: $d\n"; close KEY; chmod 0400, "$opt_f.seckey"; } else { print "PUBLIC KEY:\n"; print "e: $e\n"; print "n: $n\n"; print "PRIVATE KEY:\n"; print "d: $d\n"; }