libstdc++: Avoid -Wmaybe-uninitialized warnings in text_encoding.cc
[official-gcc.git] / libgo / go / crypto / rsa / pss_test.go
blobc3a6d468497cd44ef38023e3d97a4b2e6dbc38d1
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.
5 package rsa
7 import (
8 "bufio"
9 "bytes"
10 "compress/bzip2"
11 "crypto"
12 _ "crypto/md5"
13 "crypto/rand"
14 "crypto/sha1"
15 "crypto/sha256"
16 "encoding/hex"
17 "math/big"
18 "os"
19 "strconv"
20 "strings"
21 "testing"
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,
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,
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,
60 hash := sha1.New()
61 hash.Write(msg)
62 hashed := hash.Sum(nil)
64 encoded, err := emsaPSSEncode(hashed, 1023, salt, sha1.New())
65 if err != nil {
66 t.Errorf("Error from emsaPSSEncode: %s\n", err)
68 if !bytes.Equal(encoded, expected) {
69 t.Errorf("Bad encoding. got %x, want %x", encoded, expected)
72 if err = emsaPSSVerify(hashed, encoded, 1023, len(salt), sha1.New()); err != nil {
73 t.Errorf("Bad verification: %s", err)
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)
84 defer inFile.Close()
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"
93 values := make(chan string)
95 go func() {
96 defer close(values)
97 scanner := bufio.NewScanner(bzip2.NewReader(inFile))
98 var partialValue string
99 lastWasValue := true
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
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
123 if err := scanner.Err(); err != nil {
124 panic(err)
128 var key *PublicKey
129 var hashed []byte
130 hash := crypto.SHA1
131 h := hash.New()
132 opts := &PSSOptions{
133 SaltLength: PSSSaltLengthEqualsHash,
136 for marker := range values {
137 switch marker {
138 case newKeyMarker:
139 key = new(PublicKey)
140 nHex, ok := <-values
141 if !ok {
142 continue
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
150 case newSignatureMarker:
151 msg := fromHex(<-values)
152 <-values // skip salt
153 sig := fromHex(<-values)
155 h.Reset()
156 h.Write(msg)
157 hashed = h.Sum(hashed[:0])
159 if err := VerifyPSS(key, hash, hashed, sig, opts); err != nil {
160 t.Error(err)
162 default:
163 t.Fatalf("unknown marker: " + marker)
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)
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,
187 if err := VerifyPSS(&rsaPrivateKey.PublicKey, hash, hashed, sig, nil); err != nil {
188 t.Error(err)
192 func TestPSSNilOpts(t *testing.T) {
193 hash := crypto.SHA256
194 h := hash.New()
195 h.Write([]byte("testing"))
196 hashed := h.Sum(nil)
198 SignPSS(rand.Reader, rsaPrivateKey, hash, hashed, nil)
201 func TestPSSSigning(t *testing.T) {
202 var saltLengthCombinations = []struct {
203 signSaltLength, verifySaltLength int
204 good bool
206 {PSSSaltLengthAuto, PSSSaltLengthAuto, true},
207 {PSSSaltLengthEqualsHash, PSSSaltLengthAuto, true},
208 {PSSSaltLengthEqualsHash, PSSSaltLengthEqualsHash, true},
209 {PSSSaltLengthEqualsHash, 8, false},
210 {PSSSaltLengthAuto, PSSSaltLengthEqualsHash, false},
211 {8, 8, true},
214 hash := crypto.MD5
215 h := hash.New()
216 h.Write([]byte("testing"))
217 hashed := h.Sum(nil)
218 var opts PSSOptions
220 for i, test := range saltLengthCombinations {
221 opts.SaltLength = test.signSaltLength
222 sig, err := SignPSS(rand.Reader, rsaPrivateKey, hash, hashed, &opts)
223 if err != nil {
224 t.Errorf("#%d: error while signing: %s", i, err)
225 continue
228 opts.SaltLength = test.verifySaltLength
229 err = VerifyPSS(&rsaPrivateKey.PublicKey, hash, hashed, sig, &opts)
230 if (err == nil) != test.good {
231 t.Errorf("#%d: bad result, wanted: %t, got: %s", i, test.good, err)
236 func TestSignWithPSSSaltLengthAuto(t *testing.T) {
237 key, err := GenerateKey(rand.Reader, 513)
238 if err != nil {
239 t.Fatal(err)
241 digest := sha256.Sum256([]byte("message"))
242 signature, err := key.Sign(rand.Reader, digest[:], &PSSOptions{
243 SaltLength: PSSSaltLengthAuto,
244 Hash: crypto.SHA256,
246 if err != nil {
247 t.Fatal(err)
249 if len(signature) == 0 {
250 t.Fatal("empty signature returned")
254 func bigFromHex(hex string) *big.Int {
255 n, ok := new(big.Int).SetString(hex, 16)
256 if !ok {
257 panic("bad hex: " + hex)
259 return n
262 func intFromHex(hex string) int {
263 i, err := strconv.ParseInt(hex, 16, 32)
264 if err != nil {
265 panic(err)
267 return int(i)
270 func fromHex(hexStr string) []byte {
271 s, err := hex.DecodeString(hexStr)
272 if err != nil {
273 panic(err)
275 return s