371 lines
9.5 KiB
Go
371 lines
9.5 KiB
Go
/*
|
|
Copyright IBM Corp. All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package sw
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"crypto/elliptic"
|
|
"crypto/rand"
|
|
"crypto/x509"
|
|
"encoding/asn1"
|
|
"encoding/pem"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestOidFromNamedCurve(t *testing.T) {
|
|
var (
|
|
oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33}
|
|
oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7}
|
|
oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34}
|
|
oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35}
|
|
)
|
|
|
|
type result struct {
|
|
oid asn1.ObjectIdentifier
|
|
ok bool
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
curve elliptic.Curve
|
|
expected result
|
|
}{
|
|
{
|
|
name: "P224",
|
|
curve: elliptic.P224(),
|
|
expected: result{
|
|
oid: oidNamedCurveP224,
|
|
ok: true,
|
|
},
|
|
},
|
|
{
|
|
name: "P256",
|
|
curve: elliptic.P256(),
|
|
expected: result{
|
|
oid: oidNamedCurveP256,
|
|
ok: true,
|
|
},
|
|
},
|
|
{
|
|
name: "P384",
|
|
curve: elliptic.P384(),
|
|
expected: result{
|
|
oid: oidNamedCurveP384,
|
|
ok: true,
|
|
},
|
|
},
|
|
{
|
|
name: "P521",
|
|
curve: elliptic.P521(),
|
|
expected: result{
|
|
oid: oidNamedCurveP521,
|
|
ok: true,
|
|
},
|
|
},
|
|
{
|
|
name: "T-1000",
|
|
curve: &elliptic.CurveParams{Name: "T-1000"},
|
|
expected: result{
|
|
oid: nil,
|
|
ok: false,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
oid, ok := oidFromNamedCurve(test.curve)
|
|
require.Equal(t, oid, test.expected.oid)
|
|
require.Equal(t, ok, test.expected.ok)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestECDSAKeys(t *testing.T) {
|
|
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
if err != nil {
|
|
t.Fatalf("Failed generating ECDSA key [%s]", err)
|
|
}
|
|
|
|
// Private Key DER format
|
|
der, err := privateKeyToDER(key)
|
|
if err != nil {
|
|
t.Fatalf("Failed converting private key to DER [%s]", err)
|
|
}
|
|
keyFromDER, err := derToPrivateKey(der)
|
|
if err != nil {
|
|
t.Fatalf("Failed converting DER to private key [%s]", err)
|
|
}
|
|
ecdsaKeyFromDer := keyFromDER.(*ecdsa.PrivateKey)
|
|
// TODO: check the curve
|
|
if key.D.Cmp(ecdsaKeyFromDer.D) != 0 {
|
|
t.Fatal("Failed converting DER to private key. Invalid D.")
|
|
}
|
|
if key.X.Cmp(ecdsaKeyFromDer.X) != 0 {
|
|
t.Fatal("Failed converting DER to private key. Invalid X coordinate.")
|
|
}
|
|
if key.Y.Cmp(ecdsaKeyFromDer.Y) != 0 {
|
|
t.Fatal("Failed converting DER to private key. Invalid Y coordinate.")
|
|
}
|
|
|
|
// Private Key PEM format
|
|
rawPEM, err := privateKeyToPEM(key, nil)
|
|
if err != nil {
|
|
t.Fatalf("Failed converting private key to PEM [%s]", err)
|
|
}
|
|
pemBlock, _ := pem.Decode(rawPEM)
|
|
if pemBlock.Type != "PRIVATE KEY" {
|
|
t.Fatalf("Expected type 'PRIVATE KEY' but found '%s'", pemBlock.Type)
|
|
}
|
|
_, err = x509.ParsePKCS8PrivateKey(pemBlock.Bytes)
|
|
if err != nil {
|
|
t.Fatalf("Failed to parse PKCS#8 private key [%s]", err)
|
|
}
|
|
keyFromPEM, err := pemToPrivateKey(rawPEM, nil)
|
|
if err != nil {
|
|
t.Fatalf("Failed converting DER to private key [%s]", err)
|
|
}
|
|
ecdsaKeyFromPEM := keyFromPEM.(*ecdsa.PrivateKey)
|
|
// TODO: check the curve
|
|
if key.D.Cmp(ecdsaKeyFromPEM.D) != 0 {
|
|
t.Fatal("Failed converting PEM to private key. Invalid D.")
|
|
}
|
|
if key.X.Cmp(ecdsaKeyFromPEM.X) != 0 {
|
|
t.Fatal("Failed converting PEM to private key. Invalid X coordinate.")
|
|
}
|
|
if key.Y.Cmp(ecdsaKeyFromPEM.Y) != 0 {
|
|
t.Fatal("Failed converting PEM to private key. Invalid Y coordinate.")
|
|
}
|
|
|
|
// Nil Private Key <-> PEM
|
|
_, err = privateKeyToPEM(nil, nil)
|
|
if err == nil {
|
|
t.Fatal("PublicKeyToPEM should fail on nil")
|
|
}
|
|
|
|
_, err = privateKeyToPEM((*ecdsa.PrivateKey)(nil), nil)
|
|
if err == nil {
|
|
t.Fatal("PrivateKeyToPEM should fail on nil")
|
|
}
|
|
|
|
_, err = pemToPrivateKey(nil, nil)
|
|
if err == nil {
|
|
t.Fatal("PEMtoPublicKey should fail on nil")
|
|
}
|
|
|
|
_, err = pemToPrivateKey([]byte{0, 1, 3, 4}, nil)
|
|
if err == nil {
|
|
t.Fatal("PEMtoPublicKey should fail invalid PEM")
|
|
}
|
|
|
|
_, err = derToPrivateKey(nil)
|
|
if err == nil {
|
|
t.Fatal("DERToPrivateKey should fail on nil")
|
|
}
|
|
|
|
_, err = derToPrivateKey([]byte{0, 1, 3, 4})
|
|
if err == nil {
|
|
t.Fatal("DERToPrivateKey should fail on invalid DER")
|
|
}
|
|
|
|
_, err = privateKeyToDER(nil)
|
|
if err == nil {
|
|
t.Fatal("DERToPrivateKey should fail on nil")
|
|
}
|
|
|
|
// Private Key Encrypted PEM format
|
|
encPEM, err := privateKeyToPEM(key, []byte("passwd"))
|
|
if err != nil {
|
|
t.Fatalf("Failed converting private key to encrypted PEM [%s]", err)
|
|
}
|
|
_, err = pemToPrivateKey(encPEM, nil)
|
|
require.Error(t, err)
|
|
encKeyFromPEM, err := pemToPrivateKey(encPEM, []byte("passwd"))
|
|
if err != nil {
|
|
t.Fatalf("Failed converting DER to private key [%s]", err)
|
|
}
|
|
ecdsaKeyFromEncPEM := encKeyFromPEM.(*ecdsa.PrivateKey)
|
|
// TODO: check the curve
|
|
if key.D.Cmp(ecdsaKeyFromEncPEM.D) != 0 {
|
|
t.Fatal("Failed converting encrypted PEM to private key. Invalid D.")
|
|
}
|
|
if key.X.Cmp(ecdsaKeyFromEncPEM.X) != 0 {
|
|
t.Fatal("Failed converting encrypted PEM to private key. Invalid X coordinate.")
|
|
}
|
|
if key.Y.Cmp(ecdsaKeyFromEncPEM.Y) != 0 {
|
|
t.Fatal("Failed converting encrypted PEM to private key. Invalid Y coordinate.")
|
|
}
|
|
|
|
// Public Key PEM format
|
|
rawPEM, err = publicKeyToPEM(&key.PublicKey, nil)
|
|
if err != nil {
|
|
t.Fatalf("Failed converting public key to PEM [%s]", err)
|
|
}
|
|
pemBlock, _ = pem.Decode(rawPEM)
|
|
if pemBlock.Type != "PUBLIC KEY" {
|
|
t.Fatalf("Expected type 'PUBLIC KEY' but found '%s'", pemBlock.Type)
|
|
}
|
|
keyFromPEM, err = pemToPublicKey(rawPEM, nil)
|
|
if err != nil {
|
|
t.Fatalf("Failed converting DER to public key [%s]", err)
|
|
}
|
|
ecdsaPkFromPEM := keyFromPEM.(*ecdsa.PublicKey)
|
|
// TODO: check the curve
|
|
if key.X.Cmp(ecdsaPkFromPEM.X) != 0 {
|
|
t.Fatal("Failed converting PEM to private key. Invalid X coordinate.")
|
|
}
|
|
if key.Y.Cmp(ecdsaPkFromPEM.Y) != 0 {
|
|
t.Fatal("Failed converting PEM to private key. Invalid Y coordinate.")
|
|
}
|
|
|
|
// Nil Public Key <-> PEM
|
|
_, err = publicKeyToPEM(nil, nil)
|
|
if err == nil {
|
|
t.Fatal("PublicKeyToPEM should fail on nil")
|
|
}
|
|
|
|
_, err = pemToPublicKey(nil, nil)
|
|
if err == nil {
|
|
t.Fatal("PEMtoPublicKey should fail on nil")
|
|
}
|
|
|
|
_, err = pemToPublicKey([]byte{0, 1, 3, 4}, nil)
|
|
if err == nil {
|
|
t.Fatal("PEMtoPublicKey should fail on invalid PEM")
|
|
}
|
|
|
|
// Public Key Encrypted PEM format
|
|
encPEM, err = publicKeyToPEM(&key.PublicKey, []byte("passwd"))
|
|
if err != nil {
|
|
t.Fatalf("Failed converting private key to encrypted PEM [%s]", err)
|
|
}
|
|
_, err = pemToPublicKey(encPEM, nil)
|
|
require.Error(t, err)
|
|
pkFromEncPEM, err := pemToPublicKey(encPEM, []byte("passwd"))
|
|
if err != nil {
|
|
t.Fatalf("Failed converting DER to private key [%s]", err)
|
|
}
|
|
ecdsaPkFromEncPEM := pkFromEncPEM.(*ecdsa.PublicKey)
|
|
// TODO: check the curve
|
|
if key.X.Cmp(ecdsaPkFromEncPEM.X) != 0 {
|
|
t.Fatal("Failed converting encrypted PEM to private key. Invalid X coordinate.")
|
|
}
|
|
if key.Y.Cmp(ecdsaPkFromEncPEM.Y) != 0 {
|
|
t.Fatal("Failed converting encrypted PEM to private key. Invalid Y coordinate.")
|
|
}
|
|
|
|
_, err = pemToPublicKey(encPEM, []byte("passw"))
|
|
if err == nil {
|
|
t.Fatal("PEMtoPublicKey should fail on wrong password")
|
|
}
|
|
|
|
_, err = pemToPublicKey(encPEM, []byte("passw"))
|
|
if err == nil {
|
|
t.Fatal("PEMtoPublicKey should fail on nil password")
|
|
}
|
|
|
|
_, err = pemToPublicKey(nil, []byte("passwd"))
|
|
if err == nil {
|
|
t.Fatal("PEMtoPublicKey should fail on nil PEM")
|
|
}
|
|
|
|
_, err = pemToPublicKey([]byte{0, 1, 3, 4}, []byte("passwd"))
|
|
if err == nil {
|
|
t.Fatal("PEMtoPublicKey should fail on invalid PEM")
|
|
}
|
|
|
|
_, err = pemToPublicKey(nil, []byte("passw"))
|
|
if err == nil {
|
|
t.Fatal("PEMtoPublicKey should fail on nil PEM and wrong password")
|
|
}
|
|
|
|
// Public Key DER format
|
|
der, err = x509.MarshalPKIXPublicKey(&key.PublicKey)
|
|
require.NoError(t, err)
|
|
keyFromDER, err = derToPublicKey(der)
|
|
require.NoError(t, err)
|
|
ecdsaPkFromPEM = keyFromDER.(*ecdsa.PublicKey)
|
|
// TODO: check the curve
|
|
if key.X.Cmp(ecdsaPkFromPEM.X) != 0 {
|
|
t.Fatal("Failed converting PEM to private key. Invalid X coordinate.")
|
|
}
|
|
if key.Y.Cmp(ecdsaPkFromPEM.Y) != 0 {
|
|
t.Fatal("Failed converting PEM to private key. Invalid Y coordinate.")
|
|
}
|
|
}
|
|
|
|
func TestAESKey(t *testing.T) {
|
|
k := []byte{0, 1, 2, 3, 4, 5}
|
|
pem := aesToPEM(k)
|
|
|
|
k2, err := pemToAES(pem, nil)
|
|
require.NoError(t, err)
|
|
require.Equal(t, k, k2)
|
|
|
|
pem, err = aesToEncryptedPEM(k, k)
|
|
require.NoError(t, err)
|
|
|
|
k2, err = pemToAES(pem, k)
|
|
require.NoError(t, err)
|
|
require.Equal(t, k, k2)
|
|
|
|
_, err = pemToAES(pem, nil)
|
|
require.Error(t, err)
|
|
|
|
_, err = aesToEncryptedPEM(k, nil)
|
|
require.NoError(t, err)
|
|
|
|
k2, err = pemToAES(pem, k)
|
|
require.NoError(t, err)
|
|
require.Equal(t, k, k2)
|
|
}
|
|
|
|
func TestDERToPublicKey(t *testing.T) {
|
|
_, err := derToPublicKey(nil)
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestNil(t *testing.T) {
|
|
_, err := privateKeyToEncryptedPEM(nil, nil)
|
|
require.Error(t, err)
|
|
|
|
_, err = privateKeyToEncryptedPEM((*ecdsa.PrivateKey)(nil), nil)
|
|
require.Error(t, err)
|
|
|
|
_, err = privateKeyToEncryptedPEM("Hello World", nil)
|
|
require.Error(t, err)
|
|
|
|
_, err = pemToAES(nil, nil)
|
|
require.Error(t, err)
|
|
|
|
_, err = aesToEncryptedPEM(nil, nil)
|
|
require.Error(t, err)
|
|
|
|
_, err = publicKeyToPEM(nil, nil)
|
|
require.Error(t, err)
|
|
_, err = publicKeyToPEM((*ecdsa.PublicKey)(nil), nil)
|
|
require.Error(t, err)
|
|
_, err = publicKeyToPEM(nil, []byte("hello world"))
|
|
require.Error(t, err)
|
|
|
|
_, err = publicKeyToPEM("hello world", nil)
|
|
require.Error(t, err)
|
|
_, err = publicKeyToPEM("hello world", []byte("hello world"))
|
|
require.Error(t, err)
|
|
|
|
_, err = publicKeyToEncryptedPEM(nil, nil)
|
|
require.Error(t, err)
|
|
_, err = publicKeyToEncryptedPEM((*ecdsa.PublicKey)(nil), nil)
|
|
require.Error(t, err)
|
|
_, err = publicKeyToEncryptedPEM("hello world", nil)
|
|
require.Error(t, err)
|
|
_, err = publicKeyToEncryptedPEM("hello world", []byte("Hello world"))
|
|
require.Error(t, err)
|
|
}
|