github.com/yanyiwu/go@v0.0.0-20150106053140-03d6637dbb7f/src/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
     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.Replace(partialValue, " ", "", -1)
   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 TestPSSSigning(t *testing.T) {
   193  	var saltLengthCombinations = []struct {
   194  		signSaltLength, verifySaltLength int
   195  		good                             bool
   196  	}{
   197  		{PSSSaltLengthAuto, PSSSaltLengthAuto, true},
   198  		{PSSSaltLengthEqualsHash, PSSSaltLengthAuto, true},
   199  		{PSSSaltLengthEqualsHash, PSSSaltLengthEqualsHash, true},
   200  		{PSSSaltLengthEqualsHash, 8, false},
   201  		{PSSSaltLengthAuto, PSSSaltLengthEqualsHash, false},
   202  		{8, 8, true},
   203  	}
   204  
   205  	hash := crypto.MD5
   206  	h := hash.New()
   207  	h.Write([]byte("testing"))
   208  	hashed := h.Sum(nil)
   209  	var opts PSSOptions
   210  
   211  	for i, test := range saltLengthCombinations {
   212  		opts.SaltLength = test.signSaltLength
   213  		sig, err := SignPSS(rand.Reader, rsaPrivateKey, hash, hashed, &opts)
   214  		if err != nil {
   215  			t.Errorf("#%d: error while signing: %s", i, err)
   216  			continue
   217  		}
   218  
   219  		opts.SaltLength = test.verifySaltLength
   220  		err = VerifyPSS(&rsaPrivateKey.PublicKey, hash, hashed, sig, &opts)
   221  		if (err == nil) != test.good {
   222  			t.Errorf("#%d: bad result, wanted: %t, got: %s", i, test.good, err)
   223  		}
   224  	}
   225  }
   226  
   227  func bigFromHex(hex string) *big.Int {
   228  	n, ok := new(big.Int).SetString(hex, 16)
   229  	if !ok {
   230  		panic("bad hex: " + hex)
   231  	}
   232  	return n
   233  }
   234  
   235  func intFromHex(hex string) int {
   236  	i, err := strconv.ParseInt(hex, 16, 32)
   237  	if err != nil {
   238  		panic(err)
   239  	}
   240  	return int(i)
   241  }
   242  
   243  func fromHex(hexStr string) []byte {
   244  	s, err := hex.DecodeString(hexStr)
   245  	if err != nil {
   246  		panic(err)
   247  	}
   248  	return s
   249  }