mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			301 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			301 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Go
		
	
	
	
| // Copyright 2011 The Go Authors. All rights reserved.
 | |
| // Use of this source code is governed by a BSD-style
 | |
| // license that can be found in the LICENSE file.
 | |
| 
 | |
| // Package dsa implements the Digital Signature Algorithm, as defined in FIPS 186-3.
 | |
| //
 | |
| // The DSA operations in this package are not implemented using constant-time algorithms.
 | |
| package dsa
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"io"
 | |
| 	"math/big"
 | |
| 
 | |
| 	"crypto/internal/randutil"
 | |
| )
 | |
| 
 | |
| // Parameters represents the domain parameters for a key. These parameters can
 | |
| // be shared across many keys. The bit length of Q must be a multiple of 8.
 | |
| type Parameters struct {
 | |
| 	P, Q, G *big.Int
 | |
| }
 | |
| 
 | |
| // PublicKey represents a DSA public key.
 | |
| type PublicKey struct {
 | |
| 	Parameters
 | |
| 	Y *big.Int
 | |
| }
 | |
| 
 | |
| // PrivateKey represents a DSA private key.
 | |
| type PrivateKey struct {
 | |
| 	PublicKey
 | |
| 	X *big.Int
 | |
| }
 | |
| 
 | |
| // ErrInvalidPublicKey results when a public key is not usable by this code.
 | |
| // FIPS is quite strict about the format of DSA keys, but other code may be
 | |
| // less so. Thus, when using keys which may have been generated by other code,
 | |
| // this error must be handled.
 | |
| var ErrInvalidPublicKey = errors.New("crypto/dsa: invalid public key")
 | |
| 
 | |
| // ParameterSizes is an enumeration of the acceptable bit lengths of the primes
 | |
| // in a set of DSA parameters. See FIPS 186-3, section 4.2.
 | |
| type ParameterSizes int
 | |
| 
 | |
| const (
 | |
| 	L1024N160 ParameterSizes = iota
 | |
| 	L2048N224
 | |
| 	L2048N256
 | |
| 	L3072N256
 | |
| )
 | |
| 
 | |
| // numMRTests is the number of Miller-Rabin primality tests that we perform. We
 | |
| // pick the largest recommended number from table C.1 of FIPS 186-3.
 | |
| const numMRTests = 64
 | |
| 
 | |
| // GenerateParameters puts a random, valid set of DSA parameters into params.
 | |
| // This function can take many seconds, even on fast machines.
 | |
