sign.go 4.2 KB

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