From 50716874fdcbee62ba248f01b827226ee9591a14 Mon Sep 17 00:00:00 2001 From: Eduardo Date: Fri, 23 Aug 2019 20:59:16 -0400 Subject: [PATCH] fixing length of random numbers generated --- key_test.go | 4 +-- utils.go | 91 ++++++++++++++++++++++++++++++++++++--------------- utils_test.go | 29 +++++++++------- 3 files changed, 84 insertions(+), 40 deletions(-) diff --git a/key_test.go b/key_test.go index b4bfc5b..a7b9ce0 100644 --- a/key_test.go +++ b/key_test.go @@ -47,7 +47,7 @@ func TestGenerateKeys_validRandom(t *testing.T) { keyMetaArgs := &tcrsa.KeyMetaArgs{} - keyShares, keyMeta, err := tcrsa.NewKey(keyTestFixedSize, uint16(k), uint16(l), keyMetaArgs) + keyShares, keyMeta, err := tcrsa.NewKey(keyTestSize, uint16(k), uint16(l), keyMetaArgs) if err != nil { t.Errorf(fmt.Sprintf("%v", err)) } @@ -108,7 +108,7 @@ func TestGenerateKeys_validFixed(t *testing.T) { keyMetaArgs.R = new(big.Int).SetBytes(rBig) keyMetaArgs.U = new(big.Int).SetBytes(vkuBig) - keyShares, keyMeta, err := tcrsa.NewKey(keyTestSize, uint16(k), uint16(l), keyMetaArgs) + keyShares, keyMeta, err := tcrsa.NewKey(keyTestFixedSize, uint16(k), uint16(l), keyMetaArgs) if err != nil { t.Errorf(fmt.Sprintf("%v", err)) } diff --git a/utils.go b/utils.go index 2ab58eb..5b9e8c5 100644 --- a/utils.go +++ b/utils.go @@ -2,6 +2,7 @@ package tcrsa import ( "crypto/rand" + mathRand "math/rand" "fmt" "math/big" ) @@ -18,35 +19,65 @@ func randomDev(bitLen int) (randNum *big.Int, err error) { return } byteLen := bitLen / 8 - byteRem := bitLen % 8 - if byteRem != 0 { + if bitLen % 8 != 0 { byteLen++ } rawRand := make([]byte, byteLen) - for randNum.BitLen() != bitLen { + for randNum.BitLen() == 0 || randNum.BitLen() > bitLen { _, err = rand.Read(rawRand) if err != nil { return } randNum.SetBytes(rawRand) // set MSBs to 0 to get a bitLen equal to bitLen param. - var bit int - for bit = randNum.BitLen() - 1; bit >= bitLen; bit-- { + for bit := bitLen; bit < randNum.BitLen(); bit++ { randNum.SetBit(randNum, bit, 0) } - // Set bit number (bitLen-1) to 1 - randNum.SetBit(randNum, bit, 1) } - if randNum.BitLen() != bitLen { - err = fmt.Errorf("random number returned should have length %d, but its length is %d", bitLen, randNum.BitLen()) + if randNum.BitLen() == 0 || randNum.BitLen() > bitLen { + err = fmt.Errorf("random number returned should have length at most %d, but its length is %d", bitLen, randNum.BitLen()) return } return } -// randomPrime a random prime of length bitLen, using a given random function randFn. +// randomFixed returns a seeded pseudorandom function that returns a random number of bitLen bits. +func randomFixed(seed int64) func(int) (*big.Int, error) { + seededRand := mathRand.New(mathRand.NewSource(seed)) + return func(bitLen int) (randNum *big.Int, err error) { + randNum = big.NewInt(0) + if bitLen <= 0 { + err = fmt.Errorf("bitlen should be greater than 0, but it is %d", bitLen) + return + } + byteLen := bitLen / 8 + if bitLen % 8 != 0 { + byteLen++ + } + rawRand := make([]byte, byteLen) + for randNum.BitLen() == 0 || randNum.BitLen() > bitLen { + _, err = seededRand.Read(rawRand) + if err != nil { + return + } + randNum.SetBytes(rawRand) + // set MSBs to 0 to get a bitLen equal to bitLen param. + for bit := bitLen; bit < randNum.BitLen(); bit++ { + randNum.SetBit(randNum, bit, 0) + } + } + + if randNum.BitLen() == 0 || randNum.BitLen() > bitLen { + err = fmt.Errorf("random number returned should have length at most %d, but its length is %d", bitLen, randNum.BitLen()) + return + } + return + } +} + +// randomPrime returns a random prime of length bitLen, using a given random function randFn. func randomPrime(bitLen int, randFn func(int) (*big.Int, error)) (randPrime *big.Int, err error) { randPrime = new(big.Int) @@ -59,16 +90,16 @@ func randomPrime(bitLen int, randFn func(int) (*big.Int, error)) (randPrime *big return } - for randPrime.BitLen() != bitLen { + for randPrime.BitLen() == 0 || randPrime.BitLen() > bitLen { randPrime, err = randFn(bitLen) if err != nil { return } - randPrime = nextPrime(randPrime, c) + setAsNextPrime(randPrime, c) } - if randPrime.BitLen() != bitLen { - err = fmt.Errorf("random number returned should have length %d, but its length is %d", bitLen, randPrime.BitLen()) + if randPrime.BitLen() == 0 || randPrime.BitLen() > bitLen { + err = fmt.Errorf("random number returned should have length at most %d, but its length is %d", bitLen, randPrime.BitLen()) return } @@ -79,16 +110,16 @@ func randomPrime(bitLen int, randFn func(int) (*big.Int, error)) (randPrime *big return } -// nextPrime returns the next prime number based on a specific number, checking for its prime condition +// setAsNextPrime edits the number as the next prime number from it, checking for its prime condition // using ProbablyPrime function. -func nextPrime(num *big.Int, n int) *big.Int { +func setAsNextPrime(num *big.Int, n int) { // Possible prime should be odd num.SetBit(num, 0, 1) + two := big.NewInt(2) for !num.ProbablyPrime(n) { // I add two to the number to obtain another odd number - num.Add(num, big.NewInt(2)) + num.Add(num, two) } - return num } // generateSafePrimes generates two primes p and q, in a way that q @@ -101,20 +132,28 @@ func generateSafePrimes(bitLen int, randFn func(int) (*big.Int, error)) (*big.In q := new(big.Int) r := new(big.Int) - for true { + for { p, err := randomPrime(bitLen, randFn) if err != nil { return big.NewInt(0), big.NewInt(0), err } - q.Sub(p, big.NewInt(1)).Div(q, big.NewInt(2)) - r.Mul(p, big.NewInt(2)).Add(r, big.NewInt(1)) - if q.ProbablyPrime(c) { - return p, q, nil + // If the number will be odd after right shift + if p.Bit(1) == 1 { + // q = (p - 1) / 2 + q.Rsh(p, 1) + if q.ProbablyPrime(c) { + return p, q, nil + } } - if r.ProbablyPrime(c) { - return r, p, nil + + if p.BitLen() < bitLen { + // r = 2p + 1 + r.Lsh(p, 1) + r.SetBit(r,0,1) + if r.ProbablyPrime(c) { + return r, p, nil + } } } - return big.NewInt(0), big.NewInt(0), fmt.Errorf("should never be here") } diff --git a/utils_test.go b/utils_test.go index d701042..23b424b 100644 --- a/utils_test.go +++ b/utils_test.go @@ -5,7 +5,7 @@ import ( "testing" ) -const utilsTestBitlen = 128 +const utilsTestBitlen = 256 // Miller-Rabin primality test rounds const utilsTestC = 25 @@ -32,8 +32,8 @@ func TestRandomDev_bitSize(t *testing.T) { if err != nil { t.Errorf("first random number generation failed: %v", err) } - if rand1.BitLen() != utilsTestBitlen { - t.Errorf("random number bit length should have been %d, but it was %d", rand1.BitLen(), utilsTestBitlen) + if rand1.BitLen() > utilsTestBitlen { + t.Errorf("random number bit length should have been at most %d, but it was %d", rand1.BitLen(), utilsTestBitlen) } } @@ -59,8 +59,8 @@ func TestRandomPrimes_bitSize(t *testing.T) { if err != nil { t.Errorf("first random prime number generation failed: %v", err) } - if rand1.BitLen() != utilsTestBitlen { - t.Errorf("random number bit length should have been %d, but it was %d", rand1.BitLen(), utilsTestBitlen) + if rand1.BitLen() > utilsTestBitlen { + t.Errorf("random number bit length should have been at most %d, but it was %d", rand1.BitLen(), utilsTestBitlen) } } @@ -78,10 +78,12 @@ func TestRandomPrimes_isPrime(t *testing.T) { // Tests that NextPrime returns the next prime of a number greater than 2. func TestNextPrime(t *testing.T) { number := big.NewInt(4) + firstNumber := big.NewInt(0) + firstNumber.Set(number) expected := big.NewInt(5) - output := nextPrime(number, utilsTestC) - if output.Cmp(expected) != 0 { - t.Errorf("expecting %s as next prime of %s, but obtained %s", expected, number, output) + setAsNextPrime(number, utilsTestC) + if number.Cmp(expected) != 0 { + t.Errorf("expecting %s as next prime of %s, but obtained %s", expected, firstNumber, number) } } @@ -133,11 +135,14 @@ func TestGenerateSafePrimes_keyGeneration(t *testing.T) { } -func BenchmarkSafePrimes(b *testing.B) { + +func BenchmarkSetAsPrime(b *testing.B) { + randFn := randomFixed(12345) for i := 0; i < b.N; i++ { - _, _, err := generateSafePrimes(utilsTestBitlen, randomDev) - if err != nil { - b.Errorf("safe prime generation failed: %v", err) + randPrime := big.NewInt(0) + for randPrime.BitLen() == 0 || randPrime.BitLen() > utilsTestBitlen { + randPrime, _ = randFn(utilsTestBitlen) + setAsNextPrime(randPrime, c) } } }