pki.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. package pki
  2. import (
  3. "crypto/x509/pkix"
  4. "encoding/asn1"
  5. "encoding/pem"
  6. "errors"
  7. "strings"
  8. "github.com/cloudflare/circl/sign"
  9. "github.com/cloudflare/circl/sign/schemes"
  10. )
  11. var (
  12. allSchemesByOID map[string]sign.Scheme
  13. allSchemesByTLS map[uint]sign.Scheme
  14. )
  15. type pkixPrivKey struct {
  16. Version int
  17. Algorithm pkix.AlgorithmIdentifier
  18. PrivateKey []byte
  19. }
  20. func init() {
  21. allSchemesByOID = make(map[string]sign.Scheme)
  22. allSchemesByTLS = make(map[uint]sign.Scheme)
  23. for _, scheme := range schemes.All() {
  24. if cert, ok := scheme.(CertificateScheme); ok {
  25. allSchemesByOID[cert.Oid().String()] = scheme
  26. }
  27. if tlsScheme, ok := scheme.(TLSScheme); ok {
  28. allSchemesByTLS[tlsScheme.TLSIdentifier()] = scheme
  29. }
  30. }
  31. }
  32. func SchemeByOid(oid asn1.ObjectIdentifier) sign.Scheme { return allSchemesByOID[oid.String()] }
  33. func SchemeByTLSID(id uint) sign.Scheme { return allSchemesByTLS[id] }
  34. // Additional methods when the signature scheme is supported in X509.
  35. type CertificateScheme interface {
  36. // Return the appropriate OIDs for this instance. It is implicitly
  37. // assumed that the encoding is simple: e.g. uses the same OID for
  38. // signature and public key like Ed25519.
  39. Oid() asn1.ObjectIdentifier
  40. }
  41. // Additional methods when the signature scheme is supported in TLS.
  42. type TLSScheme interface {
  43. TLSIdentifier() uint
  44. }
  45. func UnmarshalPEMPublicKey(data []byte) (sign.PublicKey, error) {
  46. block, rest := pem.Decode(data)
  47. if len(rest) != 0 {
  48. return nil, errors.New("trailing data")
  49. }
  50. if !strings.HasSuffix(block.Type, "PUBLIC KEY") {
  51. return nil, errors.New("pem block type is not public key")
  52. }
  53. return UnmarshalPKIXPublicKey(block.Bytes)
  54. }
  55. func UnmarshalPKIXPublicKey(data []byte) (sign.PublicKey, error) {
  56. var pkix struct {
  57. Raw asn1.RawContent
  58. Algorithm pkix.AlgorithmIdentifier
  59. PublicKey asn1.BitString
  60. }
  61. if rest, err := asn1.Unmarshal(data, &pkix); err != nil {
  62. return nil, err
  63. } else if len(rest) != 0 {
  64. return nil, errors.New("trailing data")
  65. }
  66. scheme := SchemeByOid(pkix.Algorithm.Algorithm)
  67. if scheme == nil {
  68. return nil, errors.New("unsupported public key algorithm")
  69. }
  70. return scheme.UnmarshalBinaryPublicKey(pkix.PublicKey.RightAlign())
  71. }
  72. func UnmarshalPEMPrivateKey(data []byte) (sign.PrivateKey, error) {
  73. block, rest := pem.Decode(data)
  74. if len(rest) != 0 {
  75. return nil, errors.New("trailing")
  76. }
  77. if !strings.HasSuffix(block.Type, "PRIVATE KEY") {
  78. return nil, errors.New("pem block type is not private key")
  79. }
  80. return UnmarshalPKIXPrivateKey(block.Bytes)
  81. }
  82. func UnmarshalPKIXPrivateKey(data []byte) (sign.PrivateKey, error) {
  83. var pkix pkixPrivKey
  84. if rest, err := asn1.Unmarshal(data, &pkix); err != nil {
  85. return nil, err
  86. } else if len(rest) != 0 {
  87. return nil, errors.New("trailing data")
  88. }
  89. scheme := SchemeByOid(pkix.Algorithm.Algorithm)
  90. if scheme == nil {
  91. return nil, errors.New("unsupported public key algorithm")
  92. }
  93. var sk []byte
  94. if rest, err := asn1.Unmarshal(pkix.PrivateKey, &sk); err != nil {
  95. return nil, err
  96. } else if len(rest) > 0 {
  97. return nil, errors.New("trailing data")
  98. }
  99. return scheme.UnmarshalBinaryPrivateKey(sk)
  100. }
  101. func MarshalPEMPublicKey(pk sign.PublicKey) ([]byte, error) {
  102. data, err := MarshalPKIXPublicKey(pk)
  103. if err != nil {
  104. return nil, err
  105. }
  106. str := pem.EncodeToMemory(&pem.Block{
  107. Type: "PUBLIC KEY",
  108. Bytes: data,
  109. })
  110. return str, nil
  111. }
  112. func MarshalPKIXPublicKey(pk sign.PublicKey) ([]byte, error) {
  113. data, err := pk.MarshalBinary()
  114. if err != nil {
  115. return nil, err
  116. }
  117. scheme := pk.Scheme()
  118. return asn1.Marshal(struct {
  119. pkix.AlgorithmIdentifier
  120. asn1.BitString
  121. }{
  122. pkix.AlgorithmIdentifier{
  123. Algorithm: scheme.(CertificateScheme).Oid(),
  124. },
  125. asn1.BitString{
  126. Bytes: data,
  127. BitLength: len(data) * 8,
  128. },
  129. })
  130. }
  131. func MarshalPEMPrivateKey(sk sign.PrivateKey) ([]byte, error) {
  132. data, err := MarshalPKIXPrivateKey(sk)
  133. if err != nil {
  134. return nil, err
  135. }
  136. str := pem.EncodeToMemory(&pem.Block{
  137. Type: sk.Scheme().Name() + " PRIVATE KEY",
  138. Bytes: data,
  139. },
  140. )
  141. return str, nil
  142. }
  143. func MarshalPKIXPrivateKey(sk sign.PrivateKey) ([]byte, error) {
  144. data, err := sk.MarshalBinary()
  145. if err != nil {
  146. return nil, err
  147. }
  148. data, err = asn1.Marshal(data)
  149. if err != nil {
  150. return nil, err
  151. }
  152. scheme := sk.Scheme()
  153. return asn1.Marshal(pkixPrivKey{
  154. 0,
  155. pkix.AlgorithmIdentifier{
  156. Algorithm: scheme.(CertificateScheme).Oid(),
  157. },
  158. data,
  159. })
  160. }