github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/crypto/rsa/pss_test.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_test 6 7 import ( 8 "bufio" 9 "bytes" 10 "compress/bzip2" 11 "crypto" 12 "crypto/rand" 13 . "crypto/rsa" 14 "crypto/sha1" 15 "crypto/sha256" 16 "encoding/hex" 17 "math/big" 18 "os" 19 "strconv" 20 "strings" 21 "testing" 22 ) 23 24 func TestEMSAPSS(t *testing.T) { 25 // Test vector in file pss-int.txt from: ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip 26 msg := []byte{ 27 0x85, 0x9e, 0xef, 0x2f, 0xd7, 0x8a, 0xca, 0x00, 0x30, 0x8b, 28 0xdc, 0x47, 0x11, 0x93, 0xbf, 0x55, 0xbf, 0x9d, 0x78, 0xdb, 29 0x8f, 0x8a, 0x67, 0x2b, 0x48, 0x46, 0x34, 0xf3, 0xc9, 0xc2, 30 0x6e, 0x64, 0x78, 0xae, 0x10, 0x26, 0x0f, 0xe0, 0xdd, 0x8c, 31 0x08, 0x2e, 0x53, 0xa5, 0x29, 0x3a, 0xf2, 0x17, 0x3c, 0xd5, 32 0x0c, 0x6d, 0x5d, 0x35, 0x4f, 0xeb, 0xf7, 0x8b, 0x26, 0x02, 33 0x1c, 0x25, 0xc0, 0x27, 0x12, 0xe7, 0x8c, 0xd4, 0x69, 0x4c, 34 0x9f, 0x46, 0x97, 0x77, 0xe4, 0x51, 0xe7, 0xf8, 0xe9, 0xe0, 35 0x4c, 0xd3, 0x73, 0x9c, 0x6b, 0xbf, 0xed, 0xae, 0x48, 0x7f, 36 0xb5, 0x56, 0x44, 0xe9, 0xca, 0x74, 0xff, 0x77, 0xa5, 0x3c, 37 0xb7, 0x29, 0x80, 0x2f, 0x6e, 0xd4, 0xa5, 0xff, 0xa8, 0xba, 38 0x15, 0x98, 0x90, 0xfc, 39 } 40 salt := []byte{ 41 0xe3, 0xb5, 0xd5, 0xd0, 0x02, 0xc1, 0xbc, 0xe5, 0x0c, 0x2b, 42 0x65, 0xef, 0x88, 0xa1, 0x88, 0xd8, 0x3b, 0xce, 0x7e, 0x61, 43 } 44 expected := []byte{ 45 0x66, 0xe4, 0x67, 0x2e, 0x83, 0x6a, 0xd1, 0x21, 0xba, 0x24, 46 0x4b, 0xed, 0x65, 0x76, 0xb8, 0x67, 0xd9, 0xa4, 0x47, 0xc2, 47 0x8a, 0x6e, 0x66, 0xa5, 0xb8, 0x7d, 0xee, 0x7f, 0xbc, 0x7e, 48 0x65, 0xaf, 0x50, 0x57, 0xf8, 0x6f, 0xae, 0x89, 0x84, 0xd9, 49 0xba, 0x7f, 0x96, 0x9a, 0xd6, 0xfe, 0x02, 0xa4, 0xd7, 0x5f, 50 0x74, 0x45, 0xfe, 0xfd, 0xd8, 0x5b, 0x6d, 0x3a, 0x47, 0x7c, 51 0x28, 0xd2, 0x4b, 0xa1, 0xe3, 0x75, 0x6f, 0x79, 0x2d, 0xd1, 52 0xdc, 0xe8, 0xca, 0x94, 0x44, 0x0e, 0xcb, 0x52, 0x79, 0xec, 53 0xd3, 0x18, 0x3a, 0x31, 0x1f, 0xc8, 0x96, 0xda, 0x1c, 0xb3, 54 0x93, 0x11, 0xaf, 0x37, 0xea, 0x4a, 0x75, 0xe2, 0x4b, 0xdb, 55 0xfd, 0x5c, 0x1d, 0xa0, 0xde, 0x7c, 0xec, 0xdf, 0x1a, 0x89, 56 0x6f, 0x9d, 0x8b, 0xc8, 0x16, 0xd9, 0x7c, 0xd7, 0xa2, 0xc4, 57 0x3b, 0xad, 0x54, 0x6f, 0xbe, 0x8c, 0xfe, 0xbc, 58 } 59 60 hash := sha1.New() 61 hash.Write(msg) 62 hashed := hash.Sum(nil) 63 64 encoded, err := EMSAPSSEncode(hashed, 1023, salt, sha1.New()) 65 if err != nil { 66 t.Errorf("Error from emsaPSSEncode: %s\n", err) 67 } 68 if !bytes.Equal(encoded, expected) { 69 t.Errorf("Bad encoding. got %x, want %x", encoded, expected) 70 } 71 72 if err = EMSAPSSVerify(hashed, encoded, 1023, len(salt), sha1.New()); err != nil { 73 t.Errorf("Bad verification: %s", err) 74 } 75 } 76 77 // TestPSSGolden tests all the test vectors in pss-vect.txt from 78 // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip 79 func TestPSSGolden(t *testing.T) { 80 inFile, err := os.Open("testdata/pss-vect.txt.bz2") 81 if err != nil { 82 t.Fatalf("Failed to open input file: %s", err) 83 } 84 defer inFile.Close() 85 86 // The pss-vect.txt file contains RSA keys and then a series of 87 // signatures. A goroutine is used to preprocess the input by merging 88 // lines, removing spaces in hex values and identifying the start of 89 // new keys and signature blocks. 90 const newKeyMarker = "START NEW KEY" 91 const newSignatureMarker = "START NEW SIGNATURE" 92 93 values := make(chan string) 94 95 go func() { 96 defer close(values) 97 scanner := bufio.NewScanner(bzip2.NewReader(inFile)) 98 var partialValue string 99 lastWasValue := true 100 101 for scanner.Scan() { 102 line := scanner.Text() 103 switch { 104 case len(line) == 0: 105 if len(partialValue) > 0 { 106 values <- strings.ReplaceAll(partialValue, " ", "") 107 partialValue = "" 108 lastWasValue = true 109 } 110 continue 111 case strings.HasPrefix(line, "# ======") && lastWasValue: 112 values <- newKeyMarker 113 lastWasValue = false 114 case strings.HasPrefix(line, "# ------") && lastWasValue: 115 values <- newSignatureMarker 116 lastWasValue = false 117 case strings.HasPrefix(line, "#"): 118 continue 119 default: 120 partialValue += line 121 } 122 } 123 if err := scanner.Err(); err != nil { 124 panic(err) 125 } 126 }() 127 128 var key *PublicKey 129 var hashed []byte 130 hash := crypto.SHA1 131 h := hash.New() 132 opts := &PSSOptions{ 133 SaltLength: PSSSaltLengthEqualsHash, 134 } 135 136 for marker := range values { 137 switch marker { 138 case newKeyMarker: 139 key = new(PublicKey) 140 nHex, ok := <-values 141 if !ok { 142 continue 143 } 144 key.N = bigFromHex(nHex) 145 key.E = intFromHex(<-values) 146 // We don't care for d, p, q, dP, dQ or qInv. 147 for i := 0; i < 6; i++ { 148 <-values 149 } 150 case newSignatureMarker: 151 msg := fromHex(<-values) 152 <-values // skip salt 153 sig := fromHex(<-values) 154 155 h.Reset() 156 h.Write(msg) 157 hashed = h.Sum(hashed[:0]) 158 159 if err := VerifyPSS(key, hash, hashed, sig, opts); err != nil { 160 t.Error(err) 161 } 162 default: 163 t.Fatalf("unknown marker: " + marker) 164 } 165 } 166 } 167 168 // TestPSSOpenSSL ensures that we can verify a PSS signature from OpenSSL with 169 // the default options. OpenSSL sets the salt length to be maximal. 170 func TestPSSOpenSSL(t *testing.T) { 171 hash := crypto.SHA256 172 h := hash.New() 173 h.Write([]byte("testing")) 174 hashed := h.Sum(nil) 175 176 // Generated with `echo -n testing | openssl dgst -sign key.pem -sigopt rsa_padding_mode:pss -sha256 > sig` 177 sig := []byte{ 178 0x95, 0x59, 0x6f, 0xd3, 0x10, 0xa2, 0xe7, 0xa2, 0x92, 0x9d, 179 0x4a, 0x07, 0x2e, 0x2b, 0x27, 0xcc, 0x06, 0xc2, 0x87, 0x2c, 180 0x52, 0xf0, 0x4a, 0xcc, 0x05, 0x94, 0xf2, 0xc3, 0x2e, 0x20, 181 0xd7, 0x3e, 0x66, 0x62, 0xb5, 0x95, 0x2b, 0xa3, 0x93, 0x9a, 182 0x66, 0x64, 0x25, 0xe0, 0x74, 0x66, 0x8c, 0x3e, 0x92, 0xeb, 183 0xc6, 0xe6, 0xc0, 0x44, 0xf3, 0xb4, 0xb4, 0x2e, 0x8c, 0x66, 184 0x0a, 0x37, 0x9c, 0x69, 185 } 186 187 if err := VerifyPSS(&rsaPrivateKey.PublicKey, hash, hashed, sig, nil); err != nil { 188 t.Error(err) 189 } 190 } 191 192 func TestPSSNilOpts(t *testing.T) { 193 hash := crypto.SHA256 194 h := hash.New() 195 h.Write([]byte("testing")) 196 hashed := h.Sum(nil) 197 198 SignPSS(rand.Reader, rsaPrivateKey, hash, hashed, nil) 199 } 200 201 func TestPSSSigning(t *testing.T) { 202 var saltLengthCombinations = []struct { 203 signSaltLength, verifySaltLength int 204 good bool 205 }{ 206 {PSSSaltLengthAuto, PSSSaltLengthAuto, true}, 207 {PSSSaltLengthEqualsHash, PSSSaltLengthAuto, true}, 208 {PSSSaltLengthEqualsHash, PSSSaltLengthEqualsHash, true}, 209 {PSSSaltLengthEqualsHash, 8, false}, 210 {PSSSaltLengthAuto, PSSSaltLengthEqualsHash, false}, 211 {8, 8, true}, 212 {PSSSaltLengthAuto, 42, true}, 213 {PSSSaltLengthAuto, 20, false}, 214 {PSSSaltLengthAuto, -2, false}, 215 } 216 217 hash := crypto.SHA1 218 h := hash.New() 219 h.Write([]byte("testing")) 220 hashed := h.Sum(nil) 221 var opts PSSOptions 222 223 for i, test := range saltLengthCombinations { 224 opts.SaltLength = test.signSaltLength 225 sig, err := SignPSS(rand.Reader, rsaPrivateKey, hash, hashed, &opts) 226 if err != nil { 227 t.Errorf("#%d: error while signing: %s", i, err) 228 continue 229 } 230 231 opts.SaltLength = test.verifySaltLength 232 err = VerifyPSS(&rsaPrivateKey.PublicKey, hash, hashed, sig, &opts) 233 if (err == nil) != test.good { 234 t.Errorf("#%d: bad result, wanted: %t, got: %s", i, test.good, err) 235 } 236 } 237 } 238 239 func TestPSS513(t *testing.T) { 240 // See Issue 42741, and separately, RFC 8017: "Note that the octet length of 241 // EM will be one less than k if modBits - 1 is divisible by 8 and equal to 242 // k otherwise, where k is the length in octets of the RSA modulus n." 243 key, err := GenerateKey(rand.Reader, 513) 244 if err != nil { 245 t.Fatal(err) 246 } 247 digest := sha256.Sum256([]byte("message")) 248 signature, err := key.Sign(rand.Reader, digest[:], &PSSOptions{ 249 SaltLength: PSSSaltLengthAuto, 250 Hash: crypto.SHA256, 251 }) 252 if err != nil { 253 t.Fatal(err) 254 } 255 err = VerifyPSS(&key.PublicKey, crypto.SHA256, digest[:], signature, nil) 256 if err != nil { 257 t.Error(err) 258 } 259 } 260 261 func bigFromHex(hex string) *big.Int { 262 n, ok := new(big.Int).SetString(hex, 16) 263 if !ok { 264 panic("bad hex: " + hex) 265 } 266 return n 267 } 268 269 func intFromHex(hex string) int { 270 i, err := strconv.ParseInt(hex, 16, 32) 271 if err != nil { 272 panic(err) 273 } 274 return int(i) 275 } 276 277 func fromHex(hexStr string) []byte { 278 s, err := hex.DecodeString(hexStr) 279 if err != nil { 280 panic(err) 281 } 282 return s 283 } 284 285 func TestInvalidPSSSaltLength(t *testing.T) { 286 key, err := GenerateKey(rand.Reader, 245) 287 if err != nil { 288 t.Fatal(err) 289 } 290 291 digest := sha256.Sum256([]byte("message")) 292 // We don't check the exact error matches, because crypto/rsa and crypto/internal/boring 293 // return two different error variables, which have the same content but are not equal. 294 if _, err := SignPSS(rand.Reader, key, crypto.SHA256, digest[:], &PSSOptions{ 295 SaltLength: -2, 296 Hash: crypto.SHA256, 297 }); err.Error() != InvalidSaltLenErr.Error() { 298 t.Fatalf("SignPSS unexpected error: got %v, want %v", err, InvalidSaltLenErr) 299 } 300 301 // We don't check the specific error here, because crypto/rsa and crypto/internal/boring 302 // return different errors, so we just check that _an error_ was returned. 303 if err := VerifyPSS(&key.PublicKey, crypto.SHA256, []byte{1, 2, 3}, make([]byte, 31), &PSSOptions{ 304 SaltLength: -2, 305 }); err == nil { 306 t.Fatal("VerifyPSS unexpected success") 307 } 308 }