...

Source file src/crypto/rsa/pss_test.go

Documentation: crypto/rsa

		 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  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"
		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  	}
	 213  
	 214  	hash := crypto.MD5
	 215  	h := hash.New()
	 216  	h.Write([]byte("testing"))
	 217  	hashed := h.Sum(nil)
	 218  	var opts PSSOptions
	 219  
	 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
	 226  		}
	 227  
	 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)
	 232  		}
	 233  	}
	 234  }
	 235  
	 236  func TestSignWithPSSSaltLengthAuto(t *testing.T) {
	 237  	key, err := GenerateKey(rand.Reader, 513)
	 238  	if err != nil {
	 239  		t.Fatal(err)
	 240  	}
	 241  	digest := sha256.Sum256([]byte("message"))
	 242  	signature, err := key.Sign(rand.Reader, digest[:], &PSSOptions{
	 243  		SaltLength: PSSSaltLengthAuto,
	 244  		Hash:			 crypto.SHA256,
	 245  	})
	 246  	if err != nil {
	 247  		t.Fatal(err)
	 248  	}
	 249  	if len(signature) == 0 {
	 250  		t.Fatal("empty signature returned")
	 251  	}
	 252  }
	 253  
	 254  func bigFromHex(hex string) *big.Int {
	 255  	n, ok := new(big.Int).SetString(hex, 16)
	 256  	if !ok {
	 257  		panic("bad hex: " + hex)
	 258  	}
	 259  	return n
	 260  }
	 261  
	 262  func intFromHex(hex string) int {
	 263  	i, err := strconv.ParseInt(hex, 16, 32)
	 264  	if err != nil {
	 265  		panic(err)
	 266  	}
	 267  	return int(i)
	 268  }
	 269  
	 270  func fromHex(hexStr string) []byte {
	 271  	s, err := hex.DecodeString(hexStr)
	 272  	if err != nil {
	 273  		panic(err)
	 274  	}
	 275  	return s
	 276  }
	 277  

View as plain text