github.com/insolar/x-crypto@v0.0.0-20191031140942-75fab8a325f6/rsa/pss.go (about) 1 // Copyright 2013 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 rsa 6 7 // This file implements the PSS signature scheme [1]. 8 // 9 // [1] https://www.emc.com/collateral/white-papers/h11300-pkcs-1v2-2-rsa-cryptography-standard-wp.pdf 10 11 import ( 12 "bytes" 13 "errors" 14 "github.com/insolar/x-crypto" 15 "hash" 16 "io" 17 "math/big" 18 ) 19 20 func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byte, error) { 21 // See [1], section 9.1.1 22 hLen := hash.Size() 23 sLen := len(salt) 24 emLen := (emBits + 7) / 8 25 26 // 1. If the length of M is greater than the input limitation for the 27 // hash function (2^61 - 1 octets for SHA-1), output "message too 28 // long" and stop. 29 // 30 // 2. Let mHash = Hash(M), an octet string of length hLen. 31 32 if len(mHash) != hLen { 33 return nil, errors.New("crypto/rsa: input must be hashed message") 34 } 35 36 // 3. If emLen < hLen + sLen + 2, output "encoding error" and stop. 37 38 if emLen < hLen+sLen+2 { 39 return nil, errors.New("crypto/rsa: key size too small for PSS signature") 40 } 41 42 em := make([]byte, emLen) 43 db := em[:emLen-sLen-hLen-2+1+sLen] 44 h := em[emLen-sLen-hLen-2+1+sLen : emLen-1] 45 46 // 4. Generate a random octet string salt of length sLen; if sLen = 0, 47 // then salt is the empty string. 48 // 49 // 5. Let 50 // M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt; 51 // 52 // M' is an octet string of length 8 + hLen + sLen with eight 53 // initial zero octets. 54 // 55 // 6. Let H = Hash(M'), an octet string of length hLen. 56 57 var prefix [8]byte 58 59 hash.Write(prefix[:]) 60 hash.Write(mHash) 61 hash.Write(salt) 62 63 h = hash.Sum(h[:0]) 64 hash.Reset() 65 66 // 7. Generate an octet string PS consisting of emLen - sLen - hLen - 2 67 // zero octets. The length of PS may be 0. 68 // 69 // 8. Let DB = PS || 0x01 || salt; DB is an octet string of length 70 // emLen - hLen - 1. 71 72 db[emLen-sLen-hLen-2] = 0x01 73 copy(db[emLen-sLen-hLen-1:], salt) 74 75 // 9. Let dbMask = MGF(H, emLen - hLen - 1). 76 // 77 // 10. Let maskedDB = DB \xor dbMask. 78 79 mgf1XOR(db, hash, h) 80 81 // 11. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in 82 // maskedDB to zero. 83 84 db[0] &= 0xFF >> uint(8*emLen-emBits) 85 86 // 12. Let EM = maskedDB || H || 0xbc. 87 em[emLen-1] = 0xBC 88 89 // 13. Output EM. 90 return em, nil 91 } 92 93 func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error { 94 // 1. If the length of M is greater than the input limitation for the 95 // hash function (2^61 - 1 octets for SHA-1), output "inconsistent" 96 // and stop. 97 // 98 // 2. Let mHash = Hash(M), an octet string of length hLen. 99 hLen := hash.Size() 100 if hLen != len(mHash) { 101 return ErrVerification 102 } 103 104 // 3. If emLen < hLen + sLen + 2, output "inconsistent" and stop. 105 emLen := (emBits + 7) / 8 106 if emLen < hLen+sLen+2 { 107 return ErrVerification 108 } 109 110 // 4. If the rightmost octet of EM does not have hexadecimal value 111 // 0xbc, output "inconsistent" and stop. 112 if em[len(em)-1] != 0xBC { 113 return ErrVerification 114 } 115 116 // 5. Let maskedDB be the leftmost emLen - hLen - 1 octets of EM, and 117 // let H be the next hLen octets. 118 db := em[:emLen-hLen-1] 119 h := em[emLen-hLen-1 : len(em)-1] 120 121 // 6. If the leftmost 8 * emLen - emBits bits of the leftmost octet in 122 // maskedDB are not all equal to zero, output "inconsistent" and 123 // stop. 124 if em[0]&(0xFF<<uint(8-(8*emLen-emBits))) != 0 { 125 return ErrVerification 126 } 127 128 // 7. Let dbMask = MGF(H, emLen - hLen - 1). 129 // 130 // 8. Let DB = maskedDB \xor dbMask. 131 mgf1XOR(db, hash, h) 132 133 // 9. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in DB 134 // to zero. 135 db[0] &= 0xFF >> uint(8*emLen-emBits) 136 137 if sLen == PSSSaltLengthAuto { 138 FindSaltLength: 139 for sLen = emLen - (hLen + 2); sLen >= 0; sLen-- { 140 switch db[emLen-hLen-sLen-2] { 141 case 1: 142 break FindSaltLength 143 case 0: 144 continue 145 default: 146 return ErrVerification 147 } 148 } 149 if sLen < 0 { 150 return ErrVerification 151 } 152 } else { 153 // 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero 154 // or if the octet at position emLen - hLen - sLen - 1 (the leftmost 155 // position is "position 1") does not have hexadecimal value 0x01, 156 // output "inconsistent" and stop. 157 for _, e := range db[:emLen-hLen-sLen-2] { 158 if e != 0x00 { 159 return ErrVerification 160 } 161 } 162 if db[emLen-hLen-sLen-2] != 0x01 { 163 return ErrVerification 164 } 165 } 166 167 // 11. Let salt be the last sLen octets of DB. 168 salt := db[len(db)-sLen:] 169 170 // 12. Let 171 // M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt ; 172 // M' is an octet string of length 8 + hLen + sLen with eight 173 // initial zero octets. 174 // 175 // 13. Let H' = Hash(M'), an octet string of length hLen. 176 var prefix [8]byte 177 hash.Write(prefix[:]) 178 hash.Write(mHash) 179 hash.Write(salt) 180 181 h0 := hash.Sum(nil) 182 183 // 14. If H = H', output "consistent." Otherwise, output "inconsistent." 184 if !bytes.Equal(h0, h) { 185 return ErrVerification 186 } 187 return nil 188 } 189 190 // signPSSWithSalt calculates the signature of hashed using PSS [1] with specified salt. 191 // Note that hashed must be the result of hashing the input message using the 192 // given hash function. salt is a random sequence of bytes whose length will be 193 // later used to verify the signature. 194 func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) (s []byte, err error) { 195 nBits := priv.N.BitLen() 196 em, err := emsaPSSEncode(hashed, nBits-1, salt, hash.New()) 197 if err != nil { 198 return 199 } 200 m := new(big.Int).SetBytes(em) 201 c, err := decryptAndCheck(rand, priv, m) 202 if err != nil { 203 return 204 } 205 s = make([]byte, (nBits+7)/8) 206 copyWithLeftPad(s, c.Bytes()) 207 return 208 } 209 210 const ( 211 // PSSSaltLengthAuto causes the salt in a PSS signature to be as large 212 // as possible when signing, and to be auto-detected when verifying. 213 PSSSaltLengthAuto = 0 214 // PSSSaltLengthEqualsHash causes the salt length to equal the length 215 // of the hash used in the signature. 216 PSSSaltLengthEqualsHash = -1 217 ) 218 219 // PSSOptions contains options for creating and verifying PSS signatures. 220 type PSSOptions struct { 221 // SaltLength controls the length of the salt used in the PSS 222 // signature. It can either be a number of bytes, or one of the special 223 // PSSSaltLength constants. 224 SaltLength int 225 226 // Hash, if not zero, overrides the hash function passed to SignPSS. 227 // This is the only way to specify the hash function when using the 228 // crypto.Signer interface. 229 Hash crypto.Hash 230 } 231 232 // HashFunc returns pssOpts.Hash so that PSSOptions implements 233 // crypto.SignerOpts. 234 func (pssOpts *PSSOptions) HashFunc() crypto.Hash { 235 return pssOpts.Hash 236 } 237 238 func (opts *PSSOptions) saltLength() int { 239 if opts == nil { 240 return PSSSaltLengthAuto 241 } 242 return opts.SaltLength 243 } 244 245 // SignPSS calculates the signature of hashed using RSASSA-PSS [1]. 246 // Note that hashed must be the result of hashing the input message using the 247 // given hash function. The opts argument may be nil, in which case sensible 248 // defaults are used. 249 func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte, opts *PSSOptions) ([]byte, error) { 250 saltLength := opts.saltLength() 251 switch saltLength { 252 case PSSSaltLengthAuto: 253 saltLength = (priv.N.BitLen()+7)/8 - 2 - hash.Size() 254 case PSSSaltLengthEqualsHash: 255 saltLength = hash.Size() 256 } 257 258 if opts != nil && opts.Hash != 0 { 259 hash = opts.Hash 260 } 261 262 salt := make([]byte, saltLength) 263 if _, err := io.ReadFull(rand, salt); err != nil { 264 return nil, err 265 } 266 return signPSSWithSalt(rand, priv, hash, hashed, salt) 267 } 268 269 // VerifyPSS verifies a PSS signature. 270 // hashed is the result of hashing the input message using the given hash 271 // function and sig is the signature. A valid signature is indicated by 272 // returning a nil error. The opts argument may be nil, in which case sensible 273 // defaults are used. 274 func VerifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, opts *PSSOptions) error { 275 return verifyPSS(pub, hash, hashed, sig, opts.saltLength()) 276 } 277 278 // verifyPSS verifies a PSS signature with the given salt length. 279 func verifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, saltLen int) error { 280 nBits := pub.N.BitLen() 281 if len(sig) != (nBits+7)/8 { 282 return ErrVerification 283 } 284 s := new(big.Int).SetBytes(sig) 285 m := encrypt(new(big.Int), pub, s) 286 emBits := nBits - 1 287 emLen := (emBits + 7) / 8 288 if emLen < len(m.Bytes()) { 289 return ErrVerification 290 } 291 em := make([]byte, emLen) 292 copyWithLeftPad(em, m.Bytes()) 293 if saltLen == PSSSaltLengthEqualsHash { 294 saltLen = hash.Size() 295 } 296 return emsaPSSVerify(hashed, em, emBits, saltLen, hash.New()) 297 }