Home | History | Annotate | Download | only in rand
      1 // Copyright 2011 The Go Authors.  All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package rand
      6 
      7 import (
      8 	"errors"
      9 	"io"
     10 	"math/big"
     11 )
     12 
     13 // smallPrimes is a list of small, prime numbers that allows us to rapidly
     14 // exclude some fraction of composite candidates when searching for a random
     15 // prime. This list is truncated at the point where smallPrimesProduct exceeds
     16 // a uint64. It does not include two because we ensure that the candidates are
     17 // odd by construction.
     18 var smallPrimes = []uint8{
     19 	3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53,
     20 }
     21 
     22 // smallPrimesProduct is the product of the values in smallPrimes and allows us
     23 // to reduce a candidate prime by this number and then determine whether it's
     24 // coprime to all the elements of smallPrimes without further big.Int
     25 // operations.
     26 var smallPrimesProduct = new(big.Int).SetUint64(16294579238595022365)
     27 
     28 // Prime returns a number, p, of the given size, such that p is prime
     29 // with high probability.
     30 // Prime will return error for any error returned by rand.Read or if bits < 2.
     31 func Prime(rand io.Reader, bits int) (p *big.Int, err error) {
     32 	if bits < 2 {
     33 		err = errors.New("crypto/rand: prime size must be at least 2-bit")
     34 		return
     35 	}
     36 
     37 	b := uint(bits % 8)
     38 	if b == 0 {
     39 		b = 8
     40 	}
     41 
     42 	bytes := make([]byte, (bits+7)/8)
     43 	p = new(big.Int)
     44 
     45 	bigMod := new(big.Int)
     46 
     47 	for {
     48 		_, err = io.ReadFull(rand, bytes)
     49 		if err != nil {
     50 			return nil, err
     51 		}
     52 
     53 		// Clear bits in the first byte to make sure the candidate has a size <= bits.
     54 		bytes[0] &= uint8(int(1<<b) - 1)
     55 		// Don't let the value be too small, i.e, set the most significant two bits.
     56 		// Setting the top two bits, rather than just the top bit,
     57 		// means that when two of these values are multiplied together,
     58 		// the result isn't ever one bit short.
     59 		if b >= 2 {
     60 			bytes[0] |= 3 << (b - 2)
     61 		} else {
     62 			// Here b==1, because b cannot be zero.
     63 			bytes[0] |= 1
     64 			if len(bytes) > 1 {
     65 				bytes[1] |= 0x80
     66 			}
     67 		}
     68 		// Make the value odd since an even number this large certainly isn't prime.
     69 		bytes[len(bytes)-1] |= 1
     70 
     71 		p.SetBytes(bytes)
     72 
     73 		// Calculate the value mod the product of smallPrimes.  If it's
     74 		// a multiple of any of these primes we add two until it isn't.
     75 		// The probability of overflowing is minimal and can be ignored
     76 		// because we still perform Miller-Rabin tests on the result.
     77 		bigMod.Mod(p, smallPrimesProduct)
     78 		mod := bigMod.Uint64()
     79 
     80 	NextDelta:
     81 		for delta := uint64(0); delta < 1<<20; delta += 2 {
     82 			m := mod + delta
     83 			for _, prime := range smallPrimes {
     84 				if m%uint64(prime) == 0 && (bits > 6 || m != uint64(prime)) {
     85 					continue NextDelta
     86 				}
     87 			}
     88 
     89 			if delta > 0 {
     90 				bigMod.SetUint64(delta)
     91 				p.Add(p, bigMod)
     92 			}
     93 			break
     94 		}
     95 
     96 		// There is a tiny possibility that, by adding delta, we caused
     97 		// the number to be one bit too long. Thus we check BitLen
     98 		// here.
     99 		if p.ProbablyPrime(20) && p.BitLen() == bits {
    100 			return
    101 		}
    102 	}
    103 }
    104 
    105 // Int returns a uniform random value in [0, max). It panics if max <= 0.
    106 func Int(rand io.Reader, max *big.Int) (n *big.Int, err error) {
    107 	if max.Sign() <= 0 {
    108 		panic("crypto/rand: argument to Int is <= 0")
    109 	}
    110 	k := (max.BitLen() + 7) / 8
    111 
    112 	// b is the number of bits in the most significant byte of max.
    113 	b := uint(max.BitLen() % 8)
    114 	if b == 0 {
    115 		b = 8
    116 	}
    117 
    118 	bytes := make([]byte, k)
    119 	n = new(big.Int)
    120 
    121 	for {
    122 		_, err = io.ReadFull(rand, bytes)
    123 		if err != nil {
    124 			return nil, err
    125 		}
    126 
    127 		// Clear bits in the first byte to increase the probability
    128 		// that the candidate is < max.
    129 		bytes[0] &= uint8(int(1<<b) - 1)
    130 
    131 		n.SetBytes(bytes)
    132 		if n.Cmp(max) < 0 {
    133 			return
    134 		}
    135 	}
    136 }
    137