github.com/panjjo/go@v0.0.0-20161104043856-d62b31386338/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 can take many seconds, even on fast machines.
    55  func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes) 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  		if _, err := io.ReadFull(rand, qBytes); err != nil {
    91  			return err
    92  		}
    93  
    94  		qBytes[len(qBytes)-1] |= 1
    95  		qBytes[0] |= 0x80
    96  		q.SetBytes(qBytes)
    97  
    98  		if !q.ProbablyPrime(numMRTests) {
    99  			continue
   100  		}
   101  
   102  		for i := 0; i < 4*L; i++ {
   103  			if _, err := io.ReadFull(rand, pBytes); err != nil {
   104  				return err
   105  			}
   106  
   107  			pBytes[len(pBytes)-1] |= 1
   108  			pBytes[0] |= 0x80
   109  
   110  			p.SetBytes(pBytes)
   111  			rem.Mod(p, q)
   112  			rem.Sub(rem, one)
   113  			p.Sub(p, rem)
   114  			if p.BitLen() < L {
   115  				continue
   116  			}
   117  
   118  			if !p.ProbablyPrime(numMRTests) {
   119  				continue
   120  			}
   121  
   122  			params.P = p
   123  			params.Q = q
   124  			break GeneratePrimes
   125  		}
   126  	}
   127  
   128  	h := new(big.Int)
   129  	h.SetInt64(2)
   130  	g := new(big.Int)
   131  
   132  	pm1 := new(big.Int).Sub(p, one)
   133  	e := new(big.Int).Div(pm1, q)
   134  
   135  	for {
   136  		g.Exp(h, e, p)
   137  		if g.Cmp(one) == 0 {
   138  			h.Add(h, one)
   139  			continue
   140  		}
   141  
   142  		params.G = g
   143  		return nil
   144  	}
   145  }
   146  
   147  // GenerateKey generates a public&private key pair. The Parameters of the
   148  // PrivateKey must already be valid (see GenerateParameters).
   149  func GenerateKey(priv *PrivateKey, rand io.Reader) error {
   150  	if priv.P == nil || priv.Q == nil || priv.G == nil {
   151  		return errors.New("crypto/dsa: parameters not set up before generating key")
   152  	}
   153  
   154  	x := new(big.Int)
   155  	xBytes := make([]byte, priv.Q.BitLen()/8)
   156  
   157  	for {
   158  		_, err := io.ReadFull(rand, xBytes)
   159  		if err != nil {
   160  			return err
   161  		}
   162  		x.SetBytes(xBytes)
   163  		if x.Sign() != 0 && x.Cmp(priv.Q) < 0 {
   164  			break
   165  		}
   166  	}
   167  
   168  	priv.X = x
   169  	priv.Y = new(big.Int)
   170  	priv.Y.Exp(priv.G, x, priv.P)
   171  	return nil
   172  }
   173  
   174  // fermatInverse calculates the inverse of k in GF(P) using Fermat's method.
   175  // This has better constant-time properties than Euclid's method (implemented
   176  // in math/big.Int.ModInverse) although math/big itself isn't strictly
   177  // constant-time so it's not perfect.
   178  func fermatInverse(k, P *big.Int) *big.Int {
   179  	two := big.NewInt(2)
   180  	pMinus2 := new(big.Int).Sub(P, two)
   181  	return new(big.Int).Exp(k, pMinus2, P)
   182  }
   183  
   184  // Sign signs an arbitrary length hash (which should be the result of hashing a
   185  // larger message) using the private key, priv. It returns the signature as a
   186  // pair of integers. The security of the private key depends on the entropy of
   187  // rand.
   188  //
   189  // Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
   190  // to the byte-length of the subgroup. This function does not perform that
   191  // truncation itself.
   192  func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
   193  	// FIPS 186-3, section 4.6
   194  
   195  	n := priv.Q.BitLen()
   196  	if n&7 != 0 {
   197  		err = ErrInvalidPublicKey
   198  		return
   199  	}
   200  	n >>= 3
   201  
   202  	for {
   203  		k := new(big.Int)
   204  		buf := make([]byte, n)
   205  		for {
   206  			_, err = io.ReadFull(rand, buf)
   207  			if err != nil {
   208  				return
   209  			}
   210  			k.SetBytes(buf)
   211  			if k.Sign() > 0 && k.Cmp(priv.Q) < 0 {
   212  				break
   213  			}
   214  		}
   215  
   216  		kInv := fermatInverse(k, priv.Q)
   217  
   218  		r = new(big.Int).Exp(priv.G, k, priv.P)
   219  		r.Mod(r, priv.Q)
   220  
   221  		if r.Sign() == 0 {
   222  			continue
   223  		}
   224  
   225  		z := k.SetBytes(hash)
   226  
   227  		s = new(big.Int).Mul(priv.X, r)
   228  		s.Add(s, z)
   229  		s.Mod(s, priv.Q)
   230  		s.Mul(s, kInv)
   231  		s.Mod(s, priv.Q)
   232  
   233  		if s.Sign() != 0 {
   234  			break
   235  		}
   236  	}
   237  
   238  	return
   239  }
   240  
   241  // Verify verifies the signature in r, s of hash using the public key, pub. It
   242  // reports whether the signature is valid.
   243  //
   244  // Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
   245  // to the byte-length of the subgroup. This function does not perform that
   246  // truncation itself.
   247  func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
   248  	// FIPS 186-3, section 4.7
   249  
   250  	if pub.P.Sign() == 0 {
   251  		return false
   252  	}
   253  
   254  	if r.Sign() < 1 || r.Cmp(pub.Q) >= 0 {
   255  		return false
   256  	}
   257  	if s.Sign() < 1 || s.Cmp(pub.Q) >= 0 {
   258  		return false
   259  	}
   260  
   261  	w := new(big.Int).ModInverse(s, pub.Q)
   262  
   263  	n := pub.Q.BitLen()
   264  	if n&7 != 0 {
   265  		return false
   266  	}
   267  	z := new(big.Int).SetBytes(hash)
   268  
   269  	u1 := new(big.Int).Mul(z, w)
   270  	u1.Mod(u1, pub.Q)
   271  	u2 := w.Mul(r, w)
   272  	u2.Mod(u2, pub.Q)
   273  	v := u1.Exp(pub.G, u1, pub.P)
   274  	u2.Exp(pub.Y, u2, pub.P)
   275  	v.Mul(v, u2)
   276  	v.Mod(v, pub.P)
   277  	v.Mod(v, pub.Q)
   278  
   279  	return v.Cmp(r) == 0
   280  }