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.
23 func TestEMSAPSS(t *testing.T) {
24 // Test vector in file pss-int.txt from: ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
26 0x85, 0x9e, 0xef, 0x2f, 0xd7, 0x8a, 0xca, 0x00, 0x30, 0x8b,
27 0xdc, 0x47, 0x11, 0x93, 0xbf, 0x55, 0xbf, 0x9d, 0x78, 0xdb,
28 0x8f, 0x8a, 0x67, 0x2b, 0x48, 0x46, 0x34, 0xf3, 0xc9, 0xc2,
29 0x6e, 0x64, 0x78, 0xae, 0x10, 0x26, 0x0f, 0xe0, 0xdd, 0x8c,
30 0x08, 0x2e, 0x53, 0xa5, 0x29, 0x3a, 0xf2, 0x17, 0x3c, 0xd5,
31 0x0c, 0x6d, 0x5d, 0x35, 0x4f, 0xeb, 0xf7, 0x8b, 0x26, 0x02,
32 0x1c, 0x25, 0xc0, 0x27, 0x12, 0xe7, 0x8c, 0xd4, 0x69, 0x4c,
33 0x9f, 0x46, 0x97, 0x77, 0xe4, 0x51, 0xe7, 0xf8, 0xe9, 0xe0,
34 0x4c, 0xd3, 0x73, 0x9c, 0x6b, 0xbf, 0xed, 0xae, 0x48, 0x7f,
35 0xb5, 0x56, 0x44, 0xe9, 0xca, 0x74, 0xff, 0x77, 0xa5, 0x3c,
36 0xb7, 0x29, 0x80, 0x2f, 0x6e, 0xd4, 0xa5, 0xff, 0xa8, 0xba,
37 0x15, 0x98, 0x90, 0xfc,
40 0xe3, 0xb5, 0xd5, 0xd0, 0x02, 0xc1, 0xbc, 0xe5, 0x0c, 0x2b,
41 0x65, 0xef, 0x88, 0xa1, 0x88, 0xd8, 0x3b, 0xce, 0x7e, 0x61,
44 0x66, 0xe4, 0x67, 0x2e, 0x83, 0x6a, 0xd1, 0x21, 0xba, 0x24,
45 0x4b, 0xed, 0x65, 0x76, 0xb8, 0x67, 0xd9, 0xa4, 0x47, 0xc2,
46 0x8a, 0x6e, 0x66, 0xa5, 0xb8, 0x7d, 0xee, 0x7f, 0xbc, 0x7e,
47 0x65, 0xaf, 0x50, 0x57, 0xf8, 0x6f, 0xae, 0x89, 0x84, 0xd9,
48 0xba, 0x7f, 0x96, 0x9a, 0xd6, 0xfe, 0x02, 0xa4, 0xd7, 0x5f,
49 0x74, 0x45, 0xfe, 0xfd, 0xd8, 0x5b, 0x6d, 0x3a, 0x47, 0x7c,
50 0x28, 0xd2, 0x4b, 0xa1, 0xe3, 0x75, 0x6f, 0x79, 0x2d, 0xd1,
51 0xdc, 0xe8, 0xca, 0x94, 0x44, 0x0e, 0xcb, 0x52, 0x79, 0xec,
52 0xd3, 0x18, 0x3a, 0x31, 0x1f, 0xc8, 0x96, 0xda, 0x1c, 0xb3,
53 0x93, 0x11, 0xaf, 0x37, 0xea, 0x4a, 0x75, 0xe2, 0x4b, 0xdb,
54 0xfd, 0x5c, 0x1d, 0xa0, 0xde, 0x7c, 0xec, 0xdf, 0x1a, 0x89,
55 0x6f, 0x9d, 0x8b, 0xc8, 0x16, 0xd9, 0x7c, 0xd7, 0xa2, 0xc4,
56 0x3b, 0xad, 0x54, 0x6f, 0xbe, 0x8c, 0xfe, 0xbc,
61 hashed := hash.Sum(nil)
63 encoded, err := emsaPSSEncode(hashed, 1023, salt, sha1.New())
65 t.Errorf("Error from emsaPSSEncode: %s\n", err)
67 if !bytes.Equal(encoded, expected) {
68 t.Errorf("Bad encoding. got %x, want %x", encoded, expected)
71 if err = emsaPSSVerify(hashed, encoded, 1023, len(salt), sha1.New()); err != nil {
72 t.Errorf("Bad verification: %s", err)
76 // TestPSSGolden tests all the test vectors in pss-vect.txt from
77 // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
78 func TestPSSGolden(t *testing.T) {
79 inFile, err := os.Open("testdata/pss-vect.txt.bz2")
81 t.Fatalf("Failed to open input file: %s", err)
85 // The pss-vect.txt file contains RSA keys and then a series of
86 // signatures. A goroutine is used to preprocess the input by merging
87 // lines, removing spaces in hex values and identifying the start of
88 // new keys and signature blocks.
89 const newKeyMarker = "START NEW KEY"
90 const newSignatureMarker = "START NEW SIGNATURE"
92 values := make(chan string)
96 scanner := bufio.NewScanner(bzip2.NewReader(inFile))
97 var partialValue string
101 line := scanner.Text()
104 if len(partialValue) > 0 {
105 values <- strings.ReplaceAll(partialValue, " ", "")
110 case strings.HasPrefix(line, "# ======") && lastWasValue:
111 values <- newKeyMarker
113 case strings.HasPrefix(line, "# ------") && lastWasValue:
114 values <- newSignatureMarker
116 case strings.HasPrefix(line, "#"):
122 if err := scanner.Err(); err != nil {
132 SaltLength: PSSSaltLengthEqualsHash,
135 for marker := range values {
143 key.N = bigFromHex(nHex)
144 key.E = intFromHex(<-values)
145 // We don't care for d, p, q, dP, dQ or qInv.
146 for i := 0; i < 6; i++ {
149 case newSignatureMarker:
150 msg := fromHex(<-values)
151 <-values // skip salt
152 sig := fromHex(<-values)
156 hashed = h.Sum(hashed[:0])
158 if err := VerifyPSS(key, hash, hashed, sig, opts); err != nil {
162 t.Fatalf("unknown marker: " + marker)
167 // TestPSSOpenSSL ensures that we can verify a PSS signature from OpenSSL with
168 // the default options. OpenSSL sets the salt length to be maximal.
169 func TestPSSOpenSSL(t *testing.T) {
170 hash := crypto.SHA256
172 h.Write([]byte("testing"))
175 // Generated with `echo -n testing | openssl dgst -sign key.pem -sigopt rsa_padding_mode:pss -sha256 > sig`
177 0x95, 0x59, 0x6f, 0xd3, 0x10, 0xa2, 0xe7, 0xa2, 0x92, 0x9d,
178 0x4a, 0x07, 0x2e, 0x2b, 0x27, 0xcc, 0x06, 0xc2, 0x87, 0x2c,
179 0x52, 0xf0, 0x4a, 0xcc, 0x05, 0x94, 0xf2, 0xc3, 0x2e, 0x20,
180 0xd7, 0x3e, 0x66, 0x62, 0xb5, 0x95, 0x2b, 0xa3, 0x93, 0x9a,
181 0x66, 0x64, 0x25, 0xe0, 0x74, 0x66, 0x8c, 0x3e, 0x92, 0xeb,
182 0xc6, 0xe6, 0xc0, 0x44, 0xf3, 0xb4, 0xb4, 0x2e, 0x8c, 0x66,
183 0x0a, 0x37, 0x9c, 0x69,
186 if err := VerifyPSS(&rsaPrivateKey.PublicKey, hash, hashed, sig, nil); err != nil {
191 func TestPSSNilOpts(t *testing.T) {
192 hash := crypto.SHA256
194 h.Write([]byte("testing"))
197 SignPSS(rand.Reader, rsaPrivateKey, hash, hashed, nil)
200 func TestPSSSigning(t *testing.T) {
201 var saltLengthCombinations = []struct {
202 signSaltLength, verifySaltLength int
205 {PSSSaltLengthAuto, PSSSaltLengthAuto, true},
206 {PSSSaltLengthEqualsHash, PSSSaltLengthAuto, true},
207 {PSSSaltLengthEqualsHash, PSSSaltLengthEqualsHash, true},
208 {PSSSaltLengthEqualsHash, 8, false},
209 {PSSSaltLengthAuto, PSSSaltLengthEqualsHash, false},
215 h.Write([]byte("testing"))
219 for i, test := range saltLengthCombinations {
220 opts.SaltLength = test.signSaltLength
221 sig, err := SignPSS(rand.Reader, rsaPrivateKey, hash, hashed, &opts)
223 t.Errorf("#%d: error while signing: %s", i, err)
227 opts.SaltLength = test.verifySaltLength
228 err = VerifyPSS(&rsaPrivateKey.PublicKey, hash, hashed, sig, &opts)
229 if (err == nil) != test.good {
230 t.Errorf("#%d: bad result, wanted: %t, got: %s", i, test.good, err)
235 func bigFromHex(hex string) *big.Int {
236 n, ok := new(big.Int).SetString(hex, 16)
238 panic("bad hex: " + hex)
243 func intFromHex(hex string) int {
244 i, err := strconv.ParseInt(hex, 16, 32)
251 func fromHex(hexStr string) []byte {
252 s, err := hex.DecodeString(hexStr)