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  }