1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

very first release

This commit is contained in:
Werner Koch 1997-12-20 17:23:29 +00:00
parent ee8d92fefa
commit cb5459aed7
20 changed files with 428 additions and 89 deletions

View File

@ -7,7 +7,7 @@
./configure --enable-m-debug ./configure --enable-m-debug
to ebanle the integrated malloc debugging stuff. to enable the integrated malloc debugging stuff.
2) Run make: 2) Run make:

133
README
View File

@ -1,20 +1,20 @@
G10 - The GNU Enryption and Signing Tool G10 - The GNU Encryption and Signing Tool
------------------------------------------ ------------------------------------------
THIS IS VERSION IS ONLY a TEST VERSION ! YOU SHOULD NOT THIS IS VERSION IS ONLY A TEST VERSION ! YOU SHOULD NOT
USE IT FOR OTHER PURPOSES THAN EVALUATING THE CURRENT CODE. USE IT FOR OTHER PURPOSES THAN EVALUATING THE CURRENT CODE.
* Only some parts work.
* The data format may change in the next version! * The data format may change in the next version!
* The code to generate keys is not secure! * Some features are not yet implemented
* Some features are not implemented
I provide this version as a reality check to start discussion. I provide this version as a reality check to start discussion.
Please subscribe to g10@net.lut.ac.uk be sending a mail with Please subscribe to g10@net.lut.ac.uk by sending a mail with
the word "subscribe" in the body to "g10-request@net.lut.ac.uk". the word "subscribe" in the body to "g10-request@net.lut.ac.uk".
@ -25,26 +25,139 @@
it cannot be compatible to old PGP versions, because those use it cannot be compatible to old PGP versions, because those use
IDEA (which is worldwide patented) and RSA (which is patented in IDEA (which is worldwide patented) and RSA (which is patented in
the United States until Sep 20, 2000). I'm sorry about this, but the United States until Sep 20, 2000). I'm sorry about this, but
this is the world we have created (e.g. by using propiertary software). this is the world we have created (e.g. by using proprietary software).
Because the OpenPGP standard is still a draft, G10 is not yet Because the OpenPGP standard is still a draft, G10 is not yet
compatible to it (or PGP 5) - but it will. The data structures compatible to it (or PGP 5) - but it will. The data structures
used are compatible with PGP 2.x, so it can parse an list such files used are compatible with PGP 2.x, so it can parse an list such files
and PGP should be able to parse data created by G10 and complain and PGP should be able to parse data created by G10 and complain
about unsupported alogorithms. about unsupported algorithms.
The default algorithms used by G10 are ElGamal for public-key The default algorithms used by G10 are ElGamal for public-key
encryption and signing; Blowfish with a 160 bit key for protecting encryption and signing; Blowfish with a 160 bit key for protecting
the secret-key components, conventional and session encryption; the secret-key components, conventional and session encryption;
RIPE MD-160 to create message digest. DSA, SHA-1 and CAST are RIPE MD-160 to create message digest. DSA, SHA-1 and CAST are
also implemented, but not used on default. I decided not also implemented, but not used on default. I decided not
to use DSA as default signing algorithm, cecause it allows only for to use DSA as default signing algorithm, because it allows only for
1024 bit keys and this may be not enough in a couple of years. 1024 bit keys and this may be not enough in a couple of years.
Key generation takes a long time and should be improved!
Resources
---------
G10 needs a directory "~/.g10" to store the default keyrings
and other files.
Key Generation
--------------
Create a key pair with this command:
g10 --gen-key
This asks some questions and then starts key generation. To create
good random numbers for prime number generation, it uses a /dev/random
which will emit only bytes if the kernel can gather enough entropy.
If you see no progress, you should start some other activities such
as a mouse moves or a "find /". Because we have no hardware device
to generate random we have to use this method.
Key generation shows progress by printing different characters to
stderr:
"." Miller-Rabin test failed.
"+" Miller-Rabin test succeeded.
"!" Reloading the pool with fresh prime numbers
"^" Checking a new value for the generator
"~" Issued during generator checks
"<" Size of one factor decreased
">" Size of one factor increased
The prime number for ElGamal is generated this way:
1) Make a prime number q of 160, 200, 240 bits (depending on the keysize).
2) Select the length of the other prime factors to be at least the size
of q and calculate the number of prime factors needed
3) Make a pool of prime number, each of the length determined in step 2
4) Get a new permutation out of the pool or continue with step 3
if we have tested all permutations.
5) Calculate a candidate prime p = 2 * q * p[1] * ... * p[n] + 1
6) Check that this prime has the correct length (this may change q if
it seems not to be possible to make a prime of the desired length)
7) Check whether this is a prime using trial divisions and the
Miller-Rabin test.
8) Continue with step 4 if we did not find a prime in step 7.
9) Find a generator for that prime.
Signatures
----------
To create a signature, use this:
g10 -s file
This creates a file file.g10 which is compressed and has a signature
attached.
g10 -sa file
Same as above, but file.g10 is ascii armored.
g10 -s -o out file
Creates a signature of file, but writes the output to the file "out".
Encryption
----------
To encrypt data use this:
g10 -e -r heine file
This encrypts files with the public key of "heine" and writes it
to "file.g10"
echo "hallo" | g10 -ea -r heine | mail heine
Ditto, but encrypts "hallo\n" and mails it as ascii armored message.
Debug Flags
-----------
Use the option "--debug n" to output debug informations. This option
can be used multiple times, all values are ORed; n maybe prefixed with
0x to use hex-values.
value used for
----- ----------------------------------------------
1 packet reading/writing
2 MPI details
4 ciphers and primes (may reveal sensitive data)
8 iobuf filter functions
16 iobuf stuff
32 memory allocation stuff
64 caching
128 show memory statistics at exit
Other Notes
-----------
This is work in progress, so you may find duplicated code fragments,
ugly data structures, weird usage of filenames and other thinks.
I will run "indent" over the source when making a real distribution,
but for now I stick to my own formatting rules.
Compression does not work always; this is the reason that "-z 0"
is the default.
This will be cleaned up of course.
The primary FTP site is "ftp://ftp.guug.de/pub/gcrypt/"
The primary WWW page is "http://www.d.shuttle.de/isil/g10.html"
Please direct bug reports to <g10-bugs@isil.d.shuttle.de> or better
post them to the mailing list <g10@net.lut.ac.uk>.
Have fun
Werner

