2016-04-21 19:50:03 -04:00
|
|
|
package pkcs12
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/ecdsa"
|
|
|
|
"crypto/elliptic"
|
|
|
|
"crypto/rand"
|
|
|
|
"crypto/rsa"
|
|
|
|
"crypto/x509"
|
|
|
|
"crypto/x509/pkix"
|
|
|
|
"fmt"
|
|
|
|
"math/big"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
gopkcs12 "golang.org/x/crypto/pkcs12"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestPfxRoundTriRsa(t *testing.T) {
|
|
|
|
privateKey, err := rsa.GenerateKey(rand.Reader, 512)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
key := testPfxRoundTrip(t, privateKey)
|
|
|
|
|
|
|
|
actualPrivateKey, ok := key.(*rsa.PrivateKey)
|
|
|
|
if !ok {
|
2016-07-16 01:23:53 -04:00
|
|
|
t.Fatal("failed to decode private key")
|
2016-04-21 19:50:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if privateKey.D.Cmp(actualPrivateKey.D) != 0 {
|
|
|
|
t.Errorf("priv.D")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestPfxRoundTriEcdsa(t *testing.T) {
|
|
|
|
privateKey, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
key := testPfxRoundTrip(t, privateKey)
|
|
|
|
|
|
|
|
actualPrivateKey, ok := key.(*ecdsa.PrivateKey)
|
|
|
|
if !ok {
|
|
|
|
t.Fatalf("failed to decode private key")
|
|
|
|
}
|
|
|
|
|
|
|
|
if privateKey.D.Cmp(actualPrivateKey.D) != 0 {
|
|
|
|
t.Errorf("priv.D")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func testPfxRoundTrip(t *testing.T, privateKey interface{}) interface{} {
|
|
|
|
certificateBytes, err := newCertificate("hostname", privateKey)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
bytes, err := Encode(certificateBytes, privateKey, "sesame")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
key, _, err := gopkcs12.Decode(bytes, "sesame")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf(err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
return key
|
|
|
|
}
|
|
|
|
|
|
|
|
func newCertificate(hostname string, privateKey interface{}) ([]byte, error) {
|
|
|
|
t, _ := time.Parse("2006-01-02", "2016-01-01")
|
|
|
|
notBefore := t
|
|
|
|
notAfter := notBefore.Add(365 * 24 * time.Hour)
|
|
|
|
|
|
|
|
serialNumber, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
|
|
|
|
if err != nil {
|
|
|
|
err := fmt.Errorf("Failed to Generate Serial Number: %v", err)
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
template := x509.Certificate{
|
|
|
|
SerialNumber: serialNumber,
|
|
|
|
Issuer: pkix.Name{
|
|
|
|
CommonName: hostname,
|
|
|
|
},
|
|
|
|
Subject: pkix.Name{
|
|
|
|
CommonName: hostname,
|
|
|
|
},
|
|
|
|
|
|
|
|
NotBefore: notBefore,
|
|
|
|
NotAfter: notAfter,
|
|
|
|
|
|
|
|
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
|
|
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
|
|
|
BasicConstraintsValid: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
var publicKey interface{}
|
|
|
|
switch key := privateKey.(type) {
|
|
|
|
case *rsa.PrivateKey:
|
|
|
|
publicKey = key.Public()
|
|
|
|
case *ecdsa.PrivateKey:
|
|
|
|
publicKey = key.Public()
|
|
|
|
default:
|
|
|
|
panic(fmt.Sprintf("unsupported private key type: %T", privateKey))
|
|
|
|
}
|
|
|
|
|
|
|
|
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey, privateKey)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("Failed to Generate derBytes: " + err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
return derBytes, nil
|
|
|
|
}
|