github.com/kaituanwang/hyperledger@v2.0.1+incompatible/internal/cryptogen/ca/ca_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  package ca_test
     7  
     8  import (
     9  	"crypto/ecdsa"
    10  	"crypto/x509"
    11  	"io/ioutil"
    12  	"net"
    13  	"os"
    14  	"path/filepath"
    15  	"testing"
    16  
    17  	"github.com/hyperledger/fabric/internal/cryptogen/ca"
    18  	"github.com/hyperledger/fabric/internal/cryptogen/csp"
    19  	"github.com/stretchr/testify/assert"
    20  	"github.com/stretchr/testify/require"
    21  )
    22  
    23  const (
    24  	testCAName             = "root0"
    25  	testCA2Name            = "root1"
    26  	testCA3Name            = "root2"
    27  	testName               = "cert0"
    28  	testName2              = "cert1"
    29  	testName3              = "cert2"
    30  	testIP                 = "172.16.10.31"
    31  	testCountry            = "US"
    32  	testProvince           = "California"
    33  	testLocality           = "San Francisco"
    34  	testOrganizationalUnit = "Hyperledger Fabric"
    35  	testStreetAddress      = "testStreetAddress"
    36  	testPostalCode         = "123456"
    37  )
    38  
    39  func TestLoadCertificateECDSA(t *testing.T) {
    40  	testDir, err := ioutil.TempDir("", "ca-test")
    41  	if err != nil {
    42  		t.Fatalf("Failed to create test directory: %s", err)
    43  	}
    44  	defer os.RemoveAll(testDir)
    45  
    46  	// generate private key
    47  	certDir, err := ioutil.TempDir(testDir, "certs")
    48  	if err != nil {
    49  		t.Fatalf("Failed to create certs directory: %s", err)
    50  	}
    51  	priv, err := csp.GeneratePrivateKey(certDir)
    52  	assert.NoError(t, err, "Failed to generate signed certificate")
    53  
    54  	// create our CA
    55  	caDir := filepath.Join(testDir, "ca")
    56  	rootCA, err := ca.NewCA(
    57  		caDir,
    58  		testCA3Name,
    59  		testCA3Name,
    60  		testCountry,
    61  		testProvince,
    62  		testLocality,
    63  		testOrganizationalUnit,
    64  		testStreetAddress,
    65  		testPostalCode,
    66  	)
    67  	assert.NoError(t, err, "Error generating CA")
    68  
    69  	cert, err := rootCA.SignCertificate(
    70  		certDir,
    71  		testName3,
    72  		nil,
    73  		nil,
    74  		&priv.PublicKey,
    75  		x509.KeyUsageDigitalSignature|x509.KeyUsageKeyEncipherment,
    76  		[]x509.ExtKeyUsage{x509.ExtKeyUsageAny},
    77  	)
    78  	assert.NoError(t, err, "Failed to generate signed certificate")
    79  	// KeyUsage should be x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment
    80  	assert.Equal(t, x509.KeyUsageDigitalSignature|x509.KeyUsageKeyEncipherment,
    81  		cert.KeyUsage)
    82  	assert.Contains(t, cert.ExtKeyUsage, x509.ExtKeyUsageAny)
    83  
    84  	loadedCert, err := ca.LoadCertificateECDSA(certDir)
    85  	assert.NoError(t, err)
    86  	assert.NotNil(t, loadedCert, "Should load cert")
    87  	assert.Equal(t, cert.SerialNumber, loadedCert.SerialNumber, "Should have same serial number")
    88  	assert.Equal(t, cert.Subject.CommonName, loadedCert.Subject.CommonName, "Should have same CN")
    89  }
    90  
    91  func TestLoadCertificateECDSA_wrongEncoding(t *testing.T) {
    92  	testDir, err := ioutil.TempDir("", "wrongEncoding")
    93  	require.NoError(t, err, "failed to create test directory")
    94  	defer os.RemoveAll(testDir)
    95  
    96  	filename := filepath.Join(testDir, "wrong_encoding.pem")
    97  	err = ioutil.WriteFile(filename, []byte("wrong_encoding"), 0644) // Wrong encoded cert
    98  	require.NoErrorf(t, err, "failed to create file %s", filename)
    99  
   100  	_, err = ca.LoadCertificateECDSA(testDir)
   101  	assert.NotNil(t, err)
   102  	assert.EqualError(t, err, filename+": wrong PEM encoding")
   103  }
   104  
   105  func TestLoadCertificateECDSA_empty_DER_cert(t *testing.T) {
   106  	testDir, err := ioutil.TempDir("", "ca-test")
   107  	require.NoError(t, err, "failed to create test directory")
   108  	defer os.RemoveAll(testDir)
   109  
   110  	filename := filepath.Join(testDir, "empty.pem")
   111  	empty_cert := "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"
   112  	err = ioutil.WriteFile(filename, []byte(empty_cert), 0644)
   113  	require.NoErrorf(t, err, "failed to create file %s", filename)
   114  
   115  	cert, err := ca.LoadCertificateECDSA(testDir)
   116  	assert.Nil(t, cert)
   117  	assert.NotNil(t, err)
   118  	assert.EqualError(t, err, filename+": wrong DER encoding")
   119  }
   120  
   121  func TestNewCA(t *testing.T) {
   122  	testDir, err := ioutil.TempDir("", "ca-test")
   123  	if err != nil {
   124  		t.Fatalf("Failed to create test directory: %s", err)
   125  	}
   126  	defer os.RemoveAll(testDir)
   127  
   128  	caDir := filepath.Join(testDir, "ca")
   129  	rootCA, err := ca.NewCA(
   130  		caDir,
   131  		testCAName,
   132  		testCAName,
   133  		testCountry,
   134  		testProvince,
   135  		testLocality,
   136  		testOrganizationalUnit,
   137  		testStreetAddress,
   138  		testPostalCode,
   139  	)
   140  	assert.NoError(t, err, "Error generating CA")
   141  	assert.NotNil(t, rootCA, "Failed to return CA")
   142  	assert.NotNil(t, rootCA.Signer,
   143  		"rootCA.Signer should not be empty")
   144  	assert.IsType(t, &x509.Certificate{}, rootCA.SignCert,
   145  		"rootCA.SignCert should be type x509.Certificate")
   146  
   147  	// check to make sure the root public key was stored
   148  	pemFile := filepath.Join(caDir, testCAName+"-cert.pem")
   149  	assert.Equal(t, true, checkForFile(pemFile),
   150  		"Expected to find file "+pemFile)
   151  
   152  	assert.NotEmpty(t, rootCA.SignCert.Subject.Country, "country cannot be empty.")
   153  	assert.Equal(t, testCountry, rootCA.SignCert.Subject.Country[0], "Failed to match country")
   154  	assert.NotEmpty(t, rootCA.SignCert.Subject.Province, "province cannot be empty.")
   155  	assert.Equal(t, testProvince, rootCA.SignCert.Subject.Province[0], "Failed to match province")
   156  	assert.NotEmpty(t, rootCA.SignCert.Subject.Locality, "locality cannot be empty.")
   157  	assert.Equal(t, testLocality, rootCA.SignCert.Subject.Locality[0], "Failed to match locality")
   158  	assert.NotEmpty(t, rootCA.SignCert.Subject.OrganizationalUnit, "organizationalUnit cannot be empty.")
   159  	assert.Equal(t, testOrganizationalUnit, rootCA.SignCert.Subject.OrganizationalUnit[0], "Failed to match organizationalUnit")
   160  	assert.NotEmpty(t, rootCA.SignCert.Subject.StreetAddress, "streetAddress cannot be empty.")
   161  	assert.Equal(t, testStreetAddress, rootCA.SignCert.Subject.StreetAddress[0], "Failed to match streetAddress")
   162  	assert.NotEmpty(t, rootCA.SignCert.Subject.PostalCode, "postalCode cannot be empty.")
   163  	assert.Equal(t, testPostalCode, rootCA.SignCert.Subject.PostalCode[0], "Failed to match postalCode")
   164  }
   165  
   166  func TestGenerateSignCertificate(t *testing.T) {
   167  	testDir, err := ioutil.TempDir("", "ca-test")
   168  	if err != nil {
   169  		t.Fatalf("Failed to create test directory: %s", err)
   170  	}
   171  	defer os.RemoveAll(testDir)
   172  
   173  	// generate private key
   174  	certDir, err := ioutil.TempDir(testDir, "certs")
   175  	if err != nil {
   176  		t.Fatalf("Failed to create certs directory: %s", err)
   177  	}
   178  	priv, err := csp.GeneratePrivateKey(certDir)
   179  	assert.NoError(t, err, "Failed to generate signed certificate")
   180  
   181  	// create our CA
   182  	caDir := filepath.Join(testDir, "ca")
   183  	rootCA, err := ca.NewCA(
   184  		caDir,
   185  		testCA2Name,
   186  		testCA2Name,
   187  		testCountry,
   188  		testProvince,
   189  		testLocality,
   190  		testOrganizationalUnit,
   191  		testStreetAddress,
   192  		testPostalCode,
   193  	)
   194  	assert.NoError(t, err, "Error generating CA")
   195  
   196  	cert, err := rootCA.SignCertificate(
   197  		certDir,
   198  		testName,
   199  		nil,
   200  		nil,
   201  		&priv.PublicKey,
   202  		x509.KeyUsageDigitalSignature|x509.KeyUsageKeyEncipherment,
   203  		[]x509.ExtKeyUsage{x509.ExtKeyUsageAny},
   204  	)
   205  	assert.NoError(t, err, "Failed to generate signed certificate")
   206  	// KeyUsage should be x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment
   207  	assert.Equal(t, x509.KeyUsageDigitalSignature|x509.KeyUsageKeyEncipherment,
   208  		cert.KeyUsage)
   209  	assert.Contains(t, cert.ExtKeyUsage, x509.ExtKeyUsageAny)
   210  
   211  	cert, err = rootCA.SignCertificate(
   212  		certDir,
   213  		testName,
   214  		nil,
   215  		nil,
   216  		&priv.PublicKey,
   217  		x509.KeyUsageDigitalSignature,
   218  		[]x509.ExtKeyUsage{},
   219  	)
   220  	assert.NoError(t, err, "Failed to generate signed certificate")
   221  	assert.Equal(t, 0, len(cert.ExtKeyUsage))
   222  
   223  	// make sure ous are correctly set
   224  	ous := []string{"TestOU", "PeerOU"}
   225  	cert, err = rootCA.SignCertificate(certDir, testName, ous, nil, &priv.PublicKey,
   226  		x509.KeyUsageDigitalSignature, []x509.ExtKeyUsage{})
   227  	assert.Contains(t, cert.Subject.OrganizationalUnit, ous[0])
   228  	assert.Contains(t, cert.Subject.OrganizationalUnit, ous[1])
   229  
   230  	// make sure sans are correctly set
   231  	sans := []string{testName2, testIP}
   232  	cert, err = rootCA.SignCertificate(certDir, testName, nil, sans, &priv.PublicKey,
   233  		x509.KeyUsageDigitalSignature, []x509.ExtKeyUsage{})
   234  	assert.Contains(t, cert.DNSNames, testName2)
   235  	assert.Contains(t, cert.IPAddresses, net.ParseIP(testIP).To4())
   236  
   237  	// check to make sure the signed public key was stored
   238  	pemFile := filepath.Join(certDir, testName+"-cert.pem")
   239  	assert.Equal(t, true, checkForFile(pemFile),
   240  		"Expected to find file "+pemFile)
   241  
   242  	_, err = rootCA.SignCertificate(certDir, "empty/CA", nil, nil, &priv.PublicKey,
   243  		x509.KeyUsageKeyEncipherment, []x509.ExtKeyUsage{x509.ExtKeyUsageAny})
   244  	assert.Error(t, err, "Bad name should fail")
   245  
   246  	// use an empty CA to test error path
   247  	badCA := &ca.CA{
   248  		Name:     "badCA",
   249  		SignCert: &x509.Certificate{},
   250  	}
   251  	_, err = badCA.SignCertificate(certDir, testName, nil, nil, &ecdsa.PublicKey{},
   252  		x509.KeyUsageKeyEncipherment, []x509.ExtKeyUsage{x509.ExtKeyUsageAny})
   253  	assert.Error(t, err, "Empty CA should not be able to sign")
   254  
   255  }
   256  
   257  func checkForFile(file string) bool {
   258  	if _, err := os.Stat(file); os.IsNotExist(err) {
   259  		return false
   260  	}
   261  	return true
   262  }