1
TODO
View File

@ -5,7 +5,6 @@
* add a way to difference between errors and eof in the underflow/flush * add a way to difference between errors and eof in the underflow/flush
function of iobuf. function of iobuf.
* check that all output is filtered when displayed. * check that all output is filtered when displayed.
* keyring editing
* add trust stuff * add trust stuff
* make ttyio.c work (hide passwords etc..) * make ttyio.c work (hide passwords etc..)
* use correct ASN values for DEK encoding * use correct ASN values for DEK encoding

View File

@ -149,7 +149,7 @@ elg_generate( ELG_public_key *pk, ELG_secret_key *sk, unsigned nbits )
do { do {
if( DBG_CIPHER ) if( DBG_CIPHER )
fputc('.', stderr); fputc('.', stderr);
mpi_set_bytes( x, nbits, get_random_byte, 1 ); /* fixme: should be 2 */ mpi_set_bytes( x, nbits, get_random_byte, 2 );
} while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, p_min1 )<0 ) ); } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, p_min1 )<0 ) );
y = mpi_alloc(nbits/BITS_PER_MPI_LIMB); y = mpi_alloc(nbits/BITS_PER_MPI_LIMB);

View File

@ -52,7 +52,7 @@ generate_public_prime( unsigned nbits )
{ {
MPI prime; MPI prime;
prime = gen_prime( nbits, 0, 1 ); /* fixme: change to 2 */ prime = gen_prime( nbits, 0, 2 );
fputc('\n', stderr); fputc('\n', stderr);
return prime; return prime;
} }
@ -70,6 +70,8 @@ generate_elg_prime( unsigned pbits, unsigned qbits, MPI g )
MPI prime; /* prime test value */ MPI prime; /* prime test value */
byte *perms = NULL; byte *perms = NULL;
int i, j; int i, j;
int count1, count2;
unsigned nprime;
/* find number of needed prime factors */ /* find number of needed prime factors */
for(n=1; (pbits - qbits - 1) / n >= qbits; n++ ) for(n=1; (pbits - qbits - 1) / n >= qbits; n++ )
@ -80,33 +82,32 @@ generate_elg_prime( unsigned pbits, unsigned qbits, MPI g )
fbits = (pbits - qbits -1) / n; fbits = (pbits - qbits -1) / n;
while( qbits + n*fbits < pbits ) while( qbits + n*fbits < pbits )
qbits++; qbits++;
qbits++; /* one mpre to increase tzhe chance to get a weel formed prime*/ if( DBG_CIPHER )
log_debug("gen prime: pbits=%u qbits=%u fbits=%u n=%d\n", log_debug("gen prime: pbits=%u qbits=%u fbits=%u n=%d\n",
pbits, qbits, fbits, n ); pbits, qbits, fbits, n );
prime = mpi_alloc( (pbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB ); prime = mpi_alloc( (pbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB );
q = gen_prime( qbits, 0, 0 ); /* fixme: should be 2 */ q = gen_prime( qbits, 0, 2 );
fputc('\n', stderr);
/* allocate an array to hold the factors + 2 for later usage */ /* allocate an array to hold the factors + 2 for later usage */
factors = m_alloc_clear( (n+2) * sizeof *factors ); factors = m_alloc_clear( (n+2) * sizeof *factors );
/* make a pool of 2n+5 primes (this is an arbitrary value) */ /* make a pool of 3n+5 primes (this is an arbitrary value) */
m = n*2+5; m = n*3+5;
if( m < 20 ) if( m < 25 )
m = 20; m = 25;
pool = m_alloc_clear( m * sizeof *pool ); pool = m_alloc_clear( m * sizeof *pool );
/* permutate over the pool of primes */ /* permutate over the pool of primes */
count1=count2=0;
do { do {
next_try: next_try:
if( !perms ) { if( !perms ) {
/* allocate new primes */ /* allocate new primes */
for(i=0; i < m; i++ ) { for(i=0; i < m; i++ ) {
mpi_free(pool[i]); mpi_free(pool[i]);
pool[i] = gen_prime( fbits, 0, 0 ); /* fixme: should be 2 */ pool[i] = gen_prime( fbits, 0, 2 );
} }
fputc('\n', stderr);
/* init m_out_of_n() */ /* init m_out_of_n() */
perms = m_alloc_clear( m ); perms = m_alloc_clear( m );
for(i=0; i < n; i++ ) { for(i=0; i < n; i++ ) {
@ -131,18 +132,43 @@ generate_elg_prime( unsigned pbits, unsigned qbits, MPI g )
for(i=0; i < n; i++ ) for(i=0; i < n; i++ )
mpi_mul( prime, prime, factors[i] ); mpi_mul( prime, prime, factors[i] );
mpi_add_ui( prime, prime, 1 ); mpi_add_ui( prime, prime, 1 );
} while( !( mpi_get_nbits( prime ) == pbits && check_prime( prime )) ); nprime = mpi_get_nbits(prime);
putc('\n', stderr); if( nprime < pbits ) {
if( ++count1 > 20 ) {
count1 = 0;
qbits++;
fputc('>', stderr);
q = gen_prime( qbits, 0, 2 );
goto next_try;
}
}
else
count1 = 0;
if( nprime > pbits ) {
if( ++count2 > 20 ) {
count2 = 0;
qbits--;
fputc('<', stderr);
q = gen_prime( qbits, 0, 2 );
goto next_try;
}
}
else
count2 = 0;
} while( !(nprime == pbits && check_prime( prime )) );
log_mpidump( "prime : ", prime ); if( DBG_CIPHER ) {
log_mpidump( "factor q: ", q ); putc('\n', stderr);
for(i=0; i < n; i++ ) log_mpidump( "prime : ", prime );
log_mpidump( "factor pi: ", factors[i] ); log_mpidump( "factor q: ", q );
log_debug("bit sizes: prime=%u, q=%u",mpi_get_nbits(prime), mpi_get_nbits(q) ); for(i=0; i < n; i++ )
for(i=0; i < n; i++ ) log_mpidump( "factor pi: ", factors[i] );
fprintf(stderr, ", p%d=%u", i, mpi_get_nbits(factors[i]) ); log_debug("bit sizes: prime=%u, q=%u", mpi_get_nbits(prime), mpi_get_nbits(q) );
putc('\n', stderr); for(i=0; i < n; i++ )
fprintf(stderr, ", p%d=%u", i, mpi_get_nbits(factors[i]) );
putc('\n', stderr);
}
if( g ) { /* create a generator (start with 3)*/ if( g ) { /* create a generator (start with 3)*/
MPI tmp = mpi_alloc( mpi_get_nlimbs(prime) ); MPI tmp = mpi_alloc( mpi_get_nlimbs(prime) );
@ -155,22 +181,30 @@ generate_elg_prime( unsigned pbits, unsigned qbits, MPI g )
mpi_set_ui(g,2); mpi_set_ui(g,2);
do { do {
mpi_add_ui(g, g, 1); mpi_add_ui(g, g, 1);
log_mpidump("checking g: ", g ); if( DBG_CIPHER ) {
log_debug("checking g: ");
mpi_print( stderr, g, 1 );
}
else
fputc('^', stderr);
for(i=0; i < n+2; i++ ) { for(i=0; i < n+2; i++ ) {
log_mpidump(" against: ", factors[i] ); fputc('~', stderr);
mpi_fdiv_q(tmp, pmin1, factors[i] ); mpi_fdiv_q(tmp, pmin1, factors[i] );
/* (no mpi_pow(), but it is okay to use this with mod prime) */ /* (no mpi_pow(), but it is okay to use this with mod prime) */
mpi_powm(b, g, tmp, prime ); mpi_powm(b, g, tmp, prime );
if( !mpi_cmp_ui(b, 1) ) if( !mpi_cmp_ui(b, 1) )
break; break;
} }
} while( i < n ); if( DBG_CIPHER )
fputc('\n', stderr);
} while( i < n+2 );
mpi_free(factors[n+1]); mpi_free(factors[n+1]);
mpi_free(tmp); mpi_free(tmp);
mpi_free(b); mpi_free(b);
mpi_free(pmin1); mpi_free(pmin1);
log_mpidump("found g: ", g );
} }
if( !DBG_CIPHER )
putc('\n', stderr);
m_free( factors ); /* (factors are shallow copies) */ m_free( factors ); /* (factors are shallow copies) */
for(i=0; i < m; i++ ) for(i=0; i < m; i++ )
@ -232,7 +266,6 @@ gen_prime( unsigned nbits, int secret, int randomlevel )
} }
if( x ) if( x )
continue; /* found a multiple of a already known prime */ continue; /* found a multiple of a already known prime */
fputc('.', stderr);
mpi_add_ui( prime, prime, step ); mpi_add_ui( prime, prime, step );
@ -267,6 +300,7 @@ gen_prime( unsigned nbits, int secret, int randomlevel )
m_free(mods); m_free(mods);
return prime; return prime;
} }
fputc('.', stderr);
} }
fputc(':', stderr); /* restart with a new random value */ fputc(':', stderr); /* restart with a new random value */
} }
@ -289,7 +323,6 @@ check_prime( MPI prime )
if( mpi_divisible_ui( prime, x ) ) if( mpi_divisible_ui( prime, x ) )
return 0; return 0;
} }
fputc('.', stderr);
#if 0 #if 0
result = mpi_alloc( mpi_get_nlimbs(prime) ); result = mpi_alloc( mpi_get_nlimbs(prime) );
@ -308,6 +341,7 @@ check_prime( MPI prime )
/* perform stronger tests */ /* perform stronger tests */
if( is_prime(prime, 5, &count ) ) if( is_prime(prime, 5, &count ) )
return 1; /* is probably a prime */ return 1; /* is probably a prime */
fputc('.', stderr);
return 0; return 0;
} }

