cert.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. package cert_test
  2. import (
  3. "crypto/ecdh"
  4. "crypto/ecdsa"
  5. "crypto/elliptic"
  6. "crypto/rand"
  7. "io"
  8. "net/netip"
  9. "time"
  10. "github.com/slackhq/nebula/cert"
  11. "golang.org/x/crypto/curve25519"
  12. "golang.org/x/crypto/ed25519"
  13. )
  14. // NewTestCaCert will create a new ca certificate
  15. func NewTestCaCert(version cert.Version, curve cert.Curve, before, after time.Time, networks, unsafeNetworks []netip.Prefix, groups []string) (cert.Certificate, []byte, []byte, []byte) {
  16. var err error
  17. var pub, priv []byte
  18. switch curve {
  19. case cert.Curve_CURVE25519:
  20. pub, priv, err = ed25519.GenerateKey(rand.Reader)
  21. if err != nil {
  22. panic(err)
  23. }
  24. case cert.Curve_P256:
  25. privk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  26. if err != nil {
  27. panic(err)
  28. }
  29. pub = elliptic.Marshal(elliptic.P256(), privk.PublicKey.X, privk.PublicKey.Y)
  30. priv = privk.D.FillBytes(make([]byte, 32))
  31. default:
  32. // There is no default to allow the underlying lib to respond with an error
  33. }
  34. if before.IsZero() {
  35. before = time.Now().Add(time.Second * -60).Round(time.Second)
  36. }
  37. if after.IsZero() {
  38. after = time.Now().Add(time.Second * 60).Round(time.Second)
  39. }
  40. t := &cert.TBSCertificate{
  41. Curve: curve,
  42. Version: version,
  43. Name: "test ca",
  44. NotBefore: time.Unix(before.Unix(), 0),
  45. NotAfter: time.Unix(after.Unix(), 0),
  46. PublicKey: pub,
  47. Networks: networks,
  48. UnsafeNetworks: unsafeNetworks,
  49. Groups: groups,
  50. IsCA: true,
  51. }
  52. c, err := t.Sign(nil, curve, priv)
  53. if err != nil {
  54. panic(err)
  55. }
  56. pem, err := c.MarshalPEM()
  57. if err != nil {
  58. panic(err)
  59. }
  60. return c, pub, priv, pem
  61. }
  62. // NewTestCert will generate a signed certificate with the provided details.
  63. // Expiry times are defaulted if you do not pass them in
  64. func NewTestCert(v cert.Version, curve cert.Curve, ca cert.Certificate, key []byte, name string, before, after time.Time, networks, unsafeNetworks []netip.Prefix, groups []string) (cert.Certificate, []byte, []byte, []byte) {
  65. if before.IsZero() {
  66. before = time.Now().Add(time.Second * -60).Round(time.Second)
  67. }
  68. if after.IsZero() {
  69. after = time.Now().Add(time.Second * 60).Round(time.Second)
  70. }
  71. var pub, priv []byte
  72. switch curve {
  73. case cert.Curve_CURVE25519:
  74. pub, priv = X25519Keypair()
  75. case cert.Curve_P256:
  76. pub, priv = P256Keypair()
  77. default:
  78. panic("unknown curve")
  79. }
  80. nc := &cert.TBSCertificate{
  81. Version: v,
  82. Curve: curve,
  83. Name: name,
  84. Networks: networks,
  85. UnsafeNetworks: unsafeNetworks,
  86. Groups: groups,
  87. NotBefore: time.Unix(before.Unix(), 0),
  88. NotAfter: time.Unix(after.Unix(), 0),
  89. PublicKey: pub,
  90. IsCA: false,
  91. }
  92. c, err := nc.Sign(ca, ca.Curve(), key)
  93. if err != nil {
  94. panic(err)
  95. }
  96. pem, err := c.MarshalPEM()
  97. if err != nil {
  98. panic(err)
  99. }
  100. return c, pub, cert.MarshalPrivateKeyToPEM(curve, priv), pem
  101. }
  102. func X25519Keypair() ([]byte, []byte) {
  103. privkey := make([]byte, 32)
  104. if _, err := io.ReadFull(rand.Reader, privkey); err != nil {
  105. panic(err)
  106. }
  107. pubkey, err := curve25519.X25519(privkey, curve25519.Basepoint)
  108. if err != nil {
  109. panic(err)
  110. }
  111. return pubkey, privkey
  112. }
  113. func P256Keypair() ([]byte, []byte) {
  114. privkey, err := ecdh.P256().GenerateKey(rand.Reader)
  115. if err != nil {
  116. panic(err)
  117. }
  118. pubkey := privkey.PublicKey()
  119. return pubkey.Bytes(), privkey.Bytes()
  120. }