github.com/hoffie/larasync@v0.0.0-20151025221940-0384d2bddcef/helpers/x509/generate.go (about) 1 package x509 2 3 import ( 4 "crypto/ecdsa" 5 "crypto/elliptic" 6 "crypto/rand" 7 "crypto/x509" 8 "crypto/x509/pkix" 9 "encoding/pem" 10 "io" 11 "math/big" 12 "os" 13 "time" 14 ) 15 16 const ( 17 certFileName = "lara-server.crt" 18 keyFileName = "lara-server.key" 19 ) 20 21 // GenerateServerCert generates a new server certificate, writing the resulting 22 // keys and certificates to the provided writers. 23 func GenerateServerCert(keyOut, certOut io.Writer) error { 24 // inspired by crypto/tls/generate_cert.go 25 priv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) 26 if err != nil { 27 return err 28 } 29 serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) 30 serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) 31 if err != nil { 32 return err 33 } 34 notBefore := time.Now() 35 notAfter := notBefore.Add(128 * 365 * 24 * time.Hour) 36 37 template := x509.Certificate{ 38 SerialNumber: serialNumber, 39 Subject: pkix.Name{ 40 Organization: []string{"larasync server certificate"}, 41 }, 42 NotBefore: notBefore, 43 NotAfter: notAfter, 44 45 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, 46 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 47 BasicConstraintsValid: true, 48 } 49 50 derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, 51 &priv.PublicKey, priv) 52 if err != nil { 53 return err 54 } 55 56 pemBlock, err := pemBlockForKey(priv) 57 if err != nil { 58 return err 59 } 60 err = pem.Encode(keyOut, pemBlock) 61 if err != nil { 62 return err 63 } 64 65 err = pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) 66 if err != nil { 67 return err 68 } 69 70 return nil 71 } 72 73 // pemBlockForKey returns a pem block containing the given private key. 74 func pemBlockForKey(k *ecdsa.PrivateKey) (*pem.Block, error) { 75 b, err := x509.MarshalECPrivateKey(k) 76 if err != nil { 77 return nil, err 78 } 79 return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}, nil 80 } 81 82 // GenerateServerCertFiles creates a certificate and a key file at the given 83 // locations. 84 func GenerateServerCertFiles(certFile, keyFile string) error { 85 certOut, err := os.OpenFile(certFile, os.O_CREATE|os.O_WRONLY, 0600) 86 if err != nil { 87 return err 88 } 89 defer certOut.Close() 90 91 keyOut, err := os.OpenFile(keyFile, os.O_CREATE|os.O_WRONLY, 0600) 92 if err != nil { 93 return err 94 } 95 defer keyOut.Close() 96 97 return GenerateServerCert(keyOut, certOut) 98 }