github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/msp/cert_test.go (about)

     1  /*
     2  Copyright IBM Corp. 2017 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package msp
    18  
    19  import (
    20  	"crypto/ecdsa"
    21  	"crypto/elliptic"
    22  	"crypto/rand"
    23  	"crypto/x509"
    24  	"crypto/x509/pkix"
    25  	"encoding/asn1"
    26  	"math/big"
    27  	"net"
    28  	"testing"
    29  	"time"
    30  
    31  	"github.com/hyperledger/fabric/bccsp/sw"
    32  	"github.com/stretchr/testify/assert"
    33  )
    34  
    35  func TestSanitizeCertWithRSA(t *testing.T) {
    36  	cert := &x509.Certificate{}
    37  	cert.SignatureAlgorithm = x509.MD2WithRSA
    38  	result := isECDSASignedCert(cert)
    39  	assert.False(t, result)
    40  
    41  	cert.SignatureAlgorithm = x509.ECDSAWithSHA512
    42  	result = isECDSASignedCert(cert)
    43  	assert.True(t, result)
    44  }
    45  
    46  func TestSanitizeCertInvalidInput(t *testing.T) {
    47  	_, err := sanitizeECDSASignedCert(nil, nil)
    48  	assert.Error(t, err)
    49  	assert.Contains(t, err.Error(), "Certificate must be different from nil.")
    50  
    51  	_, err = sanitizeECDSASignedCert(&x509.Certificate{}, nil)
    52  	assert.Error(t, err)
    53  	assert.Contains(t, err.Error(), "Parent certificate must be different from nil")
    54  
    55  	k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
    56  	assert.NoError(t, err)
    57  	cert := &x509.Certificate{}
    58  	cert.PublicKey = &k.PublicKey
    59  	sigma, err := sw.MarshalECDSASignature(big.NewInt(1), elliptic.P256().Params().N)
    60  	assert.NoError(t, err)
    61  	cert.Signature = sigma
    62  	cert.PublicKeyAlgorithm = x509.ECDSA
    63  	cert.Raw = []byte{0, 1}
    64  	_, err = sanitizeECDSASignedCert(cert, cert)
    65  	assert.Error(t, err)
    66  	assert.Contains(t, err.Error(), "asn1: structure error: tags don't match")
    67  }
    68  
    69  func TestSanitizeCert(t *testing.T) {
    70  	var k *ecdsa.PrivateKey
    71  	var cert *x509.Certificate
    72  	for {
    73  		k, cert = generateSelfSignedCert(t, time.Now())
    74  
    75  		_, s, err := sw.UnmarshalECDSASignature(cert.Signature)
    76  		assert.NoError(t, err)
    77  
    78  		lowS, err := sw.IsLowS(&k.PublicKey, s)
    79  		assert.NoError(t, err)
    80  
    81  		if !lowS {
    82  			break
    83  		}
    84  	}
    85  
    86  	sanitizedCert, err := sanitizeECDSASignedCert(cert, cert)
    87  	assert.NoError(t, err)
    88  	assert.NotEqual(t, cert.Signature, sanitizedCert.Signature)
    89  
    90  	_, s, err := sw.UnmarshalECDSASignature(sanitizedCert.Signature)
    91  	assert.NoError(t, err)
    92  
    93  	lowS, err := sw.IsLowS(&k.PublicKey, s)
    94  	assert.NoError(t, err)
    95  	assert.True(t, lowS)
    96  }
    97  
    98  func TestCertExpiration(t *testing.T) {
    99  	msp := &bccspmsp{}
   100  	msp.opts = &x509.VerifyOptions{}
   101  	msp.opts.DNSName = "test.example.com"
   102  
   103  	// Certificate is in the future
   104  	_, cert := generateSelfSignedCert(t, time.Now().Add(24*time.Hour))
   105  	msp.opts.Roots = x509.NewCertPool()
   106  	msp.opts.Roots.AddCert(cert)
   107  	_, err := msp.getUniqueValidationChain(cert)
   108  	assert.NoError(t, err)
   109  
   110  	// Certificate is in the past
   111  	_, cert = generateSelfSignedCert(t, time.Now().Add(-24*time.Hour))
   112  	msp.opts.Roots = x509.NewCertPool()
   113  	msp.opts.Roots.AddCert(cert)
   114  	_, err = msp.getUniqueValidationChain(cert)
   115  	assert.NoError(t, err)
   116  
   117  	// Certificate is in the middle
   118  	_, cert = generateSelfSignedCert(t, time.Now())
   119  	msp.opts.Roots = x509.NewCertPool()
   120  	msp.opts.Roots.AddCert(cert)
   121  	_, err = msp.getUniqueValidationChain(cert)
   122  	assert.NoError(t, err)
   123  }
   124  
   125  func generateSelfSignedCert(t *testing.T, now time.Time) (*ecdsa.PrivateKey, *x509.Certificate) {
   126  	k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   127  	assert.NoError(t, err)
   128  
   129  	// Generate a self-signed certificate
   130  	testExtKeyUsage := []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}
   131  	testUnknownExtKeyUsage := []asn1.ObjectIdentifier{[]int{1, 2, 3}, []int{2, 59, 1}}
   132  	extraExtensionData := []byte("extra extension")
   133  	commonName := "test.example.com"
   134  	template := x509.Certificate{
   135  		SerialNumber: big.NewInt(1),
   136  		Subject: pkix.Name{
   137  			CommonName:   commonName,
   138  			Organization: []string{"Σ Acme Co"},
   139  			Country:      []string{"US"},
   140  			ExtraNames: []pkix.AttributeTypeAndValue{
   141  				{
   142  					Type:  []int{2, 5, 4, 42},
   143  					Value: "Gopher",
   144  				},
   145  				// This should override the Country, above.
   146  				{
   147  					Type:  []int{2, 5, 4, 6},
   148  					Value: "NL",
   149  				},
   150  			},
   151  		},
   152  		NotBefore:             now.Add(-1 * time.Hour),
   153  		NotAfter:              now.Add(1 * time.Hour),
   154  		SignatureAlgorithm:    x509.ECDSAWithSHA256,
   155  		SubjectKeyId:          []byte{1, 2, 3, 4},
   156  		KeyUsage:              x509.KeyUsageCertSign,
   157  		ExtKeyUsage:           testExtKeyUsage,
   158  		UnknownExtKeyUsage:    testUnknownExtKeyUsage,
   159  		BasicConstraintsValid: true,
   160  		IsCA:                  true,
   161  		OCSPServer:            []string{"http://ocurrentBCCSP.example.com"},
   162  		IssuingCertificateURL: []string{"http://crt.example.com/ca1.crt"},
   163  		DNSNames:              []string{"test.example.com"},
   164  		EmailAddresses:        []string{"gopher@golang.org"},
   165  		IPAddresses:           []net.IP{net.IPv4(127, 0, 0, 1).To4(), net.ParseIP("2001:4860:0:2001::68")},
   166  		PolicyIdentifiers:     []asn1.ObjectIdentifier{[]int{1, 2, 3}},
   167  		PermittedDNSDomains:   []string{".example.com", "example.com"},
   168  		CRLDistributionPoints: []string{"http://crl1.example.com/ca1.crl", "http://crl2.example.com/ca1.crl"},
   169  		ExtraExtensions: []pkix.Extension{
   170  			{
   171  				Id:    []int{1, 2, 3, 4},
   172  				Value: extraExtensionData,
   173  			},
   174  		},
   175  	}
   176  	certRaw, err := x509.CreateCertificate(rand.Reader, &template, &template, &k.PublicKey, k)
   177  	assert.NoError(t, err)
   178  
   179  	cert, err := x509.ParseCertificate(certRaw)
   180  	assert.NoError(t, err)
   181  
   182  	return k, cert
   183  }