pem.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. package cert
  2. import (
  3. "encoding/pem"
  4. "fmt"
  5. "golang.org/x/crypto/ed25519"
  6. )
  7. const ( //cert banners
  8. CertificateBanner = "NEBULA CERTIFICATE"
  9. CertificateV2Banner = "NEBULA CERTIFICATE V2"
  10. )
  11. const ( //key-agreement-key banners
  12. X25519PrivateKeyBanner = "NEBULA X25519 PRIVATE KEY"
  13. X25519PublicKeyBanner = "NEBULA X25519 PUBLIC KEY"
  14. P256PrivateKeyBanner = "NEBULA P256 PRIVATE KEY"
  15. P256PublicKeyBanner = "NEBULA P256 PUBLIC KEY"
  16. )
  17. /* including "ECDSA" in the P256 banners is a clue that these keys should be used only for signing */
  18. const ( //signing key banners
  19. EncryptedECDSAP256PrivateKeyBanner = "NEBULA ECDSA P256 ENCRYPTED PRIVATE KEY"
  20. ECDSAP256PrivateKeyBanner = "NEBULA ECDSA P256 PRIVATE KEY"
  21. ECDSAP256PublicKeyBanner = "NEBULA ECDSA P256 PUBLIC KEY"
  22. EncryptedEd25519PrivateKeyBanner = "NEBULA ED25519 ENCRYPTED PRIVATE KEY"
  23. Ed25519PrivateKeyBanner = "NEBULA ED25519 PRIVATE KEY"
  24. Ed25519PublicKeyBanner = "NEBULA ED25519 PUBLIC KEY"
  25. )
  26. // UnmarshalCertificateFromPEM will try to unmarshal the first pem block in a byte array, returning any non consumed
  27. // data or an error on failure
  28. func UnmarshalCertificateFromPEM(b []byte) (Certificate, []byte, error) {
  29. p, r := pem.Decode(b)
  30. if p == nil {
  31. return nil, r, ErrInvalidPEMBlock
  32. }
  33. var c Certificate
  34. var err error
  35. switch p.Type {
  36. // Implementations must validate the resulting certificate contains valid information
  37. case CertificateBanner:
  38. c, err = unmarshalCertificateV1(p.Bytes, nil)
  39. case CertificateV2Banner:
  40. c, err = unmarshalCertificateV2(p.Bytes, nil, Curve_CURVE25519)
  41. default:
  42. return nil, r, ErrInvalidPEMCertificateBanner
  43. }
  44. if err != nil {
  45. return nil, r, err
  46. }
  47. return c, r, nil
  48. }
  49. func marshalCertPublicKeyToPEM(c Certificate) []byte {
  50. if c.IsCA() {
  51. return MarshalSigningPublicKeyToPEM(c.Curve(), c.PublicKey())
  52. } else {
  53. return MarshalPublicKeyToPEM(c.Curve(), c.PublicKey())
  54. }
  55. }
  56. // MarshalPublicKeyToPEM returns a PEM representation of a public key used for ECDH.
  57. // if your public key came from a certificate, prefer Certificate.PublicKeyPEM() if possible, to avoid mistakes!
  58. func MarshalPublicKeyToPEM(curve Curve, b []byte) []byte {
  59. switch curve {
  60. case Curve_CURVE25519:
  61. return pem.EncodeToMemory(&pem.Block{Type: X25519PublicKeyBanner, Bytes: b})
  62. case Curve_P256:
  63. return pem.EncodeToMemory(&pem.Block{Type: P256PublicKeyBanner, Bytes: b})
  64. default:
  65. return nil
  66. }
  67. }
  68. // MarshalSigningPublicKeyToPEM returns a PEM representation of a public key used for signing.
  69. // if your public key came from a certificate, prefer Certificate.PublicKeyPEM() if possible, to avoid mistakes!
  70. func MarshalSigningPublicKeyToPEM(curve Curve, b []byte) []byte {
  71. switch curve {
  72. case Curve_CURVE25519:
  73. return pem.EncodeToMemory(&pem.Block{Type: Ed25519PublicKeyBanner, Bytes: b})
  74. case Curve_P256:
  75. return pem.EncodeToMemory(&pem.Block{Type: P256PublicKeyBanner, Bytes: b})
  76. default:
  77. return nil
  78. }
  79. }
  80. func UnmarshalPublicKeyFromPEM(b []byte) ([]byte, []byte, Curve, error) {
  81. k, r := pem.Decode(b)
  82. if k == nil {
  83. return nil, r, 0, fmt.Errorf("input did not contain a valid PEM encoded block")
  84. }
  85. var expectedLen int
  86. var curve Curve
  87. switch k.Type {
  88. case X25519PublicKeyBanner, Ed25519PublicKeyBanner:
  89. expectedLen = 32
  90. curve = Curve_CURVE25519
  91. case P256PublicKeyBanner, ECDSAP256PublicKeyBanner:
  92. // Uncompressed
  93. expectedLen = 65
  94. curve = Curve_P256
  95. default:
  96. return nil, r, 0, fmt.Errorf("bytes did not contain a proper public key banner")
  97. }
  98. if len(k.Bytes) != expectedLen {
  99. return nil, r, 0, fmt.Errorf("key was not %d bytes, is invalid %s public key", expectedLen, curve)
  100. }
  101. return k.Bytes, r, curve, nil
  102. }
  103. func MarshalPrivateKeyToPEM(curve Curve, b []byte) []byte {
  104. switch curve {
  105. case Curve_CURVE25519:
  106. return pem.EncodeToMemory(&pem.Block{Type: X25519PrivateKeyBanner, Bytes: b})
  107. case Curve_P256:
  108. return pem.EncodeToMemory(&pem.Block{Type: P256PrivateKeyBanner, Bytes: b})
  109. default:
  110. return nil
  111. }
  112. }
  113. func MarshalSigningPrivateKeyToPEM(curve Curve, b []byte) []byte {
  114. switch curve {
  115. case Curve_CURVE25519:
  116. return pem.EncodeToMemory(&pem.Block{Type: Ed25519PrivateKeyBanner, Bytes: b})
  117. case Curve_P256:
  118. return pem.EncodeToMemory(&pem.Block{Type: ECDSAP256PrivateKeyBanner, Bytes: b})
  119. default:
  120. return nil
  121. }
  122. }
  123. // UnmarshalPrivateKeyFromPEM will try to unmarshal the first pem block in a byte array, returning any non
  124. // consumed data or an error on failure
  125. func UnmarshalPrivateKeyFromPEM(b []byte) ([]byte, []byte, Curve, error) {
  126. k, r := pem.Decode(b)
  127. if k == nil {
  128. return nil, r, 0, fmt.Errorf("input did not contain a valid PEM encoded block")
  129. }
  130. var expectedLen int
  131. var curve Curve
  132. switch k.Type {
  133. case X25519PrivateKeyBanner:
  134. expectedLen = 32
  135. curve = Curve_CURVE25519
  136. case P256PrivateKeyBanner:
  137. expectedLen = 32
  138. curve = Curve_P256
  139. default:
  140. return nil, r, 0, fmt.Errorf("bytes did not contain a proper private key banner")
  141. }
  142. if len(k.Bytes) != expectedLen {
  143. return nil, r, 0, fmt.Errorf("key was not %d bytes, is invalid %s private key", expectedLen, curve)
  144. }
  145. return k.Bytes, r, curve, nil
  146. }
  147. func UnmarshalSigningPrivateKeyFromPEM(b []byte) ([]byte, []byte, Curve, error) {
  148. k, r := pem.Decode(b)
  149. if k == nil {
  150. return nil, r, 0, fmt.Errorf("input did not contain a valid PEM encoded block")
  151. }
  152. var curve Curve
  153. switch k.Type {
  154. case EncryptedEd25519PrivateKeyBanner:
  155. return nil, nil, Curve_CURVE25519, ErrPrivateKeyEncrypted
  156. case EncryptedECDSAP256PrivateKeyBanner:
  157. return nil, nil, Curve_P256, ErrPrivateKeyEncrypted
  158. case Ed25519PrivateKeyBanner:
  159. curve = Curve_CURVE25519
  160. if len(k.Bytes) != ed25519.PrivateKeySize {
  161. return nil, r, 0, fmt.Errorf("key was not %d bytes, is invalid Ed25519 private key", ed25519.PrivateKeySize)
  162. }
  163. case ECDSAP256PrivateKeyBanner:
  164. curve = Curve_P256
  165. if len(k.Bytes) != 32 {
  166. return nil, r, 0, fmt.Errorf("key was not 32 bytes, is invalid ECDSA P256 private key")
  167. }
  168. default:
  169. return nil, r, 0, fmt.Errorf("bytes did not contain a proper Ed25519/ECDSA private key banner")
  170. }
  171. return k.Bytes, r, curve, nil
  172. }