mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
add DSA key generation
This commit is contained in:
parent
42b03f6ebd
commit
69cf10ffab
2
THANKS
2
THANKS
@ -24,6 +24,8 @@ Ulf M
|
|||||||
Walter Koch walterk@ddorf.rhein-ruhr.de
|
Walter Koch walterk@ddorf.rhein-ruhr.de
|
||||||
Werner Koch werner.koch@guug.de
|
Werner Koch werner.koch@guug.de
|
||||||
Wim Vandeputte bunbun@reptile.rug.ac.be
|
Wim Vandeputte bunbun@reptile.rug.ac.be
|
||||||
|
tzeruch@ceddec.com
|
||||||
|
|
||||||
|
|
||||||
Thanks to the German Unix User Group for providing FTP space and
|
Thanks to the German Unix User Group for providing FTP space and
|
||||||
Martin Hamilton for hosting the mailing list.
|
Martin Hamilton for hosting the mailing list.
|
||||||
|
2
TODO
2
TODO
@ -47,3 +47,5 @@
|
|||||||
|
|
||||||
* add readline support (but how can we allcoate it in secure memory?)
|
* add readline support (but how can we allcoate it in secure memory?)
|
||||||
|
|
||||||
|
* add a testcase for --print-mds
|
||||||
|
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
Tue May 5 21:28:55 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||||
|
|
||||||
|
* elgamal.c (elg_generate): choosing x was not correct, could
|
||||||
|
yield 6 bytes which are not from the random pool, tsss, tsss..
|
||||||
|
|
||||||
|
Tue May 5 14:09:06 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||||
|
|
||||||
|
* primegen.c (generate_elg_prime): Add arg mode, changed all
|
||||||
|
callers and implemented mode 1.
|
||||||
|
|
||||||
Mon Apr 27 14:41:58 1998 Werner Koch (wk@isil.d.shuttle.de)
|
Mon Apr 27 14:41:58 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||||
|
|
||||||
* cipher.c (cipher_get_keylen): New.
|
* cipher.c (cipher_get_keylen): New.
|
||||||
|
118
cipher/dsa.c
118
cipher/dsa.c
@ -22,6 +22,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "mpi.h"
|
#include "mpi.h"
|
||||||
#include "cipher.h"
|
#include "cipher.h"
|
||||||
@ -74,6 +75,123 @@ dsa_free_secret_key( DSA_secret_key *sk )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_keys( DSA_public_key *pk, DSA_secret_key *sk, unsigned qbits )
|
||||||
|
{
|
||||||
|
MPI test = mpi_alloc( qbits / BITS_PER_MPI_LIMB );
|
||||||
|
MPI out1_a = mpi_alloc( qbits / BITS_PER_MPI_LIMB );
|
||||||
|
MPI out1_b = mpi_alloc( qbits / BITS_PER_MPI_LIMB );
|
||||||
|
|
||||||
|
mpi_set_bytes( test, qbits, get_random_byte, 0 );
|
||||||
|
|
||||||
|
dsa_sign( out1_a, out1_b, test, sk );
|
||||||
|
if( !dsa_verify( out1_a, out1_b, test, pk ) )
|
||||||
|
log_fatal("DSA:: sign, verify failed\n");
|
||||||
|
|
||||||
|
mpi_free( test );
|
||||||
|
mpi_free( out1_a );
|
||||||
|
mpi_free( out1_b );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/****************
|
||||||
|
* Generate a DSA key pair with a key of size NBITS
|
||||||
|
* Returns: 2 structures filled with all needed values
|
||||||
|
* and an array with the n-1 factors of (p-1)
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
dsa_generate( DSA_public_key *pk, DSA_secret_key *sk,
|
||||||
|
unsigned nbits, MPI **ret_factors )
|
||||||
|
{
|
||||||
|
MPI p; /* the prime */
|
||||||
|
MPI q; /* the 160 bit prime factor */
|
||||||
|
MPI g; /* the generator */
|
||||||
|
MPI y; /* g^x mod p */
|
||||||
|
MPI x; /* the secret exponent */
|
||||||
|
MPI h, e; /* helper */
|
||||||
|
unsigned qbits;
|
||||||
|
byte *rndbuf;
|
||||||
|
|
||||||
|
assert( nbits >= 512 && nbits <= 1024 );
|
||||||
|
|
||||||
|
qbits = 160;
|
||||||
|
p = generate_elg_prime( 1, nbits, qbits, NULL, ret_factors );
|
||||||
|
/* get q out of factors */
|
||||||
|
q = mpi_copy((*ret_factors)[0]);
|
||||||
|
if( mpi_get_nbits(q) != qbits )
|
||||||
|
BUG();
|
||||||
|
|
||||||
|
/* find a generator g (h and e are helpers)*/
|
||||||
|
/* e = (p-1)/q */
|
||||||
|
e = mpi_alloc( mpi_get_nlimbs(p) );
|
||||||
|
mpi_sub_ui( e, p, 1 );
|
||||||
|
mpi_fdiv_q( e, e, q );
|
||||||
|
g = mpi_alloc( mpi_get_nlimbs(p) );
|
||||||
|
h = mpi_alloc_set_ui( 1 ); /* we start with 2 */
|
||||||
|
do {
|
||||||
|
mpi_add_ui( h, h, 1 );
|
||||||
|
/* g = h^e mod p */
|
||||||
|
mpi_powm( g, h, e, p );
|
||||||
|
} while( !mpi_cmp_ui( g, 1 ) ); /* continue until g != 1 */
|
||||||
|
|
||||||
|
/* select a random number which has these properties:
|
||||||
|
* 0 < x < q-1
|
||||||
|
* This must be a very good random number because this
|
||||||
|
* is the secret part. */
|
||||||
|
if( DBG_CIPHER )
|
||||||
|
log_debug("choosing a random x ");
|
||||||
|
assert( qbits >= 16 );
|
||||||
|
x = mpi_alloc_secure( mpi_get_nlimbs(q) );
|
||||||
|
mpi_sub_ui( h, q, 1 ); /* put q-1 into h */
|
||||||
|
rndbuf = NULL;
|
||||||
|
do {
|
||||||
|
if( DBG_CIPHER )
|
||||||
|
fputc('.', stderr);
|
||||||
|
if( !rndbuf )
|
||||||
|
rndbuf = get_random_bits( qbits, 2, 1 );
|
||||||
|
else { /* change only some of the higher bits (= 2 bytes)*/
|
||||||
|
char *r = get_random_bits( 16, 2, 1 );
|
||||||
|
memcpy(rndbuf, r, 16/8 );
|
||||||
|
m_free(r);
|
||||||
|
}
|
||||||
|
mpi_set_buffer( x, rndbuf, (qbits+7)/8, 0 );
|
||||||
|
mpi_clear_highbit( x, qbits+1 );
|
||||||
|
} while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, h )<0 ) );
|
||||||
|
m_free(rndbuf);
|
||||||
|
mpi_free( e );
|
||||||
|
mpi_free( h );
|
||||||
|
|
||||||
|
/* y = g^x mod p */
|
||||||
|
y = mpi_alloc( mpi_get_nlimbs(p) );
|
||||||
|
mpi_powm( y, g, x, p );
|
||||||
|
|
||||||
|
if( DBG_CIPHER ) {
|
||||||
|
fputc('\n', stderr);
|
||||||
|
log_mpidump("dsa p= ", p );
|
||||||
|
log_mpidump("dsa q= ", q );
|
||||||
|
log_mpidump("dsa g= ", g );
|
||||||
|
log_mpidump("dsa y= ", y );
|
||||||
|
log_mpidump("dsa x= ", x );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy the stuff to the key structures */
|
||||||
|
pk->p = mpi_copy(p);
|
||||||
|
pk->q = mpi_copy(q);
|
||||||
|
pk->g = mpi_copy(g);
|
||||||
|
pk->y = mpi_copy(y);
|
||||||
|
sk->p = p;
|
||||||
|
sk->q = q;
|
||||||
|
sk->g = g;
|
||||||
|
sk->y = y;
|
||||||
|
sk->x = x;
|
||||||
|
|
||||||
|
/* now we can test our keys (this should never fail!) */
|
||||||
|
test_keys( pk, sk, qbits );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
/****************
|
||||||
* Test whether the secret key is valid.
|
* Test whether the secret key is valid.
|
||||||
* Returns: if this is a valid key.
|
* Returns: if this is a valid key.
|
||||||
|
@ -41,8 +41,9 @@ typedef struct {
|
|||||||
|
|
||||||
void dsa_free_public_key( DSA_public_key *pk );
|
void dsa_free_public_key( DSA_public_key *pk );
|
||||||
void dsa_free_secret_key( DSA_secret_key *sk );
|
void dsa_free_secret_key( DSA_secret_key *sk );
|
||||||
void dsa_generate( DSA_public_key *pk, DSA_secret_key *sk, unsigned nbits );
|
|
||||||
int dsa_check_secret_key( DSA_secret_key *sk );
|
int dsa_check_secret_key( DSA_secret_key *sk );
|
||||||
|
void dsa_generate( DSA_public_key *pk, DSA_secret_key *sk,
|
||||||
|
unsigned nbits, MPI **ret_factors );
|
||||||
void dsa_sign(MPI r, MPI s, MPI input, DSA_secret_key *skey);
|
void dsa_sign(MPI r, MPI s, MPI input, DSA_secret_key *skey);
|
||||||
int dsa_verify(MPI r, MPI s, MPI input, DSA_public_key *pkey);
|
int dsa_verify(MPI r, MPI s, MPI input, DSA_public_key *pkey);
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ elg_generate( ELG_public_key *pk, ELG_secret_key *sk,
|
|||||||
else
|
else
|
||||||
qbits = 240;
|
qbits = 240;
|
||||||
g = mpi_alloc(1);
|
g = mpi_alloc(1);
|
||||||
p = generate_elg_prime( nbits, qbits, g, ret_factors );
|
p = generate_elg_prime( 0, nbits, qbits, g, ret_factors );
|
||||||
mpi_sub_ui(p_min1, p, 1);
|
mpi_sub_ui(p_min1, p, 1);
|
||||||
|
|
||||||
|
|
||||||
@ -163,7 +163,7 @@ elg_generate( ELG_public_key *pk, ELG_secret_key *sk,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
char *r = get_random_bits( 16, 2, 1 );
|
char *r = get_random_bits( 16, 2, 1 );
|
||||||
memcpy(rndbuf, r, 16 );
|
memcpy(rndbuf, r, 16/8 );
|
||||||
m_free(r);
|
m_free(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,37 +63,49 @@ generate_public_prime( unsigned nbits )
|
|||||||
* security from it - The prime number is public and we could also
|
* security from it - The prime number is public and we could also
|
||||||
* offer the factors for those who are willing to check that it is
|
* offer the factors for those who are willing to check that it is
|
||||||
* indeed a strong prime.
|
* indeed a strong prime.
|
||||||
|
*
|
||||||
|
* mode 0: Standard
|
||||||
|
* 1: Make sure that at least one factor is of size qbits.
|
||||||
*/
|
*/
|
||||||
MPI
|
MPI
|
||||||
generate_elg_prime( unsigned pbits, unsigned qbits, MPI g, MPI **ret_factors )
|
generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
|
||||||
|
MPI g, MPI **ret_factors )
|
||||||
{
|
{
|
||||||
int n; /* number of factors */
|
int n; /* number of factors */
|
||||||
int m; /* number of primes in pool */
|
int m; /* number of primes in pool */
|
||||||
unsigned fbits; /* length of prime factors */
|
unsigned fbits; /* length of prime factors */
|
||||||
MPI *factors; /* current factors */
|
MPI *factors; /* current factors */
|
||||||
MPI *pool; /* pool of primes */
|
MPI *pool; /* pool of primes */
|
||||||
MPI q; /* first prime factor */
|
MPI q; /* first prime factor (variable)*/
|
||||||
MPI prime; /* prime test value */
|
MPI prime; /* prime test value */
|
||||||
|
MPI q_factor; /* used for mode 1 */
|
||||||
byte *perms = NULL;
|
byte *perms = NULL;
|
||||||
int i, j;
|
int i, j;
|
||||||
int count1, count2;
|
int count1, count2;
|
||||||
unsigned nprime;
|
unsigned nprime;
|
||||||
|
unsigned req_qbits = qbits; /* the requested q bits size */
|
||||||
|
|
||||||
/* 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++ )
|
||||||
;
|
;
|
||||||
n--;
|
n--;
|
||||||
if( !n )
|
if( !n || (mode==1 && n < 2) )
|
||||||
log_fatal("can't gen prime with pbits=%u qbits=%u\n", pbits, qbits );
|
log_fatal("can't gen prime with pbits=%u qbits=%u\n", pbits, qbits );
|
||||||
fbits = (pbits - qbits -1) / n;
|
if( mode == 1 ) {
|
||||||
while( qbits + n*fbits < pbits )
|
n--;
|
||||||
qbits++;
|
fbits = (pbits - 2*req_qbits -1) / n;
|
||||||
|
qbits = pbits - req_qbits - n*fbits;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fbits = (pbits - req_qbits -1) / n;
|
||||||
|
qbits = pbits - n*fbits;
|
||||||
|
}
|
||||||
if( DBG_CIPHER )
|
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/%u n=%d\n",
|
||||||
pbits, qbits, fbits, n );
|
pbits, req_qbits, 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, 1 );
|
q = gen_prime( qbits, 0, 1 );
|
||||||
|
q_factor = mode==1? gen_prime( req_qbits, 0, 1 ) : NULL;
|
||||||
|
|
||||||
/* 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 );
|
||||||
@ -139,6 +151,8 @@ generate_elg_prime( unsigned pbits, unsigned qbits, MPI g, MPI **ret_factors )
|
|||||||
|
|
||||||
mpi_set( prime, q );
|
mpi_set( prime, q );
|
||||||
mpi_mul_ui( prime, prime, 2 );
|
mpi_mul_ui( prime, prime, 2 );
|
||||||
|
if( mode == 1 )
|
||||||
|
mpi_mul( prime, prime, q_factor );
|
||||||
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 );
|
||||||
@ -171,18 +185,30 @@ generate_elg_prime( unsigned pbits, unsigned qbits, MPI g, MPI **ret_factors )
|
|||||||
putc('\n', stderr);
|
putc('\n', stderr);
|
||||||
log_mpidump( "prime : ", prime );
|
log_mpidump( "prime : ", prime );
|
||||||
log_mpidump( "factor q: ", q );
|
log_mpidump( "factor q: ", q );
|
||||||
|
if( mode == 1 )
|
||||||
|
log_mpidump( "factor q0: ", q_factor );
|
||||||
for(i=0; i < n; i++ )
|
for(i=0; i < n; i++ )
|
||||||
log_mpidump( "factor pi: ", factors[i] );
|
log_mpidump( "factor pi: ", factors[i] );
|
||||||
log_debug("bit sizes: prime=%u, q=%u", mpi_get_nbits(prime), mpi_get_nbits(q) );
|
log_debug("bit sizes: prime=%u, q=%u", mpi_get_nbits(prime), mpi_get_nbits(q) );
|
||||||
|
if( mode == 1 )
|
||||||
|
fprintf(stderr, ", q0=%u", mpi_get_nbits(q_factor) );
|
||||||
for(i=0; i < n; i++ )
|
for(i=0; i < n; i++ )
|
||||||
fprintf(stderr, ", p%d=%u", i, mpi_get_nbits(factors[i]) );
|
fprintf(stderr, ", p%d=%u", i, mpi_get_nbits(factors[i]) );
|
||||||
putc('\n', stderr);
|
putc('\n', stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ret_factors ) { /* caller wants the factors */
|
if( ret_factors ) { /* caller wants the factors */
|
||||||
*ret_factors = m_alloc_clear( (n+1) * sizeof **ret_factors );
|
*ret_factors = m_alloc_clear( (n+2) * sizeof **ret_factors);
|
||||||
for(i=0; i < n; i++ )
|
if( mode == 1 ) {
|
||||||
(*ret_factors)[i] = mpi_copy( factors[i] );
|
i = 0;
|
||||||
|
(*ret_factors)[i++] = mpi_copy( q_factor );
|
||||||
|
for(; i <= n; i++ )
|
||||||
|
(*ret_factors)[i] = mpi_copy( factors[i] );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for(; i < n; i++ )
|
||||||
|
(*ret_factors)[i] = mpi_copy( factors[i] );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( g ) { /* create a generator (start with 3)*/
|
if( g ) { /* create a generator (start with 3)*/
|
||||||
@ -190,6 +216,8 @@ generate_elg_prime( unsigned pbits, unsigned qbits, MPI g, MPI **ret_factors )
|
|||||||
MPI b = mpi_alloc( mpi_get_nlimbs(prime) );
|
MPI b = mpi_alloc( mpi_get_nlimbs(prime) );
|
||||||
MPI pmin1 = mpi_alloc( mpi_get_nlimbs(prime) );
|
MPI pmin1 = mpi_alloc( mpi_get_nlimbs(prime) );
|
||||||
|
|
||||||
|
if( mode == 1 )
|
||||||
|
BUG(); /* not yet implemented */
|
||||||
factors[n] = q;
|
factors[n] = q;
|
||||||
factors[n+1] = mpi_alloc_set_ui(2);
|
factors[n+1] = mpi_alloc_set_ui(2);
|
||||||
mpi_sub_ui( pmin1, prime, 1 );
|
mpi_sub_ui( pmin1, prime, 1 );
|
||||||
@ -230,6 +258,7 @@ generate_elg_prime( unsigned pbits, unsigned qbits, MPI g, MPI **ret_factors )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static MPI
|
static MPI
|
||||||
gen_prime( unsigned nbits, int secret, int randomlevel )
|
gen_prime( unsigned nbits, int secret, int randomlevel )
|
||||||
{
|
{
|
||||||
|
@ -702,10 +702,11 @@ transform( TIGER_CONTEXT *hd, byte *data )
|
|||||||
u64 a,b,c,aa,bb,cc;
|
u64 a,b,c,aa,bb,cc;
|
||||||
u64 x[8];
|
u64 x[8];
|
||||||
#ifdef BIG_ENDIAN_HOST
|
#ifdef BIG_ENDIAN_HOST
|
||||||
#define MKWORD(d,n) ( (d)[8*(n)+0] << 56 | (d)[8*(n)+1] << 48 \
|
#define MKWORD(d,n) \
|
||||||
| (d)[8*(n)+2] << 40 | (d)[8*(n)+3] << 32 \
|
( ((u64)(d)[8*(n)+0]) << 56 | ((u64)(d)[8*(n)+1]) << 48 \
|
||||||
| (d)[8*(n)+4] << 24 | (d)[8*(n)+5] << 16 \
|
| ((u64)(d)[8*(n)+2]) << 40 | ((u64)(d)[8*(n)+3]) << 32 \
|
||||||
| (d)[8*(n)+6] << 8 | (d)[8*(n)+7] )
|
| ((u64)(d)[8*(n)+4]) << 24 | ((u64)(d)[8*(n)+5]) << 16 \
|
||||||
|
| ((u64)(d)[8*(n)+6]) << 8 | ((u64)(d)[8*(n)+7]) )
|
||||||
x[0] = MKWORD(data, 0);
|
x[0] = MKWORD(data, 0);
|
||||||
x[1] = MKWORD(data, 1);
|
x[1] = MKWORD(data, 1);
|
||||||
x[2] = MKWORD(data, 2);
|
x[2] = MKWORD(data, 2);
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
Tue May 5 22:11:59 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||||
|
|
||||||
|
* keygen.c (gen_dsa): New.
|
||||||
|
* build_packet.c (do_secret_cert): Support for DSA
|
||||||
|
|
||||||
Mon May 4 19:01:25 1998 Werner Koch (wk@isil.d.shuttle.de)
|
Mon May 4 19:01:25 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||||
|
|
||||||
* compress.c: doubled buffer sizes
|
* compress.c: doubled buffer sizes
|
||||||
|
@ -292,6 +292,29 @@ do_secret_cert( IOBUF out, int ctb, PKT_secret_cert *skc )
|
|||||||
mpi_write(a, skc->d.elg.x );
|
mpi_write(a, skc->d.elg.x );
|
||||||
write_16(a, skc->csum );
|
write_16(a, skc->csum );
|
||||||
}
|
}
|
||||||
|
else if( skc->pubkey_algo == PUBKEY_ALGO_DSA ) {
|
||||||
|
mpi_write(a, skc->d.dsa.p );
|
||||||
|
mpi_write(a, skc->d.dsa.q );
|
||||||
|
mpi_write(a, skc->d.dsa.g );
|
||||||
|
mpi_write(a, skc->d.dsa.y );
|
||||||
|
if( skc->is_protected ) {
|
||||||
|
iobuf_put(a, 0xff );
|
||||||
|
iobuf_put(a, skc->protect.algo );
|
||||||
|
iobuf_put(a, skc->protect.s2k.mode );
|
||||||
|
iobuf_put(a, skc->protect.s2k.hash_algo );
|
||||||
|
if( skc->protect.s2k.mode == 1
|
||||||
|
|| skc->protect.s2k.mode == 4 )
|
||||||
|
iobuf_write(a, skc->protect.s2k.salt, 8 );
|
||||||
|
if( skc->protect.s2k.mode == 4 )
|
||||||
|
write_32(a, skc->protect.s2k.count );
|
||||||
|
iobuf_write(a, skc->protect.iv, 8 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
iobuf_put(a, 0 );
|
||||||
|
|
||||||
|
mpi_write(a, skc->d.dsa.x );
|
||||||
|
write_16(a, skc->csum );
|
||||||
|
}
|
||||||
else if( is_RSA(skc->pubkey_algo) ) {
|
else if( is_RSA(skc->pubkey_algo) ) {
|
||||||
mpi_write(a, skc->d.rsa.n );
|
mpi_write(a, skc->d.rsa.n );
|
||||||
mpi_write(a, skc->d.rsa.e );
|
mpi_write(a, skc->d.rsa.e );
|
||||||
|
18
g10/g10.c
18
g10/g10.c
@ -72,6 +72,7 @@ static ARGPARSE_OPTS opts[] = {
|
|||||||
{ 515, "fingerprint", 0, N_("list keys and fingerprints")},
|
{ 515, "fingerprint", 0, N_("list keys and fingerprints")},
|
||||||
#ifdef IS_G10
|
#ifdef IS_G10
|
||||||
{ 503, "gen-key", 0, N_("generate a new key pair")},
|
{ 503, "gen-key", 0, N_("generate a new key pair")},
|
||||||
|
{ 554, "add-key", 0, N_("add a subkey to a key pair")},
|
||||||
{ 506, "sign-key" ,0, N_("make a signature on a key in the keyring")},
|
{ 506, "sign-key" ,0, N_("make a signature on a key in the keyring")},
|
||||||
{ 505, "delete-key",0, N_("remove key from the public keyring")},
|
{ 505, "delete-key",0, N_("remove key from the public keyring")},
|
||||||
{ 524, "edit-key" ,0, N_("edit a key signature")},
|
{ 524, "edit-key" ,0, N_("edit a key signature")},
|
||||||
@ -171,7 +172,7 @@ enum cmd_values { aNull = 0,
|
|||||||
aSym, aStore, aEncr, aKeygen, aSign, aSignEncr,
|
aSym, aStore, aEncr, aKeygen, aSign, aSignEncr,
|
||||||
aSignKey, aClearsign, aListPackets, aEditSig, aDeleteKey, aDeleteSecretKey,
|
aSignKey, aClearsign, aListPackets, aEditSig, aDeleteKey, aDeleteSecretKey,
|
||||||
aKMode, aKModeC, aChangePass, aImport, aVerify, aDecrypt, aListKeys,
|
aKMode, aKModeC, aChangePass, aImport, aVerify, aDecrypt, aListKeys,
|
||||||
aListSigs,
|
aListSigs, aKeyadd,
|
||||||
aExport, aCheckKeys, aGenRevoke, aPrimegen, aPrintMDs,
|
aExport, aCheckKeys, aGenRevoke, aPrimegen, aPrintMDs,
|
||||||
aListTrustDB, aListTrustPath, aDeArmor, aEnArmor, aGenRandom, aTest,
|
aListTrustDB, aListTrustPath, aDeArmor, aEnArmor, aGenRandom, aTest,
|
||||||
aNOP };
|
aNOP };
|
||||||
@ -574,6 +575,7 @@ main( int argc, char **argv )
|
|||||||
case 551: set_cmd( &cmd, aListKeys); break;
|
case 551: set_cmd( &cmd, aListKeys); break;
|
||||||
case 552: set_cmd( &cmd, aListSigs); break;
|
case 552: set_cmd( &cmd, aListSigs); break;
|
||||||
case 553: opt.skip_verify=1; break;
|
case 553: opt.skip_verify=1; break;
|
||||||
|
case 554: set_cmd( &cmd, aKeyadd); break;
|
||||||
default : errors++; pargs.err = configfp? 1:2; break;
|
default : errors++; pargs.err = configfp? 1:2; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -817,6 +819,11 @@ main( int argc, char **argv )
|
|||||||
wrong_args("--gen-key");
|
wrong_args("--gen-key");
|
||||||
generate_keypair();
|
generate_keypair();
|
||||||
break;
|
break;
|
||||||
|
case aKeyadd: /* add a subkey (interactive) */
|
||||||
|
if( argc != 1 )
|
||||||
|
wrong_args("--add-key userid");
|
||||||
|
generate_subkeypair(*argv);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case aImport:
|
case aImport:
|
||||||
@ -873,19 +880,24 @@ main( int argc, char **argv )
|
|||||||
putchar('\n');
|
putchar('\n');
|
||||||
}
|
}
|
||||||
else if( argc == 2 ) {
|
else if( argc == 2 ) {
|
||||||
mpi_print( stdout, generate_elg_prime( atoi(argv[0]),
|
mpi_print( stdout, generate_elg_prime( 0, atoi(argv[0]),
|
||||||
atoi(argv[1]), NULL,NULL ), 1);
|
atoi(argv[1]), NULL,NULL ), 1);
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
}
|
}
|
||||||
else if( argc == 3 ) {
|
else if( argc == 3 ) {
|
||||||
MPI g = mpi_alloc(1);
|
MPI g = mpi_alloc(1);
|
||||||
mpi_print( stdout, generate_elg_prime( atoi(argv[0]),
|
mpi_print( stdout, generate_elg_prime( 0, atoi(argv[0]),
|
||||||
atoi(argv[1]), g, NULL ), 1);
|
atoi(argv[1]), g, NULL ), 1);
|
||||||
printf("\nGenerator: ");
|
printf("\nGenerator: ");
|
||||||
mpi_print( stdout, g, 1 );
|
mpi_print( stdout, g, 1 );
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
mpi_free(g);
|
mpi_free(g);
|
||||||
}
|
}
|
||||||
|
else if( argc == 4 ) {
|
||||||
|
mpi_print( stdout, generate_elg_prime( 1, atoi(argv[0]),
|
||||||
|
atoi(argv[1]), NULL,NULL ), 1);
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
else
|
else
|
||||||
usage(1);
|
usage(1);
|
||||||
break;
|
break;
|
||||||
|
@ -621,6 +621,8 @@ change_passphrase( const char *username )
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* fixme: unprotect all subkeys */
|
||||||
|
|
||||||
if( rc )
|
if( rc )
|
||||||
tty_printf("Can't edit this key: %s\n", g10_errstr(rc));
|
tty_printf("Can't edit this key: %s\n", g10_errstr(rc));
|
||||||
else {
|
else {
|
||||||
@ -648,6 +650,7 @@ change_passphrase( const char *username )
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else { /* okay */
|
else { /* okay */
|
||||||
|
/* fixme: protect all subkeys too */
|
||||||
skc->protect.algo = dek->algo;
|
skc->protect.algo = dek->algo;
|
||||||
skc->protect.s2k = *s2k;
|
skc->protect.s2k = *s2k;
|
||||||
rc = protect_secret_key( skc, dek );
|
rc = protect_secret_key( skc, dek );
|
||||||
|
95
g10/keygen.c
95
g10/keygen.c
@ -224,11 +224,84 @@ gen_rsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
|
|||||||
#endif /*ENABLE_RSA_KEYGEN*/
|
#endif /*ENABLE_RSA_KEYGEN*/
|
||||||
|
|
||||||
|
|
||||||
|
/****************
|
||||||
|
* Generate a DSA key
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
|
gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
|
||||||
STRING2KEY *s2k, PKT_secret_cert **ret_skc, u16 valid_days )
|
STRING2KEY *s2k, PKT_secret_cert **ret_skc, u16 valid_days )
|
||||||
{
|
{
|
||||||
return G10ERR_GENERAL;
|
int rc;
|
||||||
|
int i;
|
||||||
|
PACKET *pkt;
|
||||||
|
PKT_secret_cert *skc;
|
||||||
|
PKT_public_cert *pkc;
|
||||||
|
DSA_public_key pk;
|
||||||
|
DSA_secret_key sk;
|
||||||
|
MPI *factors;
|
||||||
|
|
||||||
|
if( nbits > 1024 )
|
||||||
|
nbits = 1024;
|
||||||
|
|
||||||
|
dsa_generate( &pk, &sk, nbits, &factors );
|
||||||
|
|
||||||
|
skc = m_alloc_clear( sizeof *skc );
|
||||||
|
pkc = m_alloc_clear( sizeof *pkc );
|
||||||
|
skc->timestamp = pkc->timestamp = make_timestamp();
|
||||||
|
skc->version = pkc->version = 4;
|
||||||
|
/* valid days are not stored in the packet, but it is
|
||||||
|
* used here to put it into the signature.
|
||||||
|
*/
|
||||||
|
skc->valid_days = pkc->valid_days = valid_days;
|
||||||
|
skc->pubkey_algo = pkc->pubkey_algo = PUBKEY_ALGO_DSA;
|
||||||
|
pkc->d.dsa.p = pk.p;
|
||||||
|
pkc->d.dsa.q = pk.q;
|
||||||
|
pkc->d.dsa.g = pk.g;
|
||||||
|
pkc->d.dsa.y = pk.y;
|
||||||
|
skc->d.dsa.p = sk.p;
|
||||||
|
skc->d.dsa.q = sk.q;
|
||||||
|
skc->d.dsa.g = sk.g;
|
||||||
|
skc->d.dsa.y = sk.y;
|
||||||
|
skc->d.dsa.x = sk.x;
|
||||||
|
skc->is_protected = 0;
|
||||||
|
skc->protect.algo = 0;
|
||||||
|
|
||||||
|
skc->csum = checksum_mpi( skc->d.dsa.x );
|
||||||
|
/* return an unprotected version of the skc */
|
||||||
|
*ret_skc = copy_secret_cert( NULL, skc );
|
||||||
|
|
||||||
|
if( dek ) {
|
||||||
|
skc->protect.algo = dek->algo;
|
||||||
|
skc->protect.s2k = *s2k;
|
||||||
|
rc = protect_secret_key( skc, dek );
|
||||||
|
if( rc ) {
|
||||||
|
log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
|
||||||
|
free_public_cert(pkc);
|
||||||
|
free_secret_cert(skc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pkt = m_alloc_clear(sizeof *pkt);
|
||||||
|
pkt->pkttype = PKT_PUBLIC_CERT;
|
||||||
|
pkt->pkt.public_cert = pkc;
|
||||||
|
add_kbnode(pub_root, new_kbnode( pkt ));
|
||||||
|
|
||||||
|
/* don't know whether it makes sense to have the factors, so for now
|
||||||
|
* we store them in the secret keyring (but they are not secret)
|
||||||
|
* p = 2 * q * f1 * f2 * ... * fn
|
||||||
|
* We store only f1 to f_n-1 - fn can be calculated because p and q
|
||||||
|
* are known.
|
||||||
|
*/
|
||||||
|
pkt = m_alloc_clear(sizeof *pkt);
|
||||||
|
pkt->pkttype = PKT_SECRET_CERT;
|
||||||
|
pkt->pkt.secret_cert = skc;
|
||||||
|
add_kbnode(sec_root, new_kbnode( pkt ));
|
||||||
|
for(i=1; factors[i]; i++ ) /* the first one is q */
|
||||||
|
add_kbnode( sec_root,
|
||||||
|
make_mpi_comment_node("#:DSA_factor:", factors[i] ));
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -312,7 +385,7 @@ generate_keypair()
|
|||||||
else if( algo == 2 ) {
|
else if( algo == 2 ) {
|
||||||
algo = PUBKEY_ALGO_DSA;
|
algo = PUBKEY_ALGO_DSA;
|
||||||
algo_name = "DSA";
|
algo_name = "DSA";
|
||||||
tty_printf(_("Sorry; DSA key generation is not yet supported.\n"));
|
break;
|
||||||
}
|
}
|
||||||
#ifdef ENABLE_RSA_KEYGEN
|
#ifdef ENABLE_RSA_KEYGEN
|
||||||
else if( algo == 3 ) {
|
else if( algo == 3 ) {
|
||||||
@ -380,6 +453,10 @@ generate_keypair()
|
|||||||
" <n>w = key expires in n weeks\n"
|
" <n>w = key expires in n weeks\n"
|
||||||
" <n>m = key expires in n months\n"
|
" <n>m = key expires in n months\n"
|
||||||
" <n>y = key expires in n years\n"));
|
" <n>y = key expires in n years\n"));
|
||||||
|
/* Note: The elgamal subkey for DSA has no exiration date because
|
||||||
|
* is must be signed with the DSA key and this one has the expiration
|
||||||
|
* date */
|
||||||
|
|
||||||
answer = NULL;
|
answer = NULL;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
int mult;
|
int mult;
|
||||||
@ -578,7 +655,7 @@ generate_keypair()
|
|||||||
rc = gen_rsa(nbits, pub_root, sec_root, dek, s2k, &skc, valid_days );
|
rc = gen_rsa(nbits, pub_root, sec_root, dek, s2k, &skc, valid_days );
|
||||||
#endif
|
#endif
|
||||||
else if( algo == PUBKEY_ALGO_DSA )
|
else if( algo == PUBKEY_ALGO_DSA )
|
||||||
rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, &skc, valid_days );
|
rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, &skc, valid_days);
|
||||||
else
|
else
|
||||||
BUG();
|
BUG();
|
||||||
if( !rc ) {
|
if( !rc ) {
|
||||||
@ -663,3 +740,13 @@ generate_keypair()
|
|||||||
m_free(sec_fname);
|
m_free(sec_fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************
|
||||||
|
* add a new subkey to an existing key.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
generate_subkeypair( const char *userid )
|
||||||
|
{
|
||||||
|
log_fatal("To be implemented :-)\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -70,6 +70,7 @@ int change_passphrase( const char *username );
|
|||||||
|
|
||||||
/*-- keygen.c --*/
|
/*-- keygen.c --*/
|
||||||
void generate_keypair(void);
|
void generate_keypair(void);
|
||||||
|
void generate_subkeypair(const char *userid);
|
||||||
|
|
||||||
/*-- openfile.c --*/
|
/*-- openfile.c --*/
|
||||||
int overwrite_filep( const char *fname );
|
int overwrite_filep( const char *fname );
|
||||||
|
@ -114,7 +114,8 @@ extern ushort small_prime_numbers[];
|
|||||||
/*-- primegen.c --*/
|
/*-- primegen.c --*/
|
||||||
MPI generate_secret_prime( unsigned nbits );
|
MPI generate_secret_prime( unsigned nbits );
|
||||||
MPI generate_public_prime( unsigned nbits );
|
MPI generate_public_prime( unsigned nbits );
|
||||||
MPI generate_elg_prime( unsigned pbits, unsigned qbits, MPI g, MPI **factors );
|
MPI generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
|
||||||
|
MPI g, MPI **factors );
|
||||||
|
|
||||||
|
|
||||||
#endif /*G10_CIPHER_H*/
|
#endif /*G10_CIPHER_H*/
|
||||||
|
@ -93,7 +93,7 @@ POSUB = po
|
|||||||
RANLIB = ranlib
|
RANLIB = ranlib
|
||||||
USE_INCLUDED_LIBINTL = yes
|
USE_INCLUDED_LIBINTL = yes
|
||||||
USE_NLS = yes
|
USE_NLS = yes
|
||||||
VERSION = 0.2.17
|
VERSION = 0.2.17a
|
||||||
ZLIBS =
|
ZLIBS =
|
||||||
l =
|
l =
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user