github.com/shijuvar/go@v0.0.0-20141209052335-e8f13700b70c/src/crypto/dsa/dsa.go (about)

     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 dsa implements the Digital Signature Algorithm, as defined in FIPS 186-3.
     6  package dsa
     7  
     8  import (
     9  	"errors"
    10  	"io"
    11  	"math/big"
    12  )
    13  
    14  // Parameters represents the domain parameters for a key. These parameters can
    15  // be shared across many keys. The bit length of Q must be a multiple of 8.
    16  type Parameters struct {
    17  	P, Q, G *big.Int
    18  }
    19  
    20  // PublicKey represents a DSA public key.
    21  type PublicKey struct {
    22  	Parameters
    23  	Y *big.Int
    24  }
    25  
    26  // PrivateKey represents a DSA private key.
    27  type PrivateKey struct {
    28  	PublicKey
    29  	X *big.Int
    30  }
    31  
    32  // ErrInvalidPublicKey results when a public key is not usable by this code.
    33  // FIPS is quite strict about the format of DSA keys, but other code may be
    34  // less so. Thus, when using keys which may have been generated by other code,
    35  // this error must be handled.
    36  var ErrInvalidPublicKey = errors.New("crypto/dsa: invalid public key")
    37  
    38  // ParameterSizes is a enumeration of the acceptable bit lengths of the primes
    39  // in a set of DSA parameters. See FIPS 186-3, section 4.2.
    40  type ParameterSizes int
    41  
    42  const (
    43  	L1024N160 ParameterSizes = iota
    44  	L2048N224
    45  	L2048N256
    46  	L3072N256
    47  )
    48  
    49  // numMRTests is the number of Miller-Rabin primality tests that we perform. We
    50  // pick the largest recommended number from table C.1 of FIPS 186-3.
    51  const numMRTests = 64
    52  
    53  // GenerateParameters puts a random, valid set of DSA parameters into params.
    54  // This function takes many seconds, even on fast machines.
    55  func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes) (err error) {
    56  	// This function doesn't follow FIPS 186-3 exactly in that it doesn't
    57  	// use a verification seed to generate the primes. The verification
    58  	// seed doesn't appear to be exported or used by other code and
    59  	// omitting it makes the code cleaner.
    60  
    61  	var L, N int
    62  	switch sizes {
    63  	case L1024N160:
    64  		L = 1024
    65  		N = 160
    66  	case L2048N224:
    67  		L = 2048
    68  		N = 224
    69  	case L2048N256:
    70  		L = 2048
    71  		N = 256
    72  	case L3072N256:
    73  		L = 3072
    74  		N = 256
    75  	default:
    76  		return errors.New("crypto/dsa: invalid ParameterSizes")
    77  	}
    78  
    79  	qBytes := make([]byte, N/8)
    80  	pBytes := make([]byte, L/8)
    81  
    82  	q := new(big.Int)
    83  	p := new(big.Int)
    84  	rem := new(big.Int)
    85  	one := new(big.Int)
    86  	one.SetInt64(1)
    87  
    88  GeneratePrimes:
    89  	for {
    90  		_, err = io.ReadFull(rand, qBytes)
    91  		if err != nil {
    92  			return
    93  		}
    94  
    95  		qBytes[len(qBytes)-1] |= 1
    96  		qBytes[0] |= 0x80
    97  		q.SetBytes(qBytes)
    98  
    99  		if !q.ProbablyPrime(numMRTests) {
   100  			continue
   101  		}
   102  
   103  		for i := 0; i < 4*L; i++ {
   104  			_, err = io.ReadFull(rand, pBytes)
   105  			if err != nil {
   106  				return
   107  			}
   108  
   109  			pBytes[len(pBytes)-1] |= 1
   110  			pBytes[0] |= 0x80
   111  
   112  			p.SetBytes(pBytes)
   113  			rem.Mod(p, q)
   114  			rem.Sub(rem, one)
   115  			p.Sub(p, rem)
   116  			if p.BitLen() < L {
   117  				continue
   118  			}
   119  
   120  			if !p.ProbablyPrime(numMRTests) {
   121  				continue
   122  			}
   123  
   124  			params.P = p
   125  			params.Q = q
   126  			break GeneratePrimes
   127  		}
   128  	}
   129  
   130  	h := new(big.Int)
   131  	h.SetInt64(2)
   132  	g := new(big.Int)
   133  
   134  	pm1 := new(big.Int).Sub(p, one)
   135  	e := new(big.Int).Div(pm1, q)
   136  
   137  	for {
   138  		g.Exp(h, e, p)
   139  		if g.Cmp(one) == 0 {
   140  			h.Add(h, one)
   141  			continue
   142  		}
   143  
   144  		params.G = g
   145  		return
   146  	}
   147  }
   148  
   149  // GenerateKey generates a public&private key pair. The Parameters of the
   150  // PrivateKey must already be valid (see GenerateParameters).
   151  func GenerateKey(priv *PrivateKey, rand io.Reader) error {
   152  	if priv.P == nil || priv.Q == nil || priv.G == nil {
   153  		return errors.New("crypto/dsa: parameters not set up before generating key")
   154  	}
   155  
   156  	x := new(big.Int)
   157  	xBytes := make([]byte, priv.Q.BitLen()/8)
   158  
   159  	for {
   160  		_, err := io.ReadFull(rand, xBytes)
   161  		if err != nil {
   162  			return err
   163  		}
   164  		x.SetBytes(xBytes)
   165  		if x.Sign() != 0 && x.Cmp(priv.Q) < 0 {
   166  			break
   167  		}
   168  	}
   169  
   170  	priv.X = x
   171  	priv.Y = new(big.Int)
   172  	priv.Y.Exp(priv.G, x, priv.P)
   173  	return nil
   174  }
   175  
   176  // fermatInverse calculates the inverse of k in GF(P) using Fermat's method.
   177  // This has better constant-time properties than Euclid's method (implemented
   178  // in math/big.Int.ModInverse) although math/big itself isn't strictly
   179  // constant-time so it's not perfect.
   180  func fermatInverse(k, P *big.Int) *big.Int {
   181  	two := big.NewInt(2)
   182  	pMinus2 := new(big.Int).Sub(P, two)
   183  	return new(big.Int).Exp(k, pMinus2, P)
   184  }
   185  
   186  // Sign signs an arbitrary length hash (which should be the result of hashing a
   187  // larger message) using the private key, priv. It returns the signature as a
   188  // pair of integers. The security of the private key depends on the entropy of
   189  // rand.
   190  //
   191  // Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
   192  // to the byte-length of the subgroup. This function does not perform that
   193  // truncation itself.
   194  func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
   195  	// FIPS 186-3, section 4.6
   196  
   197  	n := priv.Q.BitLen()
   198  	if n&7 != 0 {
   199  		err = ErrInvalidPublicKey
   200  		return
   201  	}
   202  	n >>= 3
   203  
   204  	for {
   205  		k := new(big.Int)
   206  		buf := make([]byte, n)
   207  		for {
   208  			_, err = io.ReadFull(rand, buf)
   209  			if err != nil {
   210  				return
   211  			}
   212  			k.SetBytes(buf)
   213  			if k.Sign() > 0 && k.Cmp(priv.Q) < 0 {
   214  				break
   215  			}
   216  		}
   217  
   218  		kInv := fermatInverse(k, priv.Q)
   219  
   220  		r = new(big.Int).Exp(priv.G, k, priv.P)
   221  		r.Mod(r, priv.Q)
   222  
   223  		if r.Sign() == 0 {
   224  			continue
   225  		}
   226  
   227  		z := k.SetBytes(hash)
   228  
   229  		s = new(big.Int).Mul(priv.X, r)
   230  		s.Add(s, z)
   231  		s.Mod(s, priv.Q)
   232  		s.Mul(s, kInv)
   233  		s.Mod(s, priv.Q)
   234  
   235  		if s.Sign() != 0 {
   236  			break
   237  		}
   238  	}
   239  
   240  	return
   241  }
   242  
   243  // Verify verifies the signature in r, s of hash using the public key, pub. It
   244  // reports whether the signature is valid.
   245  //
   246  // Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
   247  // to the byte-length of the subgroup. This function does not perform that
   248  // truncation itself.
   249  func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
   250  	// FIPS 186-3, section 4.7
   251  
   252  	if r.Sign() < 1 || r.Cmp(pub.Q) >= 0 {
   253  		return false
   254  	}
   255  	if s.Sign() < 1 || s.Cmp(pub.Q) >= 0 {
   256  		return false
   257  	}
   258  
   259  	w := new(big.Int).ModInverse(s, pub.Q)
   260  
   261  	n := pub.Q.BitLen()
   262  	if n&7 != 0 {
   263  		return false
   264  	}
   265  	z := new(big.Int).SetBytes(hash)
   266  
   267  	u1 := new(big.Int).Mul(z, w)
   268  	u1.Mod(u1, pub.Q)
   269  	u2 := w.Mul(r, w)
   270  	u2.Mod(u2, pub.Q)
   271  	v := u1.Exp(pub.G, u1, pub.P)
   272  	u2.Exp(pub.Y, u2, pub.P)
   273  	v.Mul(v, u2)
   274  	v.Mod(v, pub.P)
   275  	v.Mod(v, pub.Q)
   276  
   277  	return v.Cmp(r) == 0
   278  }