123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- // Copyright (c) 2016 Daniel Oaks <daniel@danieloaks.net>
- // released under the MIT license
-
- package mkcerts
-
- import (
- "crypto/rand"
- "crypto/rsa"
- "crypto/x509"
- "crypto/x509/pkix"
- "encoding/pem"
- "fmt"
- "math/big"
- "net"
- "os"
- "time"
- )
-
- // CreateCertBytes creates a testing ECDSA certificate, returning the cert and key bytes.
- func CreateCertBytes(orgName string, host string) (certBytes []byte, keyBytes []byte, err error) {
- validFrom := time.Now()
- validFor := 365 * 24 * time.Hour
- notAfter := validFrom.Add(validFor)
-
- priv, err := rsa.GenerateKey(rand.Reader, 2048)
- if err != nil {
- return
- }
-
- serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
- serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
- if err != nil {
- return nil, nil, fmt.Errorf("failed to generate serial number: %s", err)
- }
-
- template := x509.Certificate{
- SerialNumber: serialNumber,
- Subject: pkix.Name{
- Organization: []string{orgName},
- },
- NotBefore: validFrom,
- NotAfter: notAfter,
-
- KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
- ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
- BasicConstraintsValid: true,
- }
-
- // TODO: allow explicitly listing allowed addresses/names
- template.IPAddresses = append(template.IPAddresses, net.ParseIP("127.0.0.1"))
- template.IPAddresses = append(template.IPAddresses, net.ParseIP("::1"))
- if host != "" {
- template.DNSNames = append(template.DNSNames, host)
- }
- template.DNSNames = append(template.DNSNames, "localhost")
-
- derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
- if err != nil {
- return nil, nil, fmt.Errorf("Failed to create certificate: %s", err.Error())
- }
-
- certBytes = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
-
- b, err := x509.MarshalPKCS8PrivateKey(priv)
- if err != nil {
- return nil, nil, fmt.Errorf("Unable to marshal private key: %v", err.Error())
- }
- pemBlock := pem.Block{Type: "PRIVATE KEY", Bytes: b}
- keyBytes = pem.EncodeToMemory(&pemBlock)
- return certBytes, keyBytes, nil
- }
-
- // CreateCert creates a testing ECDSA certificate, outputting the cert and key at the given filenames.
- func CreateCert(orgName string, host string, certFilename string, keyFilename string) error {
- certBytes, keyBytes, err := CreateCertBytes(orgName, host)
-
- if err != nil {
- return err
- }
-
- certOut, err := os.Create(certFilename)
- if err != nil {
- return fmt.Errorf("failed to open %s for writing: %s", certFilename, err.Error())
- }
- defer certOut.Close()
- _, err = certOut.Write(certBytes)
- if err != nil {
- return fmt.Errorf("failed to write out cert file %s: %s", certFilename, err.Error())
- }
-
- keyOut, err := os.OpenFile(keyFilename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
- if err != nil {
- return fmt.Errorf("failed to open %s for writing: %s", keyFilename, err.Error())
- }
- defer keyOut.Close()
- _, err = keyOut.Write(keyBytes)
- if err != nil {
- return fmt.Errorf("failed to write out key file %s: %s", keyFilename, err.Error())
- }
-
- return nil
- }
|