Source file
src/crypto/rsa/pss_test.go
1
2
3
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
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
78
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
87
88
89
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
147 for i := 0; i < 6; i++ {
148 <-values
149 }
150 case newSignatureMarker:
151 msg := fromHex(<-values)
152 <-values
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: %s", marker)
164 }
165 }
166 }
167
168
169
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
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
241
242
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
293
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
302
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 }
309
View as plain text