helper_test.go 3.5 KB

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