helper_test.go 3.3 KB

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