View File

@ -30,7 +30,7 @@
struct cache { struct cache {
int len; int len;
byte buffer[100]; /* fixme: should be allocalted with m_alloc_secure()*/ byte buffer[100]; /* fixme: should be allocated with m_alloc_secure()*/
}; };
static struct cache cache[3]; static struct cache cache[3];

View File

@ -1,6 +1,7 @@
## Process this file with automake to produce Makefile.in ## Process this file with automake to produce Makefile.in
INCLUDES = -I$(top_srcdir)/include INCLUDES = -I$(top_srcdir)/include
EXTRA_DIST = OPTIONS
bin_PROGRAMS = g10 bin_PROGRAMS = g10

View File

@ -39,6 +39,7 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@ transform = @program_transform_name@
INCLUDES = -I$(top_srcdir)/include INCLUDES = -I$(top_srcdir)/include
EXTRA_DIST = OPTIONS
bin_PROGRAMS = g10 bin_PROGRAMS = g10

135
g10/OPTIONS Normal file
View File

@ -0,0 +1,135 @@
# This is a sample option file
#
# Unless you you specify which option file to use with the
# commandline option "--options filename", g10 uses per
# default the file ~/.g10/options.
#
# An option file can contain all long options which are
# available in G10. If the first non white space character of
# a line is a '#', this line is ignored. Empty lines are also
# ignored.
#
# Here is a list of all possible options. Not of all them make
# sense in an option file; consider this as a complete option
# reference
add-key
# add key to the public keyring
armor
# create ascii armored output
batch
# batch mode: never ask
cache-all
# hold everything in memory
change-passphrase
# change the passphrase of your secret keyring
check
# check a signature
check-key
# check signatures on a key in the keyring
debug value|hexvalue
# set debugging flags,
debug-all
# enable full debugging
decrypt
# decrypt data (default)
delete-key
# remove key from public keyring,
detach-sign
# make a detached signature,
dry-run
# don't make any changes
encrypt
# encrypt data
fingerprint
# show the fingerprints,
gen-key
# generate a new key pair,
gen-prime
# Generate a prime.
# With one argument: take it as the bitsize and make a simple prime of
# this size
# With two arguments: Generate a prime, usable for DL algorithms.
# With three arguments: same as above, but a third argument indicates
# taht a generator should also be calculated.
keyring filename
# add this filename to the list of keyrings
local-user user-string
# use this user-string to sign or decrypt
no
# assume no on most questions
no-armor
# Assume the input data is not in ascii armored format.
no-default-keyring
# Do not add the default keyrings to the list of keyrings
options filename
# Ignored in option files.
output filename
# use filename for output
print-mds
# print all message digests of all give filenames
remote-user
# use this user-id for encryption"
secret-keyring filename
# add filename to the list of secret keyrings
sign
# make a signature
sign-key
# make a signature on a key in the keyring
# Argument is the userid of the key to sign.
# This looks for the key, displays the key and checks all
# existing signatures of this key. If the key is not yet signed
# by the default user (or the users given with "-l"), the programm
# displays the information of the key again, together with
# it's fingerprint and asked wehter it should be signed. This question
# is repeated for all users specified with "-l". The key is then signed
# and the keyring which contains the key is updated.
store
# simply packs the input data into a rfc1991 packet format
symmetric
# encrypt the input only with the symmetric (conventional) cipher.
# This asks for a passphrase.
test
# Used for testing some parts of the program
verbose
# Give more informations suring processing. If used 2 times, the input data
# is listed in detail.
yes
# assume yes on most questions

