github.com/status-im/status-go@v1.1.0/server/certs.go (about) 1 package server 2 3 import ( 4 "crypto/ecdsa" 5 "crypto/elliptic" 6 "crypto/rand" 7 "crypto/tls" 8 "crypto/x509" 9 "crypto/x509/pkix" 10 "encoding/pem" 11 "math/big" 12 "net" 13 "time" 14 15 "github.com/ethereum/go-ethereum/log" 16 ) 17 18 var globalMediaCertificate *tls.Certificate = nil 19 var globalMediaPem string 20 21 func makeRandomSerialNumber() (*big.Int, error) { 22 serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) 23 return rand.Int(rand.Reader, serialNumberLimit) 24 } 25 26 func GenerateX509Cert(sn *big.Int, from, to time.Time, IPAddresses []net.IP, DNSNames []string) *x509.Certificate { 27 return &x509.Certificate{ 28 SerialNumber: sn, 29 Subject: pkix.Name{Organization: []string{"Self-signed cert"}}, 30 NotBefore: from, 31 NotAfter: to, 32 KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, 33 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 34 BasicConstraintsValid: true, 35 IsCA: true, 36 IPAddresses: IPAddresses, 37 DNSNames: DNSNames, 38 } 39 } 40 41 func GenerateX509PEMs(cert *x509.Certificate, key *ecdsa.PrivateKey) (certPem, keyPem []byte, err error) { 42 derBytes, err := x509.CreateCertificate(rand.Reader, cert, cert, &key.PublicKey, key) 43 if err != nil { 44 return 45 } 46 certPem = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) 47 48 privBytes, err := x509.MarshalPKCS8PrivateKey(key) 49 if err != nil { 50 return 51 } 52 keyPem = pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}) 53 54 return 55 } 56 57 func GenerateTLSCert(notBefore, notAfter time.Time, IPAddresses []net.IP, DNSNames []string) (*tls.Certificate, []byte, error) { 58 priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 59 if err != nil { 60 return nil, nil, err 61 } 62 63 sn, err := makeRandomSerialNumber() 64 if err != nil { 65 return nil, nil, err 66 } 67 68 cert := GenerateX509Cert(sn, notBefore, notAfter, IPAddresses, DNSNames) 69 certPem, keyPem, err := GenerateX509PEMs(cert, priv) 70 if err != nil { 71 return nil, nil, err 72 } 73 74 finalCert, err := tls.X509KeyPair(certPem, keyPem) 75 return &finalCert, certPem, err 76 } 77 78 func generateMediaTLSCert() error { 79 if globalMediaCertificate != nil { 80 return nil 81 } 82 83 now := time.Now() 84 notBefore := now.Add(-365 * 24 * time.Hour * 100) 85 notAfter := now.Add(365 * 24 * time.Hour * 100) 86 log.Debug("generate media cert", "system time", time.Now().String(), "cert notBefore", notBefore.String(), "cert notAfter", notAfter.String()) 87 finalCert, certPem, err := GenerateTLSCert(notBefore, notAfter, []net.IP{}, []string{Localhost}) 88 if err != nil { 89 return err 90 } 91 92 globalMediaCertificate = finalCert 93 globalMediaPem = string(certPem) 94 return nil 95 } 96 97 func PublicMediaTLSCert() (string, error) { 98 err := generateMediaTLSCert() 99 if err != nil { 100 return "", err 101 } 102 103 return globalMediaPem, nil 104 } 105 106 // ToECDSA takes a []byte of D and uses it to create an ecdsa.PublicKey on the elliptic.P256 curve 107 // this function is basically a P256 curve version of eth-node/crypto.ToECDSA without all the nice validation 108 func ToECDSA(d []byte) *ecdsa.PrivateKey { 109 k := new(ecdsa.PrivateKey) 110 k.D = new(big.Int).SetBytes(d) 111 k.PublicKey.Curve = elliptic.P256() 112 113 k.PublicKey.X, k.PublicKey.Y = k.PublicKey.Curve.ScalarBaseMult(d) 114 return k 115 }