Created
September 7, 2017 15:20
-
-
Save dmage/2f02039cb5f7b3c22cf960c90dfc9132 to your computer and use it in GitHub Desktop.
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/rand" | |
"crypto/rsa" | |
"crypto/tls" | |
"crypto/x509" | |
"crypto/x509/pkix" | |
"fmt" | |
"log" | |
"math/big" | |
"net" | |
"net/http" | |
"time" | |
) | |
type KeyPair struct { | |
Certificate []byte | |
PrivateKey interface{} | |
} | |
type CertificateOptions struct { | |
Subject pkix.Name | |
ValidFor time.Duration | |
IsCA bool | |
DNSNames []string | |
IPAddresses []net.IP | |
} | |
func GenerateRSAKeyPair(rsaBits int, parent *KeyPair, opts CertificateOptions) (*KeyPair, error) { | |
fail := func(format string, args ...interface{}) (*KeyPair, error) { | |
return nil, fmt.Errorf(format, args) | |
} | |
priv, err := rsa.GenerateKey(rand.Reader, rsaBits) | |
if err != nil { | |
return fail("failed to generate private key: %s", err) | |
} | |
notBefore := time.Now() | |
notAfter := notBefore.Add(opts.ValidFor) | |
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) | |
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) | |
if err != nil { | |
return fail("failed to generate serial number: %s", err) | |
} | |
keyUsage := x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | |
if opts.IsCA { | |
keyUsage |= x509.KeyUsageCertSign | |
} | |
template := x509.Certificate{ | |
SerialNumber: serialNumber, | |
Subject: opts.Subject, | |
NotBefore: notBefore, | |
NotAfter: notAfter, | |
KeyUsage: keyUsage, | |
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, | |
BasicConstraintsValid: true, | |
IsCA: opts.IsCA, | |
DNSNames: opts.DNSNames, | |
IPAddresses: opts.IPAddresses, | |
} | |
var parentCert *x509.Certificate | |
var parentPriv interface{} | |
if parent != nil { | |
parentCert, err = x509.ParseCertificate(parent.Certificate) | |
if err != nil { | |
return fail("failed to parse parent certificate: %s", err) | |
} | |
parentPriv = parent.PrivateKey | |
} else { | |
parentCert = &template | |
parentPriv = priv | |
} | |
derBytes, err := x509.CreateCertificate(rand.Reader, &template, parentCert, &priv.PublicKey, parentPriv) | |
if err != nil { | |
return fail("failed to create certificate: %s", err) | |
} | |
return &KeyPair{ | |
Certificate: derBytes, | |
PrivateKey: priv, | |
}, nil | |
} | |
func main() { | |
rootKeyPair, err := GenerateRSAKeyPair(1024, nil, CertificateOptions{ | |
Subject: pkix.Name{ | |
Organization: []string{"OpenShift Test Suite"}, | |
}, | |
ValidFor: 24 * time.Hour, | |
IsCA: true, | |
}) | |
if err != nil { | |
log.Fatal(err) | |
} | |
keyPair, err := GenerateRSAKeyPair(1024, rootKeyPair, CertificateOptions{ | |
Subject: pkix.Name{ | |
Organization: []string{"Server Certificate"}, | |
CommonName: "localhost", | |
}, | |
ValidFor: 12 * time.Hour, | |
}) | |
if err != nil { | |
log.Fatal(err) | |
} | |
config := &tls.Config{ | |
Certificates: []tls.Certificate{{ | |
Certificate: [][]byte{keyPair.Certificate}, | |
PrivateKey: keyPair.PrivateKey, | |
}}, | |
} | |
server := &http.Server{ | |
Addr: ":8443", | |
TLSConfig: config, | |
} | |
log.Fatal(server.ListenAndServeTLS("", "")) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment