cert.go 3.3 KB

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