github.com/pion/dtls/v2@v2.2.12/pkg/crypto/selfsign/selfsign.go (about) 1 // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> 2 // SPDX-License-Identifier: MIT 3 4 // Package selfsign is a test helper that generates self signed certificate. 5 package selfsign 6 7 import ( 8 "crypto" 9 "crypto/ecdsa" 10 "crypto/ed25519" 11 "crypto/elliptic" 12 "crypto/rand" 13 "crypto/rsa" 14 "crypto/tls" 15 "crypto/x509" 16 "crypto/x509/pkix" 17 "errors" 18 "math/big" 19 "time" 20 ) 21 22 var errInvalidPrivateKey = errors.New("selfsign: invalid private key type") 23 24 // GenerateSelfSigned creates a self-signed certificate 25 func GenerateSelfSigned() (tls.Certificate, error) { 26 priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 27 if err != nil { 28 return tls.Certificate{}, err 29 } 30 31 return SelfSign(priv) 32 } 33 34 // GenerateSelfSignedWithDNS creates a self-signed certificate 35 func GenerateSelfSignedWithDNS(cn string, sans ...string) (tls.Certificate, error) { 36 priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 37 if err != nil { 38 return tls.Certificate{}, err 39 } 40 41 return WithDNS(priv, cn, sans...) 42 } 43 44 // SelfSign creates a self-signed certificate from a elliptic curve key 45 func SelfSign(key crypto.PrivateKey) (tls.Certificate, error) { 46 return WithDNS(key, "self-signed cert") 47 } 48 49 // WithDNS creates a self-signed certificate from a elliptic curve key 50 func WithDNS(key crypto.PrivateKey, cn string, sans ...string) (tls.Certificate, error) { 51 var ( 52 pubKey crypto.PublicKey 53 maxBigInt = new(big.Int) // Max random value, a 130-bits integer, i.e 2^130 - 1 54 ) 55 56 switch k := key.(type) { 57 case ed25519.PrivateKey: 58 pubKey = k.Public() 59 case *ecdsa.PrivateKey: 60 pubKey = k.Public() 61 case *rsa.PrivateKey: 62 pubKey = k.Public() 63 default: 64 return tls.Certificate{}, errInvalidPrivateKey 65 } 66 67 /* #nosec */ 68 maxBigInt.Exp(big.NewInt(2), big.NewInt(130), nil).Sub(maxBigInt, big.NewInt(1)) 69 /* #nosec */ 70 serialNumber, err := rand.Int(rand.Reader, maxBigInt) 71 if err != nil { 72 return tls.Certificate{}, err 73 } 74 75 names := []string{cn} 76 names = append(names, sans...) 77 78 keyUsage := x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign 79 if _, isRSA := key.(*rsa.PrivateKey); isRSA { 80 keyUsage |= x509.KeyUsageKeyEncipherment 81 } 82 83 template := x509.Certificate{ 84 ExtKeyUsage: []x509.ExtKeyUsage{ 85 x509.ExtKeyUsageClientAuth, 86 x509.ExtKeyUsageServerAuth, 87 }, 88 BasicConstraintsValid: true, 89 NotBefore: time.Now(), 90 KeyUsage: keyUsage, 91 NotAfter: time.Now().AddDate(0, 1, 0), 92 SerialNumber: serialNumber, 93 Version: 2, 94 IsCA: true, 95 DNSNames: names, 96 Subject: pkix.Name{ 97 CommonName: cn, 98 }, 99 } 100 101 raw, err := x509.CreateCertificate(rand.Reader, &template, &template, pubKey, key) 102 if err != nil { 103 return tls.Certificate{}, err 104 } 105 106 leaf, err := x509.ParseCertificate(raw) 107 if err != nil { 108 return tls.Certificate{}, err 109 } 110 111 return tls.Certificate{ 112 Certificate: [][]byte{raw}, 113 PrivateKey: key, 114 Leaf: leaf, 115 }, nil 116 }