github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/common/crypto/tlsgen/key.go (about) 1 /* 2 Copyright hechain. 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/sha256" 15 "crypto/x509" 16 "crypto/x509/pkix" 17 "encoding/pem" 18 "math/big" 19 "net" 20 "time" 21 22 "github.com/pkg/errors" 23 ) 24 25 func newPrivKey() (*ecdsa.PrivateKey, []byte, error) { 26 privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 27 if err != nil { 28 return nil, nil, err 29 } 30 privBytes, err := x509.MarshalPKCS8PrivateKey(privateKey) 31 if err != nil { 32 return nil, nil, err 33 } 34 return privateKey, privBytes, nil 35 } 36 37 func newCertTemplate() (x509.Certificate, error) { 38 sn, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) 39 if err != nil { 40 return x509.Certificate{}, err 41 } 42 return x509.Certificate{ 43 Subject: pkix.Name{SerialNumber: sn.String()}, 44 NotBefore: time.Now().Add(time.Hour * (-24)), 45 NotAfter: time.Now().Add(time.Hour * 24), 46 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, 47 SerialNumber: sn, 48 }, nil 49 } 50 51 func newCertKeyPair(isCA bool, isServer bool, certSigner crypto.Signer, parent *x509.Certificate, hosts ...string) (*CertKeyPair, error) { 52 privateKey, privBytes, err := newPrivKey() 53 if err != nil { 54 return nil, err 55 } 56 57 template, err := newCertTemplate() 58 if err != nil { 59 return nil, err 60 } 61 62 tenYearsFromNow := time.Now().Add(time.Hour * 24 * 365 * 10) 63 if isCA { 64 template.NotAfter = tenYearsFromNow 65 template.IsCA = true 66 template.KeyUsage |= x509.KeyUsageCertSign | x509.KeyUsageCRLSign 67 template.ExtKeyUsage = []x509.ExtKeyUsage{ 68 x509.ExtKeyUsageClientAuth, 69 x509.ExtKeyUsageServerAuth, 70 } 71 template.BasicConstraintsValid = true 72 } else { 73 template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth} 74 } 75 if isServer { 76 template.NotAfter = tenYearsFromNow 77 template.ExtKeyUsage = append(template.ExtKeyUsage, x509.ExtKeyUsageServerAuth) 78 for _, host := range hosts { 79 if ip := net.ParseIP(host); ip != nil { 80 template.IPAddresses = append(template.IPAddresses, ip) 81 } else { 82 template.DNSNames = append(template.DNSNames, host) 83 } 84 } 85 } 86 template.SubjectKeyId = computeSKI(&privateKey.PublicKey) 87 // If no parent cert, it's a self signed cert 88 if parent == nil || certSigner == nil { 89 parent = &template 90 certSigner = privateKey 91 } 92 rawBytes, err := x509.CreateCertificate(rand.Reader, &template, parent, &privateKey.PublicKey, certSigner) 93 if err != nil { 94 return nil, err 95 } 96 pubKey := encodePEM("CERTIFICATE", rawBytes) 97 98 block, _ := pem.Decode(pubKey) 99 if block == nil { // Never comes unless x509 or pem has bug 100 return nil, errors.Errorf("%s: wrong PEM encoding", pubKey) 101 } 102 cert, err := x509.ParseCertificate(block.Bytes) 103 if err != nil { 104 return nil, err 105 } 106 privKey := encodePEM("EC PRIVATE KEY", privBytes) 107 return &CertKeyPair{ 108 Key: privKey, 109 Cert: pubKey, 110 Signer: privateKey, 111 TLSCert: cert, 112 }, nil 113 } 114 115 func encodePEM(keyType string, data []byte) []byte { 116 return pem.EncodeToMemory(&pem.Block{Type: keyType, Bytes: data}) 117 } 118 119 // RFC 7093, Section 2, Method 4 120 func computeSKI(key *ecdsa.PublicKey) []byte { 121 raw := elliptic.Marshal(key.Curve, key.X, key.Y) 122 hash := sha256.Sum256(raw) 123 return hash[:] 124 }