pem.go 4.8 KB

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