Commit b9caa4ac authored by Robert Griesemer's avatar Robert Griesemer

big: completed set of Int division routines & cleanups

- renamed Len -> BitLen, simplified implementation
- renamed old Div, Mod, DivMod -> Que, Rem, QuoRem
- implemented Div, Mod, DivMod (Euclidian definition, more
  useful in a mathematical context)
- fixed a bug in Exp (-0 was possible)
- added extra tests to check normalized results everywhere
- uniformly set Int.neg flag at the end of computations
- minor cosmetic cleanups
- ran all tests

R=rsc
CC=golang-dev
https://golang.org/cl/1091041
parent 32df6788
This diff is collapsed.
This diff is collapsed.
...@@ -356,7 +356,7 @@ func karatsuba(z, x, y nat) { ...@@ -356,7 +356,7 @@ func karatsuba(z, x, y nat) {
// alias returns true if x and y share the same base array. // alias returns true if x and y share the same base array.
func alias(x, y nat) bool { func alias(x, y nat) bool {
return &x[0:cap(x)][cap(x)-1] == &y[0:cap(y)][cap(y)-1] return cap(x) > 0 && cap(y) > 0 && &x[0:cap(x)][cap(x)-1] == &y[0:cap(y)][cap(y)-1]
} }
...@@ -412,7 +412,7 @@ func (z nat) mul(x, y nat) nat { ...@@ -412,7 +412,7 @@ func (z nat) mul(x, y nat) nat {
// m >= n > 1 // m >= n > 1
// determine if z can be reused // determine if z can be reused
if len(z) > 0 && (alias(z, x) || alias(z, y)) { if alias(z, x) || alias(z, y) {
z = nil // z is an alias for x or y - cannot reuse z = nil // z is an alias for x or y - cannot reuse
} }
...@@ -757,7 +757,7 @@ func (z nat) shl(x nat, s uint) nat { ...@@ -757,7 +757,7 @@ func (z nat) shl(x nat, s uint) nat {
// determine if z can be reused // determine if z can be reused
// TODO(gri) change shlVW so we don't need this // TODO(gri) change shlVW so we don't need this
if len(z) > 0 && alias(z, x) { if alias(z, x) {
z = nil // z is an alias for x - cannot reuse z = nil // z is an alias for x - cannot reuse
} }
...@@ -780,7 +780,7 @@ func (z nat) shr(x nat, s uint) nat { ...@@ -780,7 +780,7 @@ func (z nat) shr(x nat, s uint) nat {
// determine if z can be reused // determine if z can be reused
// TODO(gri) change shrVW so we don't need this // TODO(gri) change shrVW so we don't need this
if len(z) > 0 && alias(z, x) { if alias(z, x) {
z = nil // z is an alias for x - cannot reuse z = nil // z is an alias for x - cannot reuse
} }
......
...@@ -253,7 +253,7 @@ func (x *Integer) QuoRem(y *Integer) (*Integer, *Integer) { ...@@ -253,7 +253,7 @@ func (x *Integer) QuoRem(y *Integer) (*Integer, *Integer) {
// Div and Mod implement Euclidian division and modulus: // Div and Mod implement Euclidian division and modulus:
// //
// q = x.Div(y) // q = x.Div(y)
// r = x.Mod(y) with: 0 <= r < |q| and: y = x*q + r // r = x.Mod(y) with: 0 <= r < |q| and: x = y*q + r
// //
// (Raymond T. Boute, ``The Euclidian definition of the functions // (Raymond T. Boute, ``The Euclidian definition of the functions
// div and mod''. ACM Transactions on Programming Languages and // div and mod''. ACM Transactions on Programming Languages and
......
...@@ -18,7 +18,7 @@ import ( ...@@ -18,7 +18,7 @@ import (
// WARNING: use of this function to encrypt plaintexts other than session keys // WARNING: use of this function to encrypt plaintexts other than session keys
// is dangerous. Use RSA OAEP in new protocols. // is dangerous. Use RSA OAEP in new protocols.
func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, err os.Error) { func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, err os.Error) {
k := (pub.N.Len() + 7) / 8 k := (pub.N.BitLen() + 7) / 8
if len(msg) > k-11 { if len(msg) > k-11 {
err = MessageTooLongError{} err = MessageTooLongError{}
return return
...@@ -66,7 +66,7 @@ func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out [ ...@@ -66,7 +66,7 @@ func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out [
// Encryption Standard PKCS #1'', Daniel Bleichenbacher, Advances in Cryptology // Encryption Standard PKCS #1'', Daniel Bleichenbacher, Advances in Cryptology
// (Crypto '98), // (Crypto '98),
func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) (err os.Error) { func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) (err os.Error) {
k := (priv.N.Len() + 7) / 8 k := (priv.N.BitLen() + 7) / 8
if k-(len(key)+3+8) < 0 { if k-(len(key)+3+8) < 0 {
err = DecryptionError{} err = DecryptionError{}
return return
...@@ -83,7 +83,7 @@ func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []by ...@@ -83,7 +83,7 @@ func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []by
} }
func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid int, msg []byte, err os.Error) { func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid int, msg []byte, err os.Error) {
k := (priv.N.Len() + 7) / 8 k := (priv.N.BitLen() + 7) / 8
if k < 11 { if k < 11 {
err = DecryptionError{} err = DecryptionError{}
return return
...@@ -179,7 +179,7 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash PKCS1v15Hash, hashed [] ...@@ -179,7 +179,7 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash PKCS1v15Hash, hashed []
} }
tLen := len(prefix) + hashLen tLen := len(prefix) + hashLen
k := (priv.N.Len() + 7) / 8 k := (priv.N.BitLen() + 7) / 8
if k < tLen+11 { if k < tLen+11 {
return nil, MessageTooLongError{} return nil, MessageTooLongError{}
} }
...@@ -212,7 +212,7 @@ func VerifyPKCS1v15(pub *PublicKey, hash PKCS1v15Hash, hashed []byte, sig []byte ...@@ -212,7 +212,7 @@ func VerifyPKCS1v15(pub *PublicKey, hash PKCS1v15Hash, hashed []byte, sig []byte
} }
tLen := len(prefix) + hashLen tLen := len(prefix) + hashLen
k := (pub.N.Len() + 7) / 8 k := (pub.N.BitLen() + 7) / 8
if k < tLen+11 { if k < tLen+11 {
err = VerificationError{} err = VerificationError{}
return return
......
...@@ -67,7 +67,7 @@ func TestEncryptPKCS1v15(t *testing.T) { ...@@ -67,7 +67,7 @@ func TestEncryptPKCS1v15(t *testing.T) {
if err != nil { if err != nil {
t.Errorf("Failed to open /dev/urandom") t.Errorf("Failed to open /dev/urandom")
} }
k := (rsaPrivateKey.N.Len() + 7) / 8 k := (rsaPrivateKey.N.BitLen() + 7) / 8
tryEncryptDecrypt := func(in []byte, blind bool) bool { tryEncryptDecrypt := func(in []byte, blind bool) bool {
if len(in) > k-11 { if len(in) > k-11 {
......
...@@ -50,11 +50,11 @@ func randomPrime(rand io.Reader, bits int) (p *big.Int, err os.Error) { ...@@ -50,11 +50,11 @@ func randomPrime(rand io.Reader, bits int) (p *big.Int, err os.Error) {
// randomNumber returns a uniform random value in [0, max). // randomNumber returns a uniform random value in [0, max).
func randomNumber(rand io.Reader, max *big.Int) (n *big.Int, err os.Error) { func randomNumber(rand io.Reader, max *big.Int) (n *big.Int, err os.Error) {
k := (max.Len() + 7) / 8 k := (max.BitLen() + 7) / 8
// r is the number of bits in the used in the most significant byte of // r is the number of bits in the used in the most significant byte of
// max. // max.
r := uint(max.Len() % 8) r := uint(max.BitLen() % 8)
if r == 0 { if r == 0 {
r = 8 r = 8
} }
...@@ -244,7 +244,7 @@ func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int { ...@@ -244,7 +244,7 @@ func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int {
// twice the hash length plus 2. // twice the hash length plus 2.
func EncryptOAEP(hash hash.Hash, rand io.Reader, pub *PublicKey, msg []byte, label []byte) (out []byte, err os.Error) { func EncryptOAEP(hash hash.Hash, rand io.Reader, pub *PublicKey, msg []byte, label []byte) (out []byte, err os.Error) {
hash.Reset() hash.Reset()
k := (pub.N.Len() + 7) / 8 k := (pub.N.BitLen() + 7) / 8
if len(msg) > k-2*hash.Size()-2 { if len(msg) > k-2*hash.Size()-2 {
err = MessageTooLongError{} err = MessageTooLongError{}
return return
...@@ -365,7 +365,7 @@ func decrypt(rand io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err os.E ...@@ -365,7 +365,7 @@ func decrypt(rand io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err os.E
// DecryptOAEP decrypts ciphertext using RSA-OAEP. // DecryptOAEP decrypts ciphertext using RSA-OAEP.
// If rand != nil, DecryptOAEP uses RSA blinding to avoid timing side-channel attacks. // If rand != nil, DecryptOAEP uses RSA blinding to avoid timing side-channel attacks.
func DecryptOAEP(hash hash.Hash, rand io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) (msg []byte, err os.Error) { func DecryptOAEP(hash hash.Hash, rand io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) (msg []byte, err os.Error) {
k := (priv.N.Len() + 7) / 8 k := (priv.N.BitLen() + 7) / 8
if len(ciphertext) > k || if len(ciphertext) > k ||
k < hash.Size()*2+2 { k < hash.Size()*2+2 {
err = DecryptionError{} err = DecryptionError{}
......
...@@ -81,8 +81,8 @@ func extract_digit() int64 { ...@@ -81,8 +81,8 @@ func extract_digit() int64 {
func next_term(k int64) { func next_term(k int64) {
// TODO(eds) If big.Int ever gets a Scale method, y2 and bigk could be int64 // TODO(eds) If big.Int ever gets a Scale method, y2 and bigk could be int64
y2.New(k*2 + 1) y2.SetInt64(k*2 + 1)
bigk.New(k) bigk.SetInt64(k)
tmp1.Lsh(numer, 1) tmp1.Lsh(numer, 1)
accum.Add(accum, tmp1) accum.Add(accum, tmp1)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment