sign.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. package cert
  2. import (
  3. "crypto/ecdsa"
  4. "crypto/ed25519"
  5. "crypto/elliptic"
  6. "crypto/rand"
  7. "crypto/sha256"
  8. "fmt"
  9. "math/big"
  10. "net/netip"
  11. "time"
  12. )
  13. // TBSCertificate represents a certificate intended to be signed.
  14. // It is invalid to use this structure as a Certificate.
  15. type TBSCertificate struct {
  16. Version Version
  17. Name string
  18. Networks []netip.Prefix
  19. UnsafeNetworks []netip.Prefix
  20. Groups []string
  21. IsCA bool
  22. NotBefore time.Time
  23. NotAfter time.Time
  24. PublicKey []byte
  25. Curve Curve
  26. issuer string
  27. }
  28. type beingSignedCertificate interface {
  29. // fromTBSCertificate copies the values from the TBSCertificate to this versions internal representation
  30. // Implementations must validate the resulting certificate contains valid information
  31. fromTBSCertificate(*TBSCertificate) error
  32. // marshalForSigning returns the bytes that should be signed
  33. marshalForSigning() ([]byte, error)
  34. // setSignature sets the signature for the certificate that has just been signed. The signature must not be blank.
  35. setSignature([]byte) error
  36. }
  37. type SignerLambda func(certBytes []byte) ([]byte, error)
  38. // Sign will create a sealed certificate using details provided by the TBSCertificate as long as those
  39. // details do not violate constraints of the signing certificate.
  40. // If the TBSCertificate is a CA then signer must be nil.
  41. func (t *TBSCertificate) Sign(signer Certificate, curve Curve, key []byte) (Certificate, error) {
  42. switch t.Curve {
  43. case Curve_CURVE25519:
  44. pk := ed25519.PrivateKey(key)
  45. sp := func(certBytes []byte) ([]byte, error) {
  46. sig := ed25519.Sign(pk, certBytes)
  47. return sig, nil
  48. }
  49. return t.SignWith(signer, curve, sp)
  50. case Curve_P256:
  51. pk := &ecdsa.PrivateKey{
  52. PublicKey: ecdsa.PublicKey{
  53. Curve: elliptic.P256(),
  54. },
  55. // ref: https://github.com/golang/go/blob/go1.19/src/crypto/x509/sec1.go#L95
  56. D: new(big.Int).SetBytes(key),
  57. }
  58. // ref: https://github.com/golang/go/blob/go1.19/src/crypto/x509/sec1.go#L119
  59. pk.X, pk.Y = pk.Curve.ScalarBaseMult(key)
  60. sp := func(certBytes []byte) ([]byte, error) {
  61. // We need to hash first for ECDSA
  62. // - https://pkg.go.dev/crypto/ecdsa#SignASN1
  63. hashed := sha256.Sum256(certBytes)
  64. return ecdsa.SignASN1(rand.Reader, pk, hashed[:])
  65. }
  66. return t.SignWith(signer, curve, sp)
  67. default:
  68. return nil, fmt.Errorf("invalid curve: %s", t.Curve)
  69. }
  70. }
  71. // SignWith does the same thing as sign, but uses the function in `sp` to calculate the signature.
  72. // You should only use SignWith if you do not have direct access to your private key.
  73. func (t *TBSCertificate) SignWith(signer Certificate, curve Curve, sp SignerLambda) (Certificate, error) {
  74. if curve != t.Curve {
  75. return nil, fmt.Errorf("curve in cert and private key supplied don't match")
  76. }
  77. if signer != nil {
  78. if t.IsCA {
  79. return nil, fmt.Errorf("can not sign a CA certificate with another")
  80. }
  81. err := checkCAConstraints(signer, t.NotBefore, t.NotAfter, t.Groups, t.Networks, t.UnsafeNetworks)
  82. if err != nil {
  83. return nil, err
  84. }
  85. issuer, err := signer.Fingerprint()
  86. if err != nil {
  87. return nil, fmt.Errorf("error computing issuer: %v", err)
  88. }
  89. t.issuer = issuer
  90. } else {
  91. if !t.IsCA {
  92. return nil, fmt.Errorf("self signed certificates must have IsCA set to true")
  93. }
  94. }
  95. var c beingSignedCertificate
  96. switch t.Version {
  97. case Version1:
  98. c = &certificateV1{}
  99. err := c.fromTBSCertificate(t)
  100. if err != nil {
  101. return nil, err
  102. }
  103. case Version2:
  104. c = &certificateV2{}
  105. err := c.fromTBSCertificate(t)
  106. if err != nil {
  107. return nil, err
  108. }
  109. default:
  110. return nil, fmt.Errorf("unknown cert version %d", t.Version)
  111. }
  112. certBytes, err := c.marshalForSigning()
  113. if err != nil {
  114. return nil, err
  115. }
  116. sig, err := sp(certBytes)
  117. if err != nil {
  118. return nil, err
  119. }
  120. err = c.setSignature(sig)
  121. if err != nil {
  122. return nil, err
  123. }
  124. sc, ok := c.(Certificate)
  125. if !ok {
  126. return nil, fmt.Errorf("invalid certificate")
  127. }
  128. return sc, nil
  129. }
  130. func comparePrefix(a, b netip.Prefix) int {
  131. addr := a.Addr().Compare(b.Addr())
  132. if addr == 0 {
  133. return a.Bits() - b.Bits()
  134. }
  135. return addr
  136. }
  137. // findDuplicatePrefix returns an error if there is a duplicate prefix in the pre-sorted input slice sortedPrefixes
  138. func findDuplicatePrefix(sortedPrefixes []netip.Prefix) error {
  139. if len(sortedPrefixes) < 2 {
  140. return nil
  141. }
  142. for i := 1; i < len(sortedPrefixes); i++ {
  143. if comparePrefix(sortedPrefixes[i], sortedPrefixes[i-1]) == 0 {
  144. return NewErrInvalidCertificateProperties("duplicate network detected: %v", sortedPrefixes[i])
  145. }
  146. }
  147. return nil
  148. }