155 lines
4.0 KiB
Go
155 lines
4.0 KiB
Go
/*
|
|
Copyright IBM Corp. All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
package csp_test
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"crypto/elliptic"
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/x509"
|
|
"encoding/asn1"
|
|
"encoding/pem"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"math/big"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/hyperledger/fabric/internal/cryptogen/csp"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestLoadPrivateKey(t *testing.T) {
|
|
testDir := t.TempDir()
|
|
priv, err := csp.GeneratePrivateKey(testDir)
|
|
if err != nil {
|
|
t.Fatalf("Failed to generate private key: %s", err)
|
|
}
|
|
pkFile := filepath.Join(testDir, "priv_sk")
|
|
require.Equal(t, true, checkForFile(pkFile),
|
|
"Expected to find private key file")
|
|
loadedPriv, err := csp.LoadPrivateKey(testDir)
|
|
require.NoError(t, err, "Failed to load private key")
|
|
require.NotNil(t, loadedPriv, "Should have returned an *ecdsa.PrivateKey")
|
|
require.Equal(t, priv, loadedPriv, "Expected private keys to match")
|
|
}
|
|
|
|
func TestLoadPrivateKey_BadPEM(t *testing.T) {
|
|
testDir := t.TempDir()
|
|
|
|
badPEMFile := filepath.Join(testDir, "badpem_sk")
|
|
|
|
rsaKey, err := rsa.GenerateKey(rand.Reader, 1024)
|
|
if err != nil {
|
|
t.Fatalf("Failed to generate RSA key: %s", err)
|
|
}
|
|
|
|
pkcs8Encoded, err := x509.MarshalPKCS8PrivateKey(rsaKey)
|
|
if err != nil {
|
|
t.Fatalf("Failed to PKCS8 encode RSA private key: %s", err)
|
|
}
|
|
pkcs8RSAPem := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: pkcs8Encoded})
|
|
|
|
pkcs1Encoded := x509.MarshalPKCS1PrivateKey(rsaKey)
|
|
if pkcs1Encoded == nil {
|
|
t.Fatalf("Failed to PKCS1 encode RSA private key: %s", err)
|
|
}
|
|
pkcs1RSAPem := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: pkcs1Encoded})
|
|
|
|
for _, test := range []struct {
|
|
name string
|
|
data []byte
|
|
errMsg string
|
|
}{
|
|
{
|
|
name: "not pem encoded",
|
|
data: []byte("wrong_encoding"),
|
|
errMsg: fmt.Sprintf("%s: bytes are not PEM encoded", badPEMFile),
|
|
},
|
|
{
|
|
name: "not EC key",
|
|
data: pkcs8RSAPem,
|
|
errMsg: fmt.Sprintf("%s: pem bytes do not contain an EC private key", badPEMFile),
|
|
},
|
|
{
|
|
name: "not PKCS8 encoded",
|
|
data: pkcs1RSAPem,
|
|
errMsg: fmt.Sprintf("%s: pem bytes are not PKCS8 encoded", badPEMFile),
|
|
},
|
|
} {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
err := ioutil.WriteFile(
|
|
badPEMFile,
|
|
test.data,
|
|
0o755,
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("failed to write to wrong encoding file: %s", err)
|
|
}
|
|
_, err = csp.LoadPrivateKey(badPEMFile)
|
|
require.Contains(t, err.Error(), test.errMsg)
|
|
os.Remove(badPEMFile)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGeneratePrivateKey(t *testing.T) {
|
|
testDir := t.TempDir()
|
|
|
|
expectedFile := filepath.Join(testDir, "priv_sk")
|
|
priv, err := csp.GeneratePrivateKey(testDir)
|
|
require.NoError(t, err, "Failed to generate private key")
|
|
require.NotNil(t, priv, "Should have returned an *ecdsa.Key")
|
|
require.Equal(t, true, checkForFile(expectedFile),
|
|
"Expected to find private key file")
|
|
|
|
_, err = csp.GeneratePrivateKey("notExist")
|
|
require.Contains(t, err.Error(), "no such file or directory")
|
|
}
|
|
|
|
func TestECDSASigner(t *testing.T) {
|
|
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
if err != nil {
|
|
t.Fatalf("Failed to generate private key: %s", err)
|
|
}
|
|
|
|
signer := csp.ECDSASigner{
|
|
PrivateKey: priv,
|
|
}
|
|
require.Equal(t, priv.Public(), signer.Public().(*ecdsa.PublicKey))
|
|
digest := []byte{1}
|
|
sig, err := signer.Sign(rand.Reader, digest, nil)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create signature: %s", err)
|
|
}
|
|
|
|
// unmarshal signature
|
|
ecdsaSig := &csp.ECDSASignature{}
|
|
_, err = asn1.Unmarshal(sig, ecdsaSig)
|
|
if err != nil {
|
|
t.Fatalf("Failed to unmarshal signature: %s", err)
|
|
}
|
|
// s should not be greater than half order of curve
|
|
halfOrder := new(big.Int).Div(priv.PublicKey.Curve.Params().N, big.NewInt(2))
|
|
|
|
if ecdsaSig.S.Cmp(halfOrder) == 1 {
|
|
t.Error("Expected signature with Low S")
|
|
}
|
|
|
|
// ensure signature is valid by using standard verify function
|
|
ok := ecdsa.Verify(&priv.PublicKey, digest, ecdsaSig.R, ecdsaSig.S)
|
|
require.True(t, ok, "Expected valid signature")
|
|
}
|
|
|
|
func checkForFile(file string) bool {
|
|
if _, err := os.Stat(file); os.IsNotExist(err) {
|
|
return false
|
|
}
|
|
return true
|
|
}
|