key.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. package libtrust
  2. import (
  3. "crypto"
  4. "crypto/ecdsa"
  5. "crypto/rsa"
  6. "crypto/x509"
  7. "encoding/json"
  8. "encoding/pem"
  9. "errors"
  10. "fmt"
  11. "io"
  12. )
  13. // PublicKey is a generic interface for a Public Key.
  14. type PublicKey interface {
  15. // KeyType returns the key type for this key. For elliptic curve keys,
  16. // this value should be "EC". For RSA keys, this value should be "RSA".
  17. KeyType() string
  18. // KeyID returns a distinct identifier which is unique to this Public Key.
  19. // The format generated by this library is a base32 encoding of a 240 bit
  20. // hash of the public key data divided into 12 groups like so:
  21. // ABCD:EFGH:IJKL:MNOP:QRST:UVWX:YZ23:4567:ABCD:EFGH:IJKL:MNOP
  22. KeyID() string
  23. // Verify verifyies the signature of the data in the io.Reader using this
  24. // Public Key. The alg parameter should identify the digital signature
  25. // algorithm which was used to produce the signature and should be
  26. // supported by this public key. Returns a nil error if the signature
  27. // is valid.
  28. Verify(data io.Reader, alg string, signature []byte) error
  29. // CryptoPublicKey returns the internal object which can be used as a
  30. // crypto.PublicKey for use with other standard library operations. The type
  31. // is either *rsa.PublicKey or *ecdsa.PublicKey
  32. CryptoPublicKey() crypto.PublicKey
  33. // These public keys can be serialized to the standard JSON encoding for
  34. // JSON Web Keys. See section 6 of the IETF draft RFC for JOSE JSON Web
  35. // Algorithms.
  36. MarshalJSON() ([]byte, error)
  37. // These keys can also be serialized to the standard PEM encoding.
  38. PEMBlock() (*pem.Block, error)
  39. // The string representation of a key is its key type and ID.
  40. String() string
  41. AddExtendedField(string, interface{})
  42. GetExtendedField(string) interface{}
  43. }
  44. // PrivateKey is a generic interface for a Private Key.
  45. type PrivateKey interface {
  46. // A PrivateKey contains all fields and methods of a PublicKey of the
  47. // same type. The MarshalJSON method also outputs the private key as a
  48. // JSON Web Key, and the PEMBlock method outputs the private key as a
  49. // PEM block.
  50. PublicKey
  51. // PublicKey returns the PublicKey associated with this PrivateKey.
  52. PublicKey() PublicKey
  53. // Sign signs the data read from the io.Reader using a signature algorithm
  54. // supported by the private key. If the specified hashing algorithm is
  55. // supported by this key, that hash function is used to generate the
  56. // signature otherwise the the default hashing algorithm for this key is
  57. // used. Returns the signature and identifier of the algorithm used.
  58. Sign(data io.Reader, hashID crypto.Hash) (signature []byte, alg string, err error)
  59. // CryptoPrivateKey returns the internal object which can be used as a
  60. // crypto.PublicKey for use with other standard library operations. The
  61. // type is either *rsa.PublicKey or *ecdsa.PublicKey
  62. CryptoPrivateKey() crypto.PrivateKey
  63. }
  64. // FromCryptoPublicKey returns a libtrust PublicKey representation of the given
  65. // *ecdsa.PublicKey or *rsa.PublicKey. Returns a non-nil error when the given
  66. // key is of an unsupported type.
  67. func FromCryptoPublicKey(cryptoPublicKey crypto.PublicKey) (PublicKey, error) {
  68. switch cryptoPublicKey := cryptoPublicKey.(type) {
  69. case *ecdsa.PublicKey:
  70. return fromECPublicKey(cryptoPublicKey)
  71. case *rsa.PublicKey:
  72. return fromRSAPublicKey(cryptoPublicKey), nil
  73. default:
  74. return nil, fmt.Errorf("public key type %T is not supported", cryptoPublicKey)
  75. }
  76. }
  77. // FromCryptoPrivateKey returns a libtrust PrivateKey representation of the given
  78. // *ecdsa.PrivateKey or *rsa.PrivateKey. Returns a non-nil error when the given
  79. // key is of an unsupported type.
  80. func FromCryptoPrivateKey(cryptoPrivateKey crypto.PrivateKey) (PrivateKey, error) {
  81. switch cryptoPrivateKey := cryptoPrivateKey.(type) {
  82. case *ecdsa.PrivateKey:
  83. return fromECPrivateKey(cryptoPrivateKey)
  84. case *rsa.PrivateKey:
  85. return fromRSAPrivateKey(cryptoPrivateKey), nil
  86. default:
  87. return nil, fmt.Errorf("private key type %T is not supported", cryptoPrivateKey)
  88. }
  89. }
  90. // UnmarshalPublicKeyPEM parses the PEM encoded data and returns a libtrust
  91. // PublicKey or an error if there is a problem with the encoding.
  92. func UnmarshalPublicKeyPEM(data []byte) (PublicKey, error) {
  93. pemBlock, _ := pem.Decode(data)
  94. if pemBlock == nil {
  95. return nil, errors.New("unable to find PEM encoded data")
  96. } else if pemBlock.Type != "PUBLIC KEY" {
  97. return nil, fmt.Errorf("unable to get PublicKey from PEM type: %s", pemBlock.Type)
  98. }
  99. return pubKeyFromPEMBlock(pemBlock)
  100. }
  101. // UnmarshalPublicKeyPEMBundle parses the PEM encoded data as a bundle of
  102. // PEM blocks appended one after the other and returns a slice of PublicKey
  103. // objects that it finds.
  104. func UnmarshalPublicKeyPEMBundle(data []byte) ([]PublicKey, error) {
  105. pubKeys := []PublicKey{}
  106. for {
  107. var pemBlock *pem.Block
  108. pemBlock, data = pem.Decode(data)
  109. if pemBlock == nil {
  110. break
  111. } else if pemBlock.Type != "PUBLIC KEY" {
  112. return nil, fmt.Errorf("unable to get PublicKey from PEM type: %s", pemBlock.Type)
  113. }
  114. pubKey, err := pubKeyFromPEMBlock(pemBlock)
  115. if err != nil {
  116. return nil, err
  117. }
  118. pubKeys = append(pubKeys, pubKey)
  119. }
  120. return pubKeys, nil
  121. }
  122. // UnmarshalPrivateKeyPEM parses the PEM encoded data and returns a libtrust
  123. // PrivateKey or an error if there is a problem with the encoding.
  124. func UnmarshalPrivateKeyPEM(data []byte) (PrivateKey, error) {
  125. pemBlock, _ := pem.Decode(data)
  126. if pemBlock == nil {
  127. return nil, errors.New("unable to find PEM encoded data")
  128. }
  129. var key PrivateKey
  130. switch {
  131. case pemBlock.Type == "RSA PRIVATE KEY":
  132. rsaPrivateKey, err := x509.ParsePKCS1PrivateKey(pemBlock.Bytes)
  133. if err != nil {
  134. return nil, fmt.Errorf("unable to decode RSA Private Key PEM data: %s", err)
  135. }
  136. key = fromRSAPrivateKey(rsaPrivateKey)
  137. case pemBlock.Type == "EC PRIVATE KEY":
  138. ecPrivateKey, err := x509.ParseECPrivateKey(pemBlock.Bytes)
  139. if err != nil {
  140. return nil, fmt.Errorf("unable to decode EC Private Key PEM data: %s", err)
  141. }
  142. key, err = fromECPrivateKey(ecPrivateKey)
  143. if err != nil {
  144. return nil, err
  145. }
  146. default:
  147. return nil, fmt.Errorf("unable to get PrivateKey from PEM type: %s", pemBlock.Type)
  148. }
  149. addPEMHeadersToKey(pemBlock, key.PublicKey())
  150. return key, nil
  151. }
  152. // UnmarshalPublicKeyJWK unmarshals the given JSON Web Key into a generic
  153. // Public Key to be used with libtrust.
  154. func UnmarshalPublicKeyJWK(data []byte) (PublicKey, error) {
  155. jwk := make(map[string]interface{})
  156. err := json.Unmarshal(data, &jwk)
  157. if err != nil {
  158. return nil, fmt.Errorf(
  159. "decoding JWK Public Key JSON data: %s\n", err,
  160. )
  161. }
  162. // Get the Key Type value.
  163. kty, err := stringFromMap(jwk, "kty")
  164. if err != nil {
  165. return nil, fmt.Errorf("JWK Public Key type: %s", err)
  166. }
  167. switch {
  168. case kty == "EC":
  169. // Call out to unmarshal EC public key.
  170. return ecPublicKeyFromMap(jwk)
  171. case kty == "RSA":
  172. // Call out to unmarshal RSA public key.
  173. return rsaPublicKeyFromMap(jwk)
  174. default:
  175. return nil, fmt.Errorf(
  176. "JWK Public Key type not supported: %q\n", kty,
  177. )
  178. }
  179. }
  180. // UnmarshalPublicKeyJWKSet parses the JSON encoded data as a JSON Web Key Set
  181. // and returns a slice of Public Key objects.
  182. func UnmarshalPublicKeyJWKSet(data []byte) ([]PublicKey, error) {
  183. rawKeys, err := loadJSONKeySetRaw(data)
  184. if err != nil {
  185. return nil, err
  186. }
  187. pubKeys := make([]PublicKey, 0, len(rawKeys))
  188. for _, rawKey := range rawKeys {
  189. pubKey, err := UnmarshalPublicKeyJWK(rawKey)
  190. if err != nil {
  191. return nil, err
  192. }
  193. pubKeys = append(pubKeys, pubKey)
  194. }
  195. return pubKeys, nil
  196. }
  197. // UnmarshalPrivateKeyJWK unmarshals the given JSON Web Key into a generic
  198. // Private Key to be used with libtrust.
  199. func UnmarshalPrivateKeyJWK(data []byte) (PrivateKey, error) {
  200. jwk := make(map[string]interface{})
  201. err := json.Unmarshal(data, &jwk)
  202. if err != nil {
  203. return nil, fmt.Errorf(
  204. "decoding JWK Private Key JSON data: %s\n", err,
  205. )
  206. }
  207. // Get the Key Type value.
  208. kty, err := stringFromMap(jwk, "kty")
  209. if err != nil {
  210. return nil, fmt.Errorf("JWK Private Key type: %s", err)
  211. }
  212. switch {
  213. case kty == "EC":
  214. // Call out to unmarshal EC private key.
  215. return ecPrivateKeyFromMap(jwk)
  216. case kty == "RSA":
  217. // Call out to unmarshal RSA private key.
  218. return rsaPrivateKeyFromMap(jwk)
  219. default:
  220. return nil, fmt.Errorf(
  221. "JWK Private Key type not supported: %q\n", kty,
  222. )
  223. }
  224. }