github.com/hyperledger-labs/bdls@v2.1.1+incompatible/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/hyperledger/fabric/bccsp/utils"
    33  	"github.com/stretchr/testify/assert"
    34  )
    35  
    36  func TestSanitizeCertWithRSA(t *testing.T) {
    37  	cert := &x509.Certificate{}
    38  	cert.SignatureAlgorithm = x509.MD2WithRSA
    39  	result := isECDSASignedCert(cert)
    40  	assert.False(t, result)
    41  
    42  	cert.SignatureAlgorithm = x509.ECDSAWithSHA512
    43  	result = isECDSASignedCert(cert)
    44  	assert.True(t, result)
    45  }
    46  
    47  func TestSanitizeCertInvalidInput(t *testing.T) {
    48  	_, err := sanitizeECDSASignedCert(nil, nil)
    49  	assert.Error(t, err)
    50  	assert.Contains(t, err.Error(), "certificate must be different from nil")
    51  
    52  	_, err = sanitizeECDSASignedCert(&x509.Certificate{}, nil)
    53  	assert.Error(t, err)
    54  	assert.Contains(t, err.Error(), "parent certificate must be different from nil")
    55  
    56  	k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
    57  	assert.NoError(t, err)
    58  	cert := &x509.Certificate{}
    59  	cert.PublicKey = &k.PublicKey
    60  	sigma, err := utils.MarshalECDSASignature(big.NewInt(1), elliptic.P256().Params().N)
    61  	assert.NoError(t, err)
    62  	cert.Signature = sigma
    63  	cert.PublicKeyAlgorithm = x509.ECDSA
    64  	cert.Raw = []byte{0, 1}
    65  	_, err = sanitizeECDSASignedCert(cert, cert)
    66  	assert.Error(t, err)
    67  	assert.Contains(t, err.Error(), "asn1: structure error: tags don't match")
    68  }
    69  
    70  func TestSanitizeCert(t *testing.T) {
    71  	var k *ecdsa.PrivateKey
    72  	var cert *x509.Certificate
    73  	for {
    74  		k, cert = generateSelfSignedCert(t, time.Now())
    75  
    76  		_, s, err := utils.UnmarshalECDSASignature(cert.Signature)
    77  		assert.NoError(t, err)
    78  
    79  		lowS, err := utils.IsLowS(&k.PublicKey, s)
    80  		assert.NoError(t, err)
    81  
    82  		if !lowS {
    83  			break
    84  		}
    85  	}
    86  
    87  	sanitizedCert, err := sanitizeECDSASignedCert(cert, cert)
    88  	assert.NoError(t, err)
    89  	assert.NotEqual(t, cert.Signature, sanitizedCert.Signature)
    90  
    91  	_, s, err := utils.UnmarshalECDSASignature(sanitizedCert.Signature)
    92  	assert.NoError(t, err)
    93  
    94  	lowS, err := utils.IsLowS(&k.PublicKey, s)
    95  	assert.NoError(t, err)
    96  	assert.True(t, lowS)
    97  }
    98  
    99  func TestCertExpiration(t *testing.T) {
   100  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
   101  	assert.NoError(t, err)
   102  	msp := &bccspmsp{bccsp: cryptoProvider}
   103  	msp.opts = &x509.VerifyOptions{}
   104  	msp.opts.DNSName = "test.example.com"
   105  
   106  	// Certificate is in the future
   107  	_, cert := generateSelfSignedCert(t, time.Now().Add(24*time.Hour))
   108  	msp.opts.Roots = x509.NewCertPool()
   109  	msp.opts.Roots.AddCert(cert)
   110  	_, err = msp.getUniqueValidationChain(cert, msp.getValidityOptsForCert(cert))
   111  	assert.NoError(t, err)
   112  
   113  	// Certificate is in the past
   114  	_, cert = generateSelfSignedCert(t, time.Now().Add(-24*time.Hour))
   115  	msp.opts.Roots = x509.NewCertPool()
   116  	msp.opts.Roots.AddCert(cert)
   117  	_, err = msp.getUniqueValidationChain(cert, msp.getValidityOptsForCert(cert))
   118  	assert.NoError(t, err)
   119  
   120  	// Certificate is in the middle
   121  	_, cert = generateSelfSignedCert(t, time.Now())
   122  	msp.opts.Roots = x509.NewCertPool()
   123  	msp.opts.Roots.AddCert(cert)
   124  	_, err = msp.getUniqueValidationChain(cert, msp.getValidityOptsForCert(cert))
   125  	assert.NoError(t, err)
   126  }
   127  
   128  func generateSelfSignedCert(t *testing.T, now time.Time) (*ecdsa.PrivateKey, *x509.Certificate) {
   129  	k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   130  	assert.NoError(t, err)
   131  
   132  	// Generate a self-signed certificate
   133  	testExtKeyUsage := []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}
   134  	testUnknownExtKeyUsage := []asn1.ObjectIdentifier{[]int{1, 2, 3}, []int{2, 59, 1}}
   135  	extraExtensionData := []byte("extra extension")
   136  	commonName := "test.example.com"
   137  	template := x509.Certificate{
   138  		SerialNumber: big.NewInt(1),
   139  		Subject: pkix.Name{
   140  			CommonName:   commonName,
   141  			Organization: []string{"Σ Acme Co"},
   142  			Country:      []string{"US"},
   143  			ExtraNames: []pkix.AttributeTypeAndValue{
   144  				{
   145  					Type:  []int{2, 5, 4, 42},
   146  					Value: "Gopher",
   147  				},
   148  				// This should override the Country, above.
   149  				{
   150  					Type:  []int{2, 5, 4, 6},
   151  					Value: "NL",
   152  				},
   153  			},
   154  		},
   155  		NotBefore:             now.Add(-1 * time.Hour),
   156  		NotAfter:              now.Add(1 * time.Hour),
   157  		SignatureAlgorithm:    x509.ECDSAWithSHA256,
   158  		SubjectKeyId:          []byte{1, 2, 3, 4},
   159  		KeyUsage:              x509.KeyUsageCertSign,
   160  		ExtKeyUsage:           testExtKeyUsage,
   161  		UnknownExtKeyUsage:    testUnknownExtKeyUsage,
   162  		BasicConstraintsValid: true,
   163  		IsCA:                  true,
   164  		OCSPServer:            []string{"http://ocurrentBCCSP.example.com"},
   165  		IssuingCertificateURL: []string{"http://crt.example.com/ca1.crt"},
   166  		DNSNames:              []string{"test.example.com"},
   167  		EmailAddresses:        []string{"gopher@golang.org"},
   168  		IPAddresses:           []net.IP{net.IPv4(127, 0, 0, 1).To4(), net.ParseIP("2001:4860:0:2001::68")},
   169  		PolicyIdentifiers:     []asn1.ObjectIdentifier{[]int{1, 2, 3}},
   170  		PermittedDNSDomains:   []string{".example.com", "example.com"},
   171  		CRLDistributionPoints: []string{"http://crl1.example.com/ca1.crl", "http://crl2.example.com/ca1.crl"},
   172  		ExtraExtensions: []pkix.Extension{
   173  			{
   174  				Id:    []int{1, 2, 3, 4},
   175  				Value: extraExtensionData,
   176  			},
   177  		},
   178  	}
   179  	certRaw, err := x509.CreateCertificate(rand.Reader, &template, &template, &k.PublicKey, k)
   180  	assert.NoError(t, err)
   181  
   182  	cert, err := x509.ParseCertificate(certRaw)
   183  	assert.NoError(t, err)
   184  
   185  	return k, cert
   186  }