Last active
March 14, 2017 13:58
-
-
Save nicholasjackson/d0cfeb6dcb057a4cfada83ce635284e9 to your computer and use it in GitHub Desktop.
Generate Self Signed Intermediate Cert with Elliptical Curve
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"crypto/ecdsa" | |
"crypto/elliptic" | |
"crypto/rand" | |
"crypto/sha1" | |
"crypto/x509" | |
"crypto/x509/pkix" | |
"encoding/asn1" | |
"encoding/pem" | |
"fmt" | |
"log" | |
"math/big" | |
"os" | |
"time" | |
) | |
type subjectPublicKeyInfo struct { | |
Algorithm pkix.AlgorithmIdentifier | |
SubjectPublicKey asn1.BitString | |
} | |
func main() { | |
priv, _ := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) | |
pub := &priv.PublicKey | |
subjecta, _ := getSubjectKey(priv) | |
ca := &x509.Certificate{ | |
SerialNumber: big.NewInt(1653), | |
Subject: pkix.Name{ | |
Country: []string{"UK"}, | |
Organization: []string{"Acme"}, | |
OrganizationalUnit: []string{"Tech"}, | |
}, | |
NotBefore: time.Now(), | |
NotAfter: time.Now().AddDate(10, 0, 0), | |
SubjectKeyId: subjecta, | |
BasicConstraintsValid: true, | |
IsCA: true, | |
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, | |
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, | |
} | |
ca_b, err := x509.CreateCertificate(rand.Reader, ca, ca, pub, priv) | |
if err != nil { | |
log.Println("create ca failed", err) | |
return | |
} | |
priv2, _ := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) | |
pub2 := &priv2.PublicKey | |
subjectb, _ := getSubjectKey(priv) | |
cert2 := &x509.Certificate{ | |
SerialNumber: big.NewInt(1658), | |
Subject: pkix.Name{ | |
Country: []string{"UK"}, | |
Organization: []string{"Acme"}, | |
OrganizationalUnit: []string{"Tech"}, | |
}, | |
NotBefore: time.Now(), | |
NotAfter: time.Now().AddDate(10, 0, 0), | |
SubjectKeyId: subjectb, | |
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, | |
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, | |
} | |
cert2_b, err2 := x509.CreateCertificate(rand.Reader, cert2, ca, pub2, priv) | |
if err2 != nil { | |
log.Println("create cert2 failed", err2) | |
return | |
} | |
savePrivateKey(priv, "ca_key.pem") | |
savePrivateKey(priv2, "cert_key.pem") | |
saveX509Certificate(ca_b, "ca.pem") | |
saveX509Certificate(cert2_b, "cert.pem") | |
c, _ := x509.ParseCertificate(cert2_b) | |
fmt.Println(c.SignatureAlgorithm) | |
fmt.Println(c.PublicKeyAlgorithm) | |
/* | |
ca_c, _ := x509.ParseCertificate(ca_b) | |
cert2_c, _ := x509.ParseCertificate(cert2_b) | |
err3 := cert2_c.CheckSignatureFrom(ca_c) | |
log.Println("check signature", err3 == nil) | |
*/ | |
} | |
func savePrivateKey(key *ecdsa.PrivateKey, path string) error { | |
b, _ := x509.MarshalECPrivateKey(key) | |
block := &pem.Block{Type: "EC PRIVATE KEY", Bytes: b} | |
keyOut, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) | |
if err != nil { | |
return fmt.Errorf("failed to open key.pem for writing: %v", err) | |
} | |
pem.Encode(keyOut, block) | |
keyOut.Close() | |
return nil | |
} | |
func saveX509Certificate(data []byte, path string) error { | |
file, err := os.Create(path) | |
if err != nil { | |
return fmt.Errorf("failed to open cert.pem for writing: %s", err) | |
} | |
block := &pem.Block{Type: "CERTIFICATE", Bytes: data} | |
pem.Encode(file, block) | |
file.Close() | |
return nil | |
} | |
func getSubjectKey(key *ecdsa.PrivateKey) ([]byte, error) { | |
publicKey, err := x509.MarshalPKIXPublicKey(&key.PublicKey) | |
if err != nil { | |
return nil, fmt.Errorf("failed to marshal public key: %s", err) | |
} | |
var subPKI subjectPublicKeyInfo | |
_, err = asn1.Unmarshal(publicKey, &subPKI) | |
if err != nil { | |
return nil, fmt.Errorf("failed to unmarshal public key: %s", err) | |
} | |
return bigIntHash(subPKI.SubjectPublicKey.Bytes), nil | |
} | |
func bigIntHash(n []byte) []byte { | |
h := sha1.New() | |
h.Write(n) | |
return h.Sum(nil) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment