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