github.com/defanghe/fabric@v2.1.1+incompatible/internal/cryptogen/csp/csp_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  package csp_test
     7  
     8  import (
     9  	"crypto/ecdsa"
    10  	"crypto/elliptic"
    11  	"crypto/rand"
    12  	"crypto/rsa"
    13  	"crypto/x509"
    14  	"encoding/asn1"
    15  	"encoding/pem"
    16  	"fmt"
    17  	"io/ioutil"
    18  	"math/big"
    19  	"os"
    20  	"path/filepath"
    21  	"testing"
    22  
    23  	"github.com/hyperledger/fabric/internal/cryptogen/csp"
    24  	"github.com/stretchr/testify/assert"
    25  )
    26  
    27  func TestLoadPrivateKey(t *testing.T) {
    28  	testDir, err := ioutil.TempDir("", "csp-test")
    29  	if err != nil {
    30  		t.Fatalf("Failed to create test directory: %s", err)
    31  	}
    32  	defer os.RemoveAll(testDir)
    33  	priv, err := csp.GeneratePrivateKey(testDir)
    34  	if err != nil {
    35  		t.Fatalf("Failed to generate private key: %s", err)
    36  	}
    37  	pkFile := filepath.Join(testDir, "priv_sk")
    38  	assert.Equal(t, true, checkForFile(pkFile),
    39  		"Expected to find private key file")
    40  	loadedPriv, err := csp.LoadPrivateKey(testDir)
    41  	assert.NoError(t, err, "Failed to load private key")
    42  	assert.NotNil(t, loadedPriv, "Should have returned an *ecdsa.PrivateKey")
    43  	assert.Equal(t, priv, loadedPriv, "Expected private keys to match")
    44  }
    45  
    46  func TestLoadPrivateKey_BadPEM(t *testing.T) {
    47  	testDir, err := ioutil.TempDir("", "csp-test")
    48  	if err != nil {
    49  		t.Fatalf("Failed to create test directory: %s", err)
    50  	}
    51  	defer os.RemoveAll(testDir)
    52  
    53  	badPEMFile := filepath.Join(testDir, "badpem_sk")
    54  
    55  	rsaKey, err := rsa.GenerateKey(rand.Reader, 1024)
    56  	if err != nil {
    57  		t.Fatalf("Failed to generate RSA key: %s", err)
    58  	}
    59  
    60  	pkcs8Encoded, err := x509.MarshalPKCS8PrivateKey(rsaKey)
    61  	if err != nil {
    62  		t.Fatalf("Failed to PKCS8 encode RSA private key: %s", err)
    63  	}
    64  	pkcs8RSAPem := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: pkcs8Encoded})
    65  
    66  	pkcs1Encoded := x509.MarshalPKCS1PrivateKey(rsaKey)
    67  	if pkcs1Encoded == nil {
    68  		t.Fatalf("Failed to PKCS1 encode RSA private key: %s", err)
    69  	}
    70  	pkcs1RSAPem := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: pkcs1Encoded})
    71  
    72  	for _, test := range []struct {
    73  		name   string
    74  		data   []byte
    75  		errMsg string
    76  	}{
    77  		{
    78  			name:   "not pem encoded",
    79  			data:   []byte("wrong_encoding"),
    80  			errMsg: fmt.Sprintf("%s: bytes are not PEM encoded", badPEMFile),
    81  		},
    82  		{
    83  			name:   "not EC key",
    84  			data:   pkcs8RSAPem,
    85  			errMsg: fmt.Sprintf("%s: pem bytes do not contain an EC private key", badPEMFile),
    86  		},
    87  		{
    88  			name:   "not PKCS8 encoded",
    89  			data:   pkcs1RSAPem,
    90  			errMsg: fmt.Sprintf("%s: pem bytes are not PKCS8 encoded", badPEMFile),
    91  		},
    92  	} {
    93  		t.Run(test.name, func(t *testing.T) {
    94  			err := ioutil.WriteFile(
    95  				badPEMFile,
    96  				test.data,
    97  				0755,
    98  			)
    99  			if err != nil {
   100  				t.Fatalf("failed to write to wrong encoding file: %s", err)
   101  			}
   102  			_, err = csp.LoadPrivateKey(badPEMFile)
   103  			assert.Contains(t, err.Error(), test.errMsg)
   104  			os.Remove(badPEMFile)
   105  		})
   106  	}
   107  }
   108  
   109  func TestGeneratePrivateKey(t *testing.T) {
   110  	testDir, err := ioutil.TempDir("", "csp-test")
   111  	if err != nil {
   112  		t.Fatalf("Failed to create test directory: %s", err)
   113  	}
   114  	defer os.RemoveAll(testDir)
   115  
   116  	expectedFile := filepath.Join(testDir, "priv_sk")
   117  	priv, err := csp.GeneratePrivateKey(testDir)
   118  	assert.NoError(t, err, "Failed to generate private key")
   119  	assert.NotNil(t, priv, "Should have returned an *ecdsa.Key")
   120  	assert.Equal(t, true, checkForFile(expectedFile),
   121  		"Expected to find private key file")
   122  
   123  	priv, err = csp.GeneratePrivateKey("notExist")
   124  	assert.Contains(t, err.Error(), "no such file or directory")
   125  }
   126  
   127  func TestECDSASigner(t *testing.T) {
   128  	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   129  	if err != nil {
   130  		t.Fatalf("Failed to generate private key: %s", err)
   131  	}
   132  
   133  	signer := csp.ECDSASigner{
   134  		PrivateKey: priv,
   135  	}
   136  	assert.Equal(t, priv.Public(), signer.Public().(*ecdsa.PublicKey))
   137  	digest := []byte{1}
   138  	sig, err := signer.Sign(rand.Reader, digest, nil)
   139  	if err != nil {
   140  		t.Fatalf("Failed to create signature: %s", err)
   141  	}
   142  
   143  	// unmarshal signature
   144  	ecdsaSig := &csp.ECDSASignature{}
   145  	_, err = asn1.Unmarshal(sig, ecdsaSig)
   146  	if err != nil {
   147  		t.Fatalf("Failed to unmarshal signature: %s", err)
   148  	}
   149  	// s should not be greater than half order of curve
   150  	halfOrder := new(big.Int).Div(priv.PublicKey.Curve.Params().N, big.NewInt(2))
   151  
   152  	if ecdsaSig.S.Cmp(halfOrder) == 1 {
   153  		t.Error("Expected signature with Low S")
   154  	}
   155  
   156  	// ensure signature is valid by using standard verify function
   157  	ok := ecdsa.Verify(&priv.PublicKey, digest, ecdsaSig.R, ecdsaSig.S)
   158  	assert.True(t, ok, "Expected valid signature")
   159  }
   160  
   161  func checkForFile(file string) bool {
   162  	if _, err := os.Stat(file); os.IsNotExist(err) {
   163  		return false
   164  	}
   165  	return true
   166  }