selfsign.go 2.9 KB

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