github.com/hyperledger-labs/bdls@v2.1.1+incompatible/common/crypto/tlsgen/key.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package tlsgen 8 9 import ( 10 "crypto" 11 "crypto/ecdsa" 12 "crypto/elliptic" 13 "crypto/rand" 14 "crypto/x509" 15 "crypto/x509/pkix" 16 "encoding/pem" 17 "math/big" 18 "net" 19 "time" 20 21 "github.com/pkg/errors" 22 ) 23 24 func newPrivKey() (*ecdsa.PrivateKey, []byte, error) { 25 privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 26 if err != nil { 27 return nil, nil, err 28 } 29 privBytes, err := x509.MarshalPKCS8PrivateKey(privateKey) 30 if err != nil { 31 return nil, nil, err 32 } 33 return privateKey, privBytes, nil 34 } 35 36 func newCertTemplate() (x509.Certificate, error) { 37 sn, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) 38 if err != nil { 39 return x509.Certificate{}, err 40 } 41 return x509.Certificate{ 42 Subject: pkix.Name{SerialNumber: sn.String()}, 43 NotBefore: time.Now().Add(time.Hour * (-24)), 44 NotAfter: time.Now().Add(time.Hour * 24), 45 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, 46 SerialNumber: sn, 47 }, nil 48 } 49 50 func newCertKeyPair(isCA bool, isServer bool, host string, certSigner crypto.Signer, parent *x509.Certificate) (*CertKeyPair, error) { 51 privateKey, privBytes, err := newPrivKey() 52 if err != nil { 53 return nil, err 54 } 55 56 template, err := newCertTemplate() 57 if err != nil { 58 return nil, err 59 } 60 61 tenYearsFromNow := time.Now().Add(time.Hour * 24 * 365 * 10) 62 if isCA { 63 template.NotAfter = tenYearsFromNow 64 template.IsCA = true 65 template.KeyUsage |= x509.KeyUsageCertSign | x509.KeyUsageCRLSign 66 template.ExtKeyUsage = []x509.ExtKeyUsage{ 67 x509.ExtKeyUsageClientAuth, 68 x509.ExtKeyUsageServerAuth, 69 } 70 template.BasicConstraintsValid = true 71 } else { 72 template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth} 73 } 74 if isServer { 75 template.NotAfter = tenYearsFromNow 76 template.ExtKeyUsage = append(template.ExtKeyUsage, x509.ExtKeyUsageServerAuth) 77 if ip := net.ParseIP(host); ip != nil { 78 template.IPAddresses = append(template.IPAddresses, ip) 79 } else { 80 template.DNSNames = append(template.DNSNames, host) 81 } 82 } 83 // If no parent cert, it's a self signed cert 84 if parent == nil || certSigner == nil { 85 parent = &template 86 certSigner = privateKey 87 } 88 rawBytes, err := x509.CreateCertificate(rand.Reader, &template, parent, &privateKey.PublicKey, certSigner) 89 if err != nil { 90 return nil, err 91 } 92 pubKey := encodePEM("CERTIFICATE", rawBytes) 93 94 block, _ := pem.Decode(pubKey) 95 if block == nil { // Never comes unless x509 or pem has bug 96 return nil, errors.Errorf("%s: wrong PEM encoding", pubKey) 97 } 98 cert, err := x509.ParseCertificate(block.Bytes) 99 if err != nil { 100 return nil, err 101 } 102 privKey := encodePEM("EC PRIVATE KEY", privBytes) 103 return &CertKeyPair{ 104 Key: privKey, 105 Cert: pubKey, 106 Signer: privateKey, 107 TLSCert: cert, 108 }, nil 109 } 110 111 func encodePEM(keyType string, data []byte) []byte { 112 return pem.EncodeToMemory(&pem.Block{Type: keyType, Bytes: data}) 113 }