mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-24 16:52:24 +00:00
Generate keys more carefully, so that when the user asks for an n-bit
key they always get an n-bit number instead of n-1. The latter was perfectly harmless but kept confusing users. [originally from svn r9421]
This commit is contained in:
parent
e59f1ac827
commit
9604c2b367
3
ssh.h
3
ssh.h
@ -550,7 +550,8 @@ int rsa_generate(struct RSAKey *key, int bits, progfn_t pfn,
|
|||||||
int dsa_generate(struct dss_key *key, int bits, progfn_t pfn,
|
int dsa_generate(struct dss_key *key, int bits, progfn_t pfn,
|
||||||
void *pfnparam);
|
void *pfnparam);
|
||||||
Bignum primegen(int bits, int modulus, int residue, Bignum factor,
|
Bignum primegen(int bits, int modulus, int residue, Bignum factor,
|
||||||
int phase, progfn_t pfn, void *pfnparam);
|
int phase, progfn_t pfn, void *pfnparam, unsigned firstbits);
|
||||||
|
void invent_firstbits(unsigned *one, unsigned *two);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -9,6 +9,7 @@ int dsa_generate(struct dss_key *key, int bits, progfn_t pfn,
|
|||||||
void *pfnparam)
|
void *pfnparam)
|
||||||
{
|
{
|
||||||
Bignum qm1, power, g, h, tmp;
|
Bignum qm1, power, g, h, tmp;
|
||||||
|
unsigned pfirst, qfirst;
|
||||||
int progress;
|
int progress;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -70,15 +71,16 @@ int dsa_generate(struct dss_key *key, int bits, progfn_t pfn,
|
|||||||
|
|
||||||
pfn(pfnparam, PROGFN_READY, 0, 0);
|
pfn(pfnparam, PROGFN_READY, 0, 0);
|
||||||
|
|
||||||
|
invent_firstbits(&pfirst, &qfirst);
|
||||||
/*
|
/*
|
||||||
* Generate q: a prime of length 160.
|
* Generate q: a prime of length 160.
|
||||||
*/
|
*/
|
||||||
key->q = primegen(160, 2, 2, NULL, 1, pfn, pfnparam);
|
key->q = primegen(160, 2, 2, NULL, 1, pfn, pfnparam, qfirst);
|
||||||
/*
|
/*
|
||||||
* Now generate p: a prime of length `bits', such that p-1 is
|
* Now generate p: a prime of length `bits', such that p-1 is
|
||||||
* divisible by q.
|
* divisible by q.
|
||||||
*/
|
*/
|
||||||
key->p = primegen(bits-160, 2, 2, key->q, 2, pfn, pfnparam);
|
key->p = primegen(bits-160, 2, 2, key->q, 2, pfn, pfnparam, pfirst);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Next we need g. Raise 2 to the power (p-1)/q modulo p, and
|
* Next we need g. Raise 2 to the power (p-1)/q modulo p, and
|
||||||
|
51
sshprime.c
51
sshprime.c
@ -838,11 +838,19 @@ static const unsigned short primes[] = {
|
|||||||
* more than a multiple of a dirty great bignum. In this case
|
* more than a multiple of a dirty great bignum. In this case
|
||||||
* `bits' gives the size of the factor by which we _multiply_
|
* `bits' gives the size of the factor by which we _multiply_
|
||||||
* that bignum, rather than the size of the whole number.
|
* that bignum, rather than the size of the whole number.
|
||||||
|
*
|
||||||
|
* - for the basically cosmetic purposes of generating keys of the
|
||||||
|
* length actually specified rather than off by one bit, we permit
|
||||||
|
* the caller to provide an unsigned integer 'firstbits' which will
|
||||||
|
* match the top few bits of the returned prime. (That is, there
|
||||||
|
* will exist some n such that (returnvalue >> n) == firstbits.) If
|
||||||
|
* 'firstbits' is not needed, specifying it to either 0 or 1 is
|
||||||
|
* an adequate no-op.
|
||||||
*/
|
*/
|
||||||
Bignum primegen(int bits, int modulus, int residue, Bignum factor,
|
Bignum primegen(int bits, int modulus, int residue, Bignum factor,
|
||||||
int phase, progfn_t pfn, void *pfnparam)
|
int phase, progfn_t pfn, void *pfnparam, unsigned firstbits)
|
||||||
{
|
{
|
||||||
int i, k, v, byte, bitsleft, check, checks;
|
int i, k, v, byte, bitsleft, check, checks, fbsize;
|
||||||
unsigned long delta;
|
unsigned long delta;
|
||||||
unsigned long moduli[NPRIMES + 1];
|
unsigned long moduli[NPRIMES + 1];
|
||||||
unsigned long residues[NPRIMES + 1];
|
unsigned long residues[NPRIMES + 1];
|
||||||
@ -853,6 +861,10 @@ Bignum primegen(int bits, int modulus, int residue, Bignum factor,
|
|||||||
byte = 0;
|
byte = 0;
|
||||||
bitsleft = 0;
|
bitsleft = 0;
|
||||||
|
|
||||||
|
fbsize = 0;
|
||||||
|
while (firstbits >> fbsize) /* work out how to align this */
|
||||||
|
fbsize++;
|
||||||
|
|
||||||
STARTOVER:
|
STARTOVER:
|
||||||
|
|
||||||
pfn(pfnparam, PROGFN_PROGRESS, phase, ++progress);
|
pfn(pfnparam, PROGFN_PROGRESS, phase, ++progress);
|
||||||
@ -865,9 +877,11 @@ Bignum primegen(int bits, int modulus, int residue, Bignum factor,
|
|||||||
*/
|
*/
|
||||||
p = bn_power_2(bits - 1);
|
p = bn_power_2(bits - 1);
|
||||||
for (i = 0; i < bits; i++) {
|
for (i = 0; i < bits; i++) {
|
||||||
if (i == 0 || i == bits - 1)
|
if (i == 0 || i == bits - 1) {
|
||||||
v = (i != 0 || !factor) ? 1 : 0;
|
v = (i != 0 || !factor) ? 1 : 0;
|
||||||
else {
|
} else if (i >= bits - fbsize) {
|
||||||
|
v = (firstbits >> (i - (bits - fbsize))) & 1;
|
||||||
|
} else {
|
||||||
if (bitsleft <= 0)
|
if (bitsleft <= 0)
|
||||||
bitsleft = 8, byte = random_byte();
|
bitsleft = 8, byte = random_byte();
|
||||||
v = byte & 1;
|
v = byte & 1;
|
||||||
@ -1041,3 +1055,32 @@ Bignum primegen(int bits, int modulus, int residue, Bignum factor,
|
|||||||
freebn(pm1);
|
freebn(pm1);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Invent a pair of values suitable for use as 'firstbits' in the
|
||||||
|
* above function, such that their product is at least 2.
|
||||||
|
*
|
||||||
|
* This is used for generating both RSA and DSA keys which have
|
||||||
|
* exactly the specified number of bits rather than one fewer - if you
|
||||||
|
* generate an a-bit and a b-bit number completely at random and
|
||||||
|
* multiply them together, you could end up with either an (ab-1)-bit
|
||||||
|
* number or an (ab)-bit number. The former happens log(2)*2-1 of the
|
||||||
|
* time (about 39%) and, though actually harmless, every time it
|
||||||
|
* occurs it has a non-zero probability of sparking a user email along
|
||||||
|
* the lines of 'Hey, I asked PuTTYgen for a 2048-bit key and I only
|
||||||
|
* got 2047 bits! Bug!'
|
||||||
|
*/
|
||||||
|
void invent_firstbits(unsigned *one, unsigned *two)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Our criterion is that any number in the range [one,one+1)
|
||||||
|
* multiplied by any number in the range [two,two+1) should have
|
||||||
|
* the highest bit set. It should be clear that we can trivially
|
||||||
|
* test this by multiplying the smallest values in each interval,
|
||||||
|
* i.e. the ones we actually invented.
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
*one = 0x100 | random_byte();
|
||||||
|
*two = 0x100 | random_byte();
|
||||||
|
} while (*one * *two < 0x20000);
|
||||||
|
}
|
||||||
|
@ -10,6 +10,7 @@ int rsa_generate(struct RSAKey *key, int bits, progfn_t pfn,
|
|||||||
void *pfnparam)
|
void *pfnparam)
|
||||||
{
|
{
|
||||||
Bignum pm1, qm1, phi_n;
|
Bignum pm1, qm1, phi_n;
|
||||||
|
unsigned pfirst, qfirst;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up the phase limits for the progress report. We do this
|
* Set up the phase limits for the progress report. We do this
|
||||||
@ -59,10 +60,11 @@ int rsa_generate(struct RSAKey *key, int bits, progfn_t pfn,
|
|||||||
* general that's slightly more fiddly to arrange. By choosing
|
* general that's slightly more fiddly to arrange. By choosing
|
||||||
* a prime e, we can simplify the criterion.)
|
* a prime e, we can simplify the criterion.)
|
||||||
*/
|
*/
|
||||||
|
invent_firstbits(&pfirst, &qfirst);
|
||||||
key->p = primegen(bits / 2, RSA_EXPONENT, 1, NULL,
|
key->p = primegen(bits / 2, RSA_EXPONENT, 1, NULL,
|
||||||
1, pfn, pfnparam);
|
1, pfn, pfnparam, pfirst);
|
||||||
key->q = primegen(bits - bits / 2, RSA_EXPONENT, 1, NULL,
|
key->q = primegen(bits - bits / 2, RSA_EXPONENT, 1, NULL,
|
||||||
2, pfn, pfnparam);
|
2, pfn, pfnparam, qfirst);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ensure p > q, by swapping them if not.
|
* Ensure p > q, by swapping them if not.
|
||||||
|
Loading…
Reference in New Issue
Block a user