github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/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  // Sign signs an arbitrary length hash (which should be the result of hashing a
   177  // larger message) using the private key, priv. It returns the signature as a
   178  // pair of integers. The security of the private key depends on the entropy of
   179  // rand.
   180  //
   181  // Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
   182  // to the byte-length of the subgroup. This function does not perform that
   183  // truncation itself.
   184  func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
   185  	// FIPS 186-3, section 4.6
   186  
   187  	n := priv.Q.BitLen()
   188  	if n&7 != 0 {
   189  		err = ErrInvalidPublicKey
   190  		return
   191  	}
   192  	n >>= 3
   193  
   194  	for {
   195  		k := new(big.Int)
   196  		buf := make([]byte, n)
   197  		for {
   198  			_, err = io.ReadFull(rand, buf)
   199  			if err != nil {
   200  				return
   201  			}
   202  			k.SetBytes(buf)
   203  			if k.Sign() > 0 && k.Cmp(priv.Q) < 0 {
   204  				break
   205  			}
   206  		}
   207  
   208  		kInv := new(big.Int).ModInverse(k, priv.Q)
   209  
   210  		r = new(big.Int).Exp(priv.G, k, priv.P)
   211  		r.Mod(r, priv.Q)
   212  
   213  		if r.Sign() == 0 {
   214  			continue
   215  		}
   216  
   217  		z := k.SetBytes(hash)
   218  
   219  		s = new(big.Int).Mul(priv.X, r)
   220  		s.Add(s, z)
   221  		s.Mod(s, priv.Q)
   222  		s.Mul(s, kInv)
   223  		s.Mod(s, priv.Q)
   224  
   225  		if s.Sign() != 0 {
   226  			break
   227  		}
   228  	}
   229  
   230  	return
   231  }
   232  
   233  // Verify verifies the signature in r, s of hash using the public key, pub. It
   234  // reports whether the signature is valid.
   235  //
   236  // Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
   237  // to the byte-length of the subgroup. This function does not perform that
   238  // truncation itself.
   239  func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
   240  	// FIPS 186-3, section 4.7
   241  
   242  	if r.Sign() < 1 || r.Cmp(pub.Q) >= 0 {
   243  		return false
   244  	}
   245  	if s.Sign() < 1 || s.Cmp(pub.Q) >= 0 {
   246  		return false
   247  	}
   248  
   249  	w := new(big.Int).ModInverse(s, pub.Q)
   250  
   251  	n := pub.Q.BitLen()
   252  	if n&7 != 0 {
   253  		return false
   254  	}
   255  	z := new(big.Int).SetBytes(hash)
   256  
   257  	u1 := new(big.Int).Mul(z, w)
   258  	u1.Mod(u1, pub.Q)
   259  	u2 := w.Mul(r, w)
   260  	u2.Mod(u2, pub.Q)
   261  	v := u1.Exp(pub.G, u1, pub.P)
   262  	u2.Exp(pub.Y, u2, pub.P)
   263  	v.Mul(v, u2)
   264  	v.Mod(v, pub.P)
   265  	v.Mod(v, pub.Q)
   266  
   267  	return v.Cmp(r) == 0
   268  }