@@ -33,6 +33,7 @@ import (
33
33
"crypto/rand"
34
34
"crypto/subtle"
35
35
"errors"
36
+ "fmt"
36
37
"hash"
37
38
"io"
38
39
"math"
@@ -272,7 +273,165 @@ func (priv *PrivateKey) Validate() error {
272
273
// returned key does not depend deterministically on the bytes read from rand,
273
274
// and may change between calls and/or between versions.
274
275
func GenerateKey (random io.Reader , bits int ) (* PrivateKey , error ) {
275
- return GenerateMultiPrimeKey (random , 2 , bits )
276
+ if bits < 2048 {
277
+ // Fall back to old implementation for smaller keys.
278
+ return GenerateMultiPrimeKey (random , 2 , bits )
279
+ }
280
+
281
+ priv := new (PrivateKey )
282
+ priv .E = 65537
283
+ // p and q
284
+ primes := make ([]* big.Int , 2 )
285
+ priv .Primes = primes
286
+
287
+ if priv .rsaFipsGeneratePrimeFactors (bits ) != nil {
288
+ return nil , errors .New ("crypto/rsa: could not generate prime factors p,q" )
289
+ }
290
+ n := new (big.Int ).Set (bigOne )
291
+ totient := new (big.Int ).Set (bigOne )
292
+ pminus1 := new (big.Int )
293
+ for _ , prime := range primes {
294
+ n .Mul (n , prime )
295
+ pminus1 .Sub (prime , bigOne )
296
+ totient .Mul (totient , pminus1 )
297
+ }
298
+ priv .D = new (big.Int )
299
+ e := big .NewInt (int64 (priv .E ))
300
+ ok := priv .D .ModInverse (e , totient )
301
+
302
+ if ok != nil {
303
+ priv .N = n
304
+ } else {
305
+ return nil , errors .New ("crypto/rsa: modulus error with public key exponent" )
306
+ }
307
+ priv .N = n
308
+ priv .Precomputed = PrecomputedValues {Dp : nil , Dq : nil , Qinv : nil , CRTValues : make ([]CRTValue , 0 ), n : nil , p : nil , q : nil }
309
+ priv .Precompute ()
310
+ return priv , nil
311
+ }
312
+
313
+ func diffCheck (p * big.Int , q * big.Int , bits int ) bool {
314
+ // 2^(nlen/2)-100
315
+ limit := new (big.Int ).Lsh (bigOne , (uint )(bits >> 1 )- 99 )
316
+ z := new (big.Int ).Sub (p , q )
317
+ z = z .Abs (z )
318
+ if z .Cmp (limit ) <= 0 {
319
+ return true
320
+ } else {
321
+ return false
322
+ }
323
+ }
324
+
325
+ func rsaFipsAuxPrimeMRRounds (bits int ) int {
326
+ if bits >= 4096 {
327
+ return 44
328
+ }
329
+ if bits >= 3072 {
330
+ return 41
331
+ }
332
+ if bits >= 2048 {
333
+ return 38
334
+ }
335
+ return 0
336
+ }
337
+
338
+ func (priv * PrivateKey ) rsaFipsGeneratePrimeFactors (bits int ) error {
339
+ rounds := rsaFipsAuxPrimeMRRounds (bits )
340
+ bytes := ((bits >> 1 ) + 7 ) >> 3
341
+
342
+ E := new (big.Int ).SetInt64 (int64 (priv .E ))
343
+
344
+ // 1/sqrt(2) * 2^256
345
+ base , ok := new (big.Int ).SetString ("0xB504F333F9DE6484597D89B3754ABE9F1D6F60BA893BA84CED17AC8583339916" , 0 )
346
+ if ! ok {
347
+ panic ("crypto/rsa: overflow of static constant sqrt2inv" )
348
+ }
349
+ if (bits >> 1 ) < 257 {
350
+ return errors .New ("crypto/rsa: Number of bits too small" )
351
+ }
352
+ sqrtinv := new (big.Int ).Lsh (base , (uint )((bits >> 1 )- 257 ))
353
+
354
+ i := 0
355
+ pbuf := make ([]byte , bytes )
356
+ var p , q * big.Int
357
+ for {
358
+ // Generate p
359
+ if _ , err := rand .Read (pbuf ); err != nil {
360
+ panic ("crypto/rsa: RNG failure" )
361
+ }
362
+ pbuf [bytes - 1 ] |= 1
363
+ pbuf [0 ] |= 0xe0
364
+ pbuf [1 ] |= 0xa0
365
+ p = new (big.Int ).SetBytes (pbuf )
366
+
367
+ // check if p < 1/sqrt(2)*(2^(bits/2)-1)
368
+ for p .Cmp (sqrtinv ) < 0 {
369
+ if _ , err := rand .Read (pbuf ); err != nil {
370
+ return fmt .Errorf ("crypto/rsa: error reading from random number generator: %s" , err )
371
+ }
372
+ pbuf [bytes - 1 ] |= 1
373
+ pbuf [0 ] |= 0xe0
374
+ pbuf [1 ] |= 0xa0
375
+
376
+ p = new (big.Int ).SetBytes (pbuf )
377
+ }
378
+ diff := new (big.Int ).Sub (p , bigOne )
379
+ ret := new (big.Int ).GCD (nil , nil , diff , E )
380
+ if ret .Cmp (bigOne ) == 0 {
381
+ isPrime := p .ProbablyPrime (rounds )
382
+ if isPrime {
383
+ goto genq
384
+ }
385
+ }
386
+ i ++
387
+ if i >= 5 * bits {
388
+ priv .Primes [0 ] = nil
389
+ priv .Primes [1 ] = nil
390
+ return errors .New ("crypto/rsa: number of tries to find prime factor exceeded limit" )
391
+ }
392
+ }
393
+ genq:
394
+ // Generate q
395
+ i = 0
396
+ for {
397
+ if _ , err := rand .Read (pbuf ); err != nil {
398
+ return fmt .Errorf ("crypto/rsa: error reading from random number generator: %s" , err )
399
+ }
400
+ pbuf [bytes - 1 ] |= 1
401
+ pbuf [0 ] |= 0xe0
402
+ pbuf [1 ] |= 0x80
403
+
404
+ q = new (big.Int ).SetBytes (pbuf )
405
+
406
+ // check if q < 1/sqrt(2)*(2^(bits/2)-1)
407
+ for q .Cmp (sqrtinv ) < 0 || diffCheck (p , q , bits ) {
408
+ if _ , err := rand .Read (pbuf ); err != nil {
409
+ return fmt .Errorf ("crypto/rsa: error reading from random number generator: %s" , err )
410
+ }
411
+ pbuf [bytes - 1 ] |= 1
412
+ pbuf [0 ] |= 0xe0
413
+ pbuf [1 ] |= 0x80
414
+
415
+ q = new (big.Int ).SetBytes (pbuf )
416
+ }
417
+ diff := new (big.Int ).Sub (q , bigOne )
418
+ ret := new (big.Int ).GCD (nil , nil , diff , E )
419
+ if ret .Cmp (bigOne ) == 0 {
420
+ isPrime := q .ProbablyPrime (rounds )
421
+ if isPrime {
422
+ break
423
+ }
424
+ }
425
+ i ++
426
+ if i >= 10 * bits {
427
+ priv .Primes [0 ] = nil
428
+ priv .Primes [1 ] = nil
429
+ return errors .New ("crypto/rsa: number of tries to find prime factor exceeded limit" )
430
+ }
431
+ }
432
+ priv .Primes [0 ] = p
433
+ priv .Primes [1 ] = q
434
+ return nil
276
435
}
277
436
278
437
// GenerateMultiPrimeKey generates a multi-prime RSA keypair of the given bit
0 commit comments