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