Skip to content

Instantly share code, notes, and snippets.

@nicholasjackson
Last active March 14, 2017 13:58
Show Gist options
  • Save nicholasjackson/d0cfeb6dcb057a4cfada83ce635284e9 to your computer and use it in GitHub Desktop.
Save nicholasjackson/d0cfeb6dcb057a4cfada83ce635284e9 to your computer and use it in GitHub Desktop.
Generate Self Signed Intermediate Cert with Elliptical Curve
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