| func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes) error {
 | |
| 	// This function doesn't follow FIPS 186-3 exactly in that it doesn't
 | |
| 	// use a verification seed to generate the primes. The verification
 | |
| 	// seed doesn't appear to be exported or used by other code and
 | |
| 	// omitting it makes the code cleaner.
 | |
| 
 | |
| 	var L, N int
 | |
| 	switch sizes {
 | |
| 	case L1024N160:
 | |
| 		L = 1024
 | |
| 		N = 160
 | |
| 	case L2048N224:
 | |
| 		L = 2048
 | |
| 		N = 224
 | |
| 	case L2048N256:
 | |
| 		L = 2048
 | |
| 		N = 256
 | |
| 	case L3072N256:
 | |
| 		L = 3072
 | |
| 		N = 256
 | |
| 	default:
 | |
| 		return errors.New("crypto/dsa: invalid ParameterSizes")
 | |
| 	}
 | |
| 
 | |
| 	qBytes := make([]byte, N/8)
 | |
| 	pBytes := make([]byte, L/8)
 | |
| 
 | |
| 	q := new(big.Int)
 | |
| 	p := new(big.Int)
 | |
| 	rem := new(big.Int)
 | |
| 	one := new(big.Int)
 | |
| 	one.SetInt64(1)
 | |
| 
 | |
| GeneratePrimes:
 | |
| 	for {
 | |
| 		if _, err := io.ReadFull(rand, qBytes); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 
 | |
| 		qBytes[len(qBytes)-1] |= 1
 | |
| 		qBytes[0] |= 0x80
 | |
| 		q.SetBytes(qBytes)
 | |
| 
 | |
| 		if !q.ProbablyPrime(numMRTests) {
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		for i := 0; i < 4*L; i++ {
 | |
| 			if _, err := io.ReadFull(rand, pBytes); err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 
 | |
| 			pBytes[len(pBytes)-1] |= 1
 | |
| 			pBytes[0] |= 0x80
 | |
| 
 | |
| 			p.SetBytes(pBytes)
 | |
| 			rem.Mod(p, q)
 | |
| 			rem.Sub(rem, one)
 | |
| 			p.Sub(p, rem)
 | |
| 			if p.BitLen() < L {
 | |
| 				continue
 | |
| 			}
 | |
| 
 | |
| 			if !p.ProbablyPrime(numMRTests) {
 | |
| 				continue
 | |
| 			}
 | |
| 
 | |
| 			params.P = p
 | |
| 			params.Q = q
 | |
| 			break GeneratePrimes
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	h := new(big.Int)
 | |
| 	h.SetInt64(2)
 | |
| 	g := new(big.Int)
 | |
| 
 | |
| 	pm1 := new(big.Int).Sub(p, one)
 | |
| 	e := new(big.Int).Div(pm1, q)
 | |
| 
 | |
| 	for {
 | |
| 		g.Exp(h, e, p)
 | |
| 		if g.Cmp(one) == 0 {
 | |
| 			h.Add(h, one)
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		params.G = g
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // GenerateKey generates a public&private key pair. The Parameters of the
 | |
| // PrivateKey must already be valid (see GenerateParameters).
 | |
| func GenerateKey(priv *PrivateKey, rand io.Reader) error {
 | |
| 	if priv.P == nil || priv.Q == nil || priv.G == nil {
 | |
| 		return errors.New("crypto/dsa: parameters not set up before generating key")
 | |
| 	}
 | |
| 
 | |
| 	x := new(big.Int)
 | |
| 	xBytes := make([]byte, priv.Q.BitLen()/8)
 | |
| 
 | |
| 	for {
 | |
| 		_, err := io.ReadFull(rand, xBytes)
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		x.SetBytes(xBytes)
 | |
| 		if x.Sign() != 0 && x.Cmp(priv.Q) < 0 {
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	priv.X = x
 | |
| 	priv.Y = new(big.Int)
 | |
| 	priv.Y.Exp(priv.G, x, priv.P)
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // fermatInverse calculates the inverse of k in GF(P) using Fermat's method.
 | |
| // This has better constant-time properties than Euclid's method (implemented
 | |
| // in math/big.Int.ModInverse) although math/big itself isn't strictly
 | |
| // constant-time so it's not perfect.
 | |
| func fermatInverse(k, P *big.Int) *big.Int {
 | |
| 	two := big.NewInt(2)
 | |
| 	pMinus2 := new(big.Int).Sub(P, two)
 | |
| 	return new(big.Int).Exp(k, pMinus2, P)
 | |
| }
 | |
| 
 | |
| // Sign signs an arbitrary length hash (which should be the result of hashing a
 | |
| // larger message) using the private key, priv. It returns the signature as a
 | |
| // pair of integers. The security of the private key depends on the entropy of
 | |
| // rand.
 | |
| //
 | |
| // Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
 | |
| // to the byte-length of the subgroup. This function does not perform that
 | |
| // truncation itself.
 | |
| //
 | |
| // Be aware that calling Sign with an attacker-controlled PrivateKey may
 | |
| // require an arbitrary amount of CPU.
 | |
| func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
 | |
| 	randutil.MaybeReadByte(rand)
 | |
| 
 | |
| 	// FIPS 186-3, section 4.6
 | |
| 
 | |
| 	n := priv.Q.BitLen()
 | |
| 	if priv.Q.Sign() <= 0 || priv.P.Sign() <= 0 || priv.G.Sign() <= 0 || priv.X.Sign() <= 0 || n&7 != 0 {
 | |
| 		err = ErrInvalidPublicKey
 | |
| 		return
 | |
| 	}
 | |
| 	n >>= 3
 | |
| 
 | |
| 	var attempts int
 | |
| 	for attempts = 10; attempts > 0; attempts-- {
 | |
| 		k := new(big.Int)
 | |
| 		buf := make([]byte, n)
 | |
| 		for {
 | |
| 			_, err = io.ReadFull(rand, buf)
 | |
| 			if err != nil {
 | |
| 				return
 | |
| 			}
 | |
| 			k.SetBytes(buf)
 | |
| 			// priv.Q must be >= 128 because the test above
 | |
| 			// requires it to be > 0 and that
 | |
| 			//    ceil(log_2(Q)) mod 8 = 0
 | |
| 			// Thus this loop will quickly terminate.
 | |
| 			if k.Sign() > 0 && k.Cmp(priv.Q) < 0 {
 | |
| 				break
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		kInv := fermatInverse(k, priv.Q)
 | |
| 
 | |
| 		r = new(big.Int).Exp(priv.G, k, priv.P)
 | |
| 		r.Mod(r, priv.Q)
 | |
| 
 | |
| 		if r.Sign() == 0 {
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		z := k.SetBytes(hash)
 | |
| 
 | |
| 		s = new(big.Int).Mul(priv.X, r)
 | |
| 		s.Add(s, z)
 | |
| 		s.Mod(s, priv.Q)
 | |
| 		s.Mul(s, kInv)
 | |
| 		s.Mod(s, priv.Q)
 | |
| 
 | |
| 		if s.Sign() != 0 {
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// Only degenerate private keys will require more than a handful of
 | |
| 	// attempts.
 | |
| 	if attempts == 0 {
 | |
| 		return nil, nil, ErrInvalidPublicKey
 | |
| 	}
 | |
| 
 | |
| 	return
 | |
| }
 | |
| 
 | |
| // Verify verifies the signature in r, s of hash using the public key, pub. It
 | |
| // reports whether the signature is valid.
 | |
| //
 | |
| // Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
 | |
| // to the byte-length of the subgroup. This function does not perform that
 | |
| // truncation itself.
 | |
| func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
 | |
| 	// FIPS 186-3, section 4.7
 | |
| 
 | |
| 	if pub.P.Sign() == 0 {
 | |
| 		return false
 | |
| 	}
 | |
| 
 | |
| 	if r.Sign() < 1 || r.Cmp(pub.Q) >= 0 {
 | |
| 		return false
 | |
| 	}
 | |
| 	if s.Sign() < 1 || s.Cmp(pub.Q) >= 0 {
 | |
| 		return false
 | |
| 	}
 | |
| 
 | |
| 	w := new(big.Int).ModInverse(s, pub.Q)
 | |
| 
 | |
| 	n := pub.Q.BitLen()
 | |
| 	if n&7 != 0 {
 | |
| 		return false
 | |
| 	}
 | |
| 	z := new(big.Int).SetBytes(hash)
 | |
| 
 | |
| 	u1 := new(big.Int).Mul(z, w)
 | |
| 	u1.Mod(u1, pub.Q)
 | |
| 	u2 := w.Mul(r, w)
 | |
| 	u2.Mod(u2, pub.Q)
 | |
| 	v := u1.Exp(pub.G, u1, pub.P)
 | |
| 	u2.Exp(pub.Y, u2, pub.P)
 | |
| 	v.Mul(v, u2)
 | |
| 	v.Mod(v, pub.P)
 | |
| 	v.Mod(v, pub.Q)
 | |
| 
 | |
| 	return v.Cmp(r) == 0
 | |
| }
 |