View File

@ -131,8 +131,9 @@ main( int argc, char **argv )
{ 515, "fingerprint", 0, "show the fingerprints"}, { 515, "fingerprint", 0, "show the fingerprints"},
{ 516, "print-mds" , 0, "print all message digests"}, { 516, "print-mds" , 0, "print all message digests"},
{ 517, "secret-keyring" ,2, "add this secret keyring to the list" }, { 517, "secret-keyring" ,2, "add this secret keyring to the list" },
{ 518, "config" , 2, "use this config file" }, { 518, "options" , 2, "read options from file" },
{ 519, "no-armor", 0, "\r"}, { 519, "no-armor", 0, "\r"},
{ 520, "no-default-keyring", 0, "\r" },
{0} }; {0} };
ARGPARSE_ARGS pargs; ARGPARSE_ARGS pargs;
@ -155,9 +156,10 @@ main( int argc, char **argv )
int parse_verbose = 0; int parse_verbose = 0;
int default_config =1; int default_config =1;
int errors=0; int errors=0;
int default_keyring = 1;
opt.compress = -1; /* defaults to default compression level */ opt.compress = 0; /* defaults to no compression level */
/* check wether we have a config file on the commandline */ /* check wether we have a config file on the commandline */
orig_argc = argc; orig_argc = argc;
@ -212,10 +214,7 @@ main( int argc, char **argv )
case 'z': opt.compress = pargs.r.ret_int; break; case 'z': opt.compress = pargs.r.ret_int; break;
case 'a': opt.armor = 1; opt.no_armor=0; break; case 'a': opt.armor = 1; opt.no_armor=0; break;
case 'c': action = aSym; break; case 'c': action = aSym; break;
case 'o': opt.outfile = pargs.r.ret_str; case 'o': opt.outfile = pargs.r.ret_str; break;
if( opt.outfile[0] == '-' && !opt.outfile[1] )
opt.outfile_is_stdout = 1;
break;
case 'e': action = action == aSign? aSignEncr : aEncr; break; case 'e': action = action == aSign? aSignEncr : aEncr; break;
case 'b': detached_sig = 1; case 'b': detached_sig = 1;
/* fall trough */ /* fall trough */
@ -257,6 +256,7 @@ main( int argc, char **argv )
} }
break; break;
case 519: opt.no_armor=1; opt.armor=0; break; case 519: opt.no_armor=1; opt.armor=0; break;
case 520: default_keyring = 0; break;
default : errors++; pargs.err = configfp? 1:2; break; default : errors++; pargs.err = configfp? 1:2; break;
} }
} }
@ -280,12 +280,12 @@ main( int argc, char **argv )
fputs(s, stderr); fputs(s, stderr);
} }
if( !sec_nrings ) { /* add default secret rings */ if( !sec_nrings || default_keyring ) { /* add default secret rings */
char *p = make_filename("~/.g10", "secring.g10", NULL ); char *p = make_filename("~/.g10", "secring.g10", NULL );
add_secret_keyring(p); add_secret_keyring(p);
m_free(p); m_free(p);
} }
if( !nrings ) { /* add default ring */ if( !nrings || default_keyring ) { /* add default ring */
char *p = make_filename("~/.g10", "pubring.g10", NULL ); char *p = make_filename("~/.g10", "pubring.g10", NULL );
add_keyring(p); add_keyring(p);
m_free(p); m_free(p);
@ -331,6 +331,7 @@ main( int argc, char **argv )
case aSignEncr: /* sign and encrypt the given file */ case aSignEncr: /* sign and encrypt the given file */
log_fatal("signing and encryption is not yet implemented\n");
usage(1); /* FIXME */ usage(1); /* FIXME */
break; break;

View File

@ -39,17 +39,6 @@
#endif #endif
static int
answer_is_yes( const char *s )
{
if( !stricmp(s, "yes") )
return 1;
if( *s == 'y' && !s[1] )
return 1;
if( *s == 'Y' && !s[1] )
return 1;
return 0;
}
static u16 static u16
@ -356,7 +345,7 @@ generate_keypair()
else if( algo == 3 ) { else if( algo == 3 ) {
algo = PUBKEY_ALGO_DSA; algo = PUBKEY_ALGO_DSA;
algo_name = "DSA"; algo_name = "DSA";
break; tty_printf("Sorry; DSA is not yet supported.\n");
} }
} }
@ -380,8 +369,8 @@ generate_keypair()
#endif #endif
if( algo == PUBKEY_ALGO_DSA && (nbits < 512 || nbits > 1024) ) if( algo == PUBKEY_ALGO_DSA && (nbits < 512 || nbits > 1024) )
tty_printf("DSA does only allow keysizes from 512 to 1024\n"); tty_printf("DSA does only allow keysizes from 512 to 1024\n");
else if( nbits < 128 ) /* FIXME: change this to 768 */ else if( nbits < 768 )
tty_printf("keysize too small; please select a larger one\n"); tty_printf("keysize too small; 768 is smallest value allowed.\n");
else if( nbits > 2048 ) { else if( nbits > 2048 ) {
tty_printf("Keysizes larger than 2048 are not suggested, because " tty_printf("Keysizes larger than 2048 are not suggested, because "
"computations take REALLY long!\n"); "computations take REALLY long!\n");
@ -441,20 +430,28 @@ generate_keypair()
tty_printf( "You need a Passphrase to protect your secret key.\n\n" ); tty_printf( "You need a Passphrase to protect your secret key.\n\n" );
dek = m_alloc_secure( sizeof *dek ); dek = m_alloc_secure( sizeof *dek );
dek->algo = CIPHER_ALGO_BLOWFISH; for(;;) {
rc = make_dek_from_passphrase( dek , 2 ); dek->algo = CIPHER_ALGO_BLOWFISH;
if( rc == -1 ) { rc = make_dek_from_passphrase( dek , 2 );
m_free(dek); dek = NULL; if( rc == -1 ) {
tty_printf( m_free(dek); dek = NULL;
tty_printf(
"You don't what a passphrase - this is probably a *bad* idea!\n" "You don't what a passphrase - this is probably a *bad* idea!\n"
"I will do it anyway. You can change your passphrase at anytime,\n" "I will do it anyway. You can change your passphrase at anytime,\n"
"using this program with the option \"--change-passphrase\"\n\n" ); "using this program with the option \"--change-passphrase\"\n\n" );
} break;
else if( rc ) { }
m_free(dek); dek = NULL; else if( rc == G10ERR_PASSPHRASE ) {
m_free(uid); tty_printf("passphrase not correctly repeated; try again.\n");
log_error("Error getting the passphrase: %s\n", g10_errstr(rc) ); }
return; else if( rc ) {
m_free(dek); dek = NULL;
m_free(uid);
log_error("Error getting the passphrase: %s\n", g10_errstr(rc) );
return;
}
else
break; /* okay */
} }
@ -474,6 +471,12 @@ generate_keypair()
pub_root = make_comment_node("#created by G10 pre-release " VERSION ); pub_root = make_comment_node("#created by G10 pre-release " VERSION );
sec_root = make_comment_node("#created by G10 pre-release " VERSION ); sec_root = make_comment_node("#created by G10 pre-release " VERSION );
tty_printf(
"We need to generate a lot of random bytes. It is a good idea to perform\n"
"some other action (work in another window, move the mouse, utilize the\n"
"network and the disks) during the prime generation; this gives the random\n"
"number generator a better chance to gain enough entropy.\n" );
if( algo == PUBKEY_ALGO_ELGAMAL ) if( algo == PUBKEY_ALGO_ELGAMAL )
rc = gen_elg(nbits, pub_root, sec_root, dek, &skc ); rc = gen_elg(nbits, pub_root, sec_root, dek, &skc );
#ifdef HAVE_RSA_CIPHER #ifdef HAVE_RSA_CIPHER

View File

@ -37,6 +37,9 @@ int encode_crypt( const char *filename, STRLIST remusr );
int sign_file( const char *filename, int detached, STRLIST locusr ); int sign_file( const char *filename, int detached, STRLIST locusr );
int sign_key( const char *username, STRLIST locusr ); int sign_key( const char *username, STRLIST locusr );
/*-- sig-check.c --*/
int check_key_signature( KBNODE root, KBNODE node );
/*-- keygen.c --*/ /*-- keygen.c --*/
void generate_keypair(void); void generate_keypair(void);

View File

@ -87,7 +87,7 @@ open_outfile( const char *iname )
IOBUF a = NULL; IOBUF a = NULL;
int rc; int rc;
if( (!iname && !opt.outfile) || opt.outfile_is_stdout ) { if( !iname && !opt.outfile ) {
if( !(a = iobuf_create(NULL)) ) if( !(a = iobuf_create(NULL)) )
log_error("can't open [stdout]: %s\n", strerror(errno) ); log_error("can't open [stdout]: %s\n", strerror(errno) );
else if( opt.verbose ) else if( opt.verbose )

View File

@ -26,7 +26,7 @@ struct {
int armor; int armor;
int compress; int compress;
char *outfile; char *outfile;
int outfile_is_stdout; int reserved0;
int batch; /* run in batch mode */ int batch; /* run in batch mode */
int answer_yes; /* answer yes on most questions */ int answer_yes; /* answer yes on most questions */
int answer_no; /* answer no on most questions */ int answer_no; /* answer no on most questions */

View File

@ -27,6 +27,7 @@
#include "memory.h" #include "memory.h"
#include "ttyio.h" #include "ttyio.h"
#include "cipher.h" #include "cipher.h"
#include "keydb.h"
static int hash_passphrase( DEK *dek, char *pw ); static int hash_passphrase( DEK *dek, char *pw );
@ -44,8 +45,14 @@ get_passphrase_hash( u32 *keyid, char *text )
DEK *dek; DEK *dek;
if( keyid ) { if( keyid ) {
char *ustr;
tty_printf("\nNeed a pass phrase to unlock the secret key!\n"); tty_printf("\nNeed a pass phrase to unlock the secret key!\n");
tty_printf("KeyID: %08lX\n\n", keyid[1] ); tty_printf("KeyID: " );
ustr = get_user_id_string( keyid );
tty_print_string( ustr, strlen(ustr) );
m_free(ustr);
tty_printf("\n\n");
} }
if( keyid && (p=getenv("G10PASSPHRASE")) ) { if( keyid && (p=getenv("G10PASSPHRASE")) ) {
pw = m_alloc_secure(strlen(p)+1); pw = m_alloc_secure(strlen(p)+1);

View File

@ -56,13 +56,8 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx )
fname[pt->namelen] = 0; fname[pt->namelen] = 0;
} }
if( !*fname ) { /* no filename given */ if( !*fname ) { /* no filename given; write to stdout */
if( opt.outfile_is_stdout ) fp = stdout;
fp = stdout;
else {
log_error("no outputfile given\n");
goto leave;
}
} }
else if( overwrite_filep( fname ) ) else if( overwrite_filep( fname ) )
goto leave; goto leave;

View File

@ -558,7 +558,7 @@ keyring_delete( KBPOS *kbpos )
} }
len = kbpos->length; len = kbpos->length;
log_debug("writing a dummy packet of length %lu\n", (ulong)len); /*log_debug("writing a dummy packet of length %lu\n", (ulong)len);*/
if( len < 2 ) if( len < 2 )
log_bug(NULL); log_bug(NULL);

View File

@ -198,8 +198,8 @@ signature_check( PKT_signature *sig, MD_HANDLE *digest )
} }
#endif/*HAVE_RSA_CIPHER*/ #endif/*HAVE_RSA_CIPHER*/
else { else {
log_debug("signature_check: unsupported pubkey algo %d\n", /*log_debug("signature_check: unsupported pubkey algo %d\n",
pkc->pubkey_algo ); pkc->pubkey_algo );*/
rc = G10ERR_PUBKEY_ALGO; rc = G10ERR_PUBKEY_ALGO;
goto leave; goto leave;
} }
@ -219,13 +219,46 @@ signature_check( PKT_signature *sig, MD_HANDLE *digest )
int int
check_key_signature( KBNODE root, KBNODE node ) check_key_signature( KBNODE root, KBNODE node )
{ {
KBNODE unode;
MD_HANDLE *md;
PKT_public_cert *pkc;
PKT_signature *sig;
int algo;
int rc;
assert( node->pkt->pkttype == PKT_SIGNATURE ); assert( node->pkt->pkttype == PKT_SIGNATURE );
assert( (node->pkt->pkt.signature->sig_class&~3) == 0x10 ); assert( (node->pkt->pkt.signature->sig_class&~3) == 0x10 );
assert( root->pkt->pkttype == PKT_PUBLIC_CERT ); assert( root->pkt->pkttype == PKT_PUBLIC_CERT );
/*FIXME!!!!!!*/ pkc = root->pkt->pkt.public_cert;
sig = node->pkt->pkt.signature;
return 0; if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
algo = sig->d.elg.digest_algo;
else if(sig->pubkey_algo == PUBKEY_ALGO_RSA )
algo = sig->d.rsa.digest_algo;
else
return G10ERR_PUBKEY_ALGO;
if( (rc=md_okay(algo)) )
return rc;
unode = find_kbparent( root, node );
if( unode && unode->pkt->pkttype == PKT_USER_ID ) {
PKT_user_id *uid = unode->pkt->pkt.user_id;
md = md_open( algo, 0 );
hash_public_cert( md, pkc );
md_write( md, uid->name, uid->len );
rc = signature_check( sig, md );
md_close(md);
}
else {
log_error("no user id for key signature packet\n");
rc = G10ERR_SIG_CLASS;
}
return rc;
} }

View File

@ -84,6 +84,7 @@ char *make_filename( const char *first_part, ... );
/*-- miscutil.c --*/ /*-- miscutil.c --*/
u32 make_timestamp(void); u32 make_timestamp(void);
void print_string( FILE *fp, byte *p, size_t n ); void print_string( FILE *fp, byte *p, size_t n );
int answer_is_yes( const char *s );
/*-- strgutil.c --*/ /*-- strgutil.c --*/
void free_strlist( STRLIST sl ); void free_strlist( STRLIST sl );

View File

@ -20,6 +20,7 @@
#include <config.h> #include <config.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <time.h> #include <time.h>
#include <ctype.h> #include <ctype.h>
#include "types.h" #include "types.h"
@ -52,3 +53,15 @@ print_string( FILE *fp, byte *p, size_t n )
putc(*p, fp); putc(*p, fp);
} }
int
answer_is_yes( const char *s )
{
if( !stricmp(s, "yes") )
return 1;
if( *s == 'y' && !s[1] )
return 1;
if( *s == 'Y' && !s[1] )
return 1;
return 0;
}