ec_key.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. package libtrust
  2. import (
  3. "crypto"
  4. "crypto/ecdsa"
  5. "crypto/elliptic"
  6. "crypto/rand"
  7. "crypto/x509"
  8. "encoding/json"
  9. "encoding/pem"
  10. "errors"
  11. "fmt"
  12. "io"
  13. "math/big"
  14. )
  15. /*
  16. * EC DSA PUBLIC KEY
  17. */
  18. // ecPublicKey implements a libtrust.PublicKey using elliptic curve digital
  19. // signature algorithms.
  20. type ecPublicKey struct {
  21. *ecdsa.PublicKey
  22. curveName string
  23. signatureAlgorithm *signatureAlgorithm
  24. extended map[string]interface{}
  25. }
  26. func fromECPublicKey(cryptoPublicKey *ecdsa.PublicKey) (*ecPublicKey, error) {
  27. curve := cryptoPublicKey.Curve
  28. switch {
  29. case curve == elliptic.P256():
  30. return &ecPublicKey{cryptoPublicKey, "P-256", es256, map[string]interface{}{}}, nil
  31. case curve == elliptic.P384():
  32. return &ecPublicKey{cryptoPublicKey, "P-384", es384, map[string]interface{}{}}, nil
  33. case curve == elliptic.P521():
  34. return &ecPublicKey{cryptoPublicKey, "P-521", es512, map[string]interface{}{}}, nil
  35. default:
  36. return nil, errors.New("unsupported elliptic curve")
  37. }
  38. }
  39. // KeyType returns the key type for elliptic curve keys, i.e., "EC".
  40. func (k *ecPublicKey) KeyType() string {
  41. return "EC"
  42. }
  43. // CurveName returns the elliptic curve identifier.
  44. // Possible values are "P-256", "P-384", and "P-521".
  45. func (k *ecPublicKey) CurveName() string {
  46. return k.curveName
  47. }
  48. // KeyID returns a distinct identifier which is unique to this Public Key.
  49. func (k *ecPublicKey) KeyID() string {
  50. return keyIDFromCryptoKey(k)
  51. }
  52. func (k *ecPublicKey) String() string {
  53. return fmt.Sprintf("EC Public Key <%s>", k.KeyID())
  54. }
  55. // Verify verifyies the signature of the data in the io.Reader using this
  56. // PublicKey. The alg parameter should identify the digital signature
  57. // algorithm which was used to produce the signature and should be supported
  58. // by this public key. Returns a nil error if the signature is valid.
  59. func (k *ecPublicKey) Verify(data io.Reader, alg string, signature []byte) error {
  60. // For EC keys there is only one supported signature algorithm depending
  61. // on the curve parameters.
  62. if k.signatureAlgorithm.HeaderParam() != alg {
  63. return fmt.Errorf("unable to verify signature: EC Public Key with curve %q does not support signature algorithm %q", k.curveName, alg)
  64. }
  65. // signature is the concatenation of (r, s), base64Url encoded.
  66. sigLength := len(signature)
  67. expectedOctetLength := 2 * ((k.Params().BitSize + 7) >> 3)
  68. if sigLength != expectedOctetLength {
  69. return fmt.Errorf("signature length is %d octets long, should be %d", sigLength, expectedOctetLength)
  70. }
  71. rBytes, sBytes := signature[:sigLength/2], signature[sigLength/2:]
  72. r := new(big.Int).SetBytes(rBytes)
  73. s := new(big.Int).SetBytes(sBytes)
  74. hasher := k.signatureAlgorithm.HashID().New()
  75. _, err := io.Copy(hasher, data)
  76. if err != nil {
  77. return fmt.Errorf("error reading data to sign: %s", err)
  78. }
  79. hash := hasher.Sum(nil)
  80. if !ecdsa.Verify(k.PublicKey, hash, r, s) {
  81. return errors.New("invalid signature")
  82. }
  83. return nil
  84. }
  85. // CryptoPublicKey returns the internal object which can be used as a
  86. // crypto.PublicKey for use with other standard library operations. The type
  87. // is either *rsa.PublicKey or *ecdsa.PublicKey
  88. func (k *ecPublicKey) CryptoPublicKey() crypto.PublicKey {
  89. return k.PublicKey
  90. }
  91. func (k *ecPublicKey) toMap() map[string]interface{} {
  92. jwk := make(map[string]interface{})
  93. for k, v := range k.extended {
  94. jwk[k] = v
  95. }
  96. jwk["kty"] = k.KeyType()
  97. jwk["kid"] = k.KeyID()
  98. jwk["crv"] = k.CurveName()
  99. xBytes := k.X.Bytes()
  100. yBytes := k.Y.Bytes()
  101. octetLength := (k.Params().BitSize + 7) >> 3
  102. // MUST include leading zeros in the output so that x, y are each
  103. // *octetLength* bytes long.
  104. xBuf := make([]byte, octetLength-len(xBytes), octetLength)
  105. yBuf := make([]byte, octetLength-len(yBytes), octetLength)
  106. xBuf = append(xBuf, xBytes...)
  107. yBuf = append(yBuf, yBytes...)
  108. jwk["x"] = joseBase64UrlEncode(xBuf)
  109. jwk["y"] = joseBase64UrlEncode(yBuf)
  110. return jwk
  111. }
  112. // MarshalJSON serializes this Public Key using the JWK JSON serialization format for
  113. // elliptic curve keys.
  114. func (k *ecPublicKey) MarshalJSON() (data []byte, err error) {
  115. return json.Marshal(k.toMap())
  116. }
  117. // PEMBlock serializes this Public Key to DER-encoded PKIX format.
  118. func (k *ecPublicKey) PEMBlock() (*pem.Block, error) {
  119. derBytes, err := x509.MarshalPKIXPublicKey(k.PublicKey)
  120. if err != nil {
  121. return nil, fmt.Errorf("unable to serialize EC PublicKey to DER-encoded PKIX format: %s", err)
  122. }
  123. k.extended["kid"] = k.KeyID() // For display purposes.
  124. return createPemBlock("PUBLIC KEY", derBytes, k.extended)
  125. }
  126. func (k *ecPublicKey) AddExtendedField(field string, value interface{}) {
  127. k.extended[field] = value
  128. }
  129. func (k *ecPublicKey) GetExtendedField(field string) interface{} {
  130. v, ok := k.extended[field]
  131. if !ok {
  132. return nil
  133. }
  134. return v
  135. }
  136. func ecPublicKeyFromMap(jwk map[string]interface{}) (*ecPublicKey, error) {
  137. // JWK key type (kty) has already been determined to be "EC".
  138. // Need to extract 'crv', 'x', 'y', and 'kid' and check for
  139. // consistency.
  140. // Get the curve identifier value.
  141. crv, err := stringFromMap(jwk, "crv")
  142. if err != nil {
  143. return nil, fmt.Errorf("JWK EC Public Key curve identifier: %s", err)
  144. }
  145. var (
  146. curve elliptic.Curve
  147. sigAlg *signatureAlgorithm
  148. )
  149. switch {
  150. case crv == "P-256":
  151. curve = elliptic.P256()
  152. sigAlg = es256
  153. case crv == "P-384":
  154. curve = elliptic.P384()
  155. sigAlg = es384
  156. case crv == "P-521":
  157. curve = elliptic.P521()
  158. sigAlg = es512
  159. default:
  160. return nil, fmt.Errorf("JWK EC Public Key curve identifier not supported: %q\n", crv)
  161. }
  162. // Get the X and Y coordinates for the public key point.
  163. xB64Url, err := stringFromMap(jwk, "x")
  164. if err != nil {
  165. return nil, fmt.Errorf("JWK EC Public Key x-coordinate: %s", err)
  166. }
  167. x, err := parseECCoordinate(xB64Url, curve)
  168. if err != nil {
  169. return nil, fmt.Errorf("JWK EC Public Key x-coordinate: %s", err)
  170. }
  171. yB64Url, err := stringFromMap(jwk, "y")
  172. if err != nil {
  173. return nil, fmt.Errorf("JWK EC Public Key y-coordinate: %s", err)
  174. }
  175. y, err := parseECCoordinate(yB64Url, curve)
  176. if err != nil {
  177. return nil, fmt.Errorf("JWK EC Public Key y-coordinate: %s", err)
  178. }
  179. key := &ecPublicKey{
  180. PublicKey: &ecdsa.PublicKey{Curve: curve, X: x, Y: y},
  181. curveName: crv, signatureAlgorithm: sigAlg,
  182. }
  183. // Key ID is optional too, but if it exists, it should match the key.
  184. _, ok := jwk["kid"]
  185. if ok {
  186. kid, err := stringFromMap(jwk, "kid")
  187. if err != nil {
  188. return nil, fmt.Errorf("JWK EC Public Key ID: %s", err)
  189. }
  190. if kid != key.KeyID() {
  191. return nil, fmt.Errorf("JWK EC Public Key ID does not match: %s", kid)
  192. }
  193. }
  194. key.extended = jwk
  195. return key, nil
  196. }
  197. /*
  198. * EC DSA PRIVATE KEY
  199. */
  200. // ecPrivateKey implements a JWK Private Key using elliptic curve digital signature
  201. // algorithms.
  202. type ecPrivateKey struct {
  203. ecPublicKey
  204. *ecdsa.PrivateKey
  205. }
  206. func fromECPrivateKey(cryptoPrivateKey *ecdsa.PrivateKey) (*ecPrivateKey, error) {
  207. publicKey, err := fromECPublicKey(&cryptoPrivateKey.PublicKey)
  208. if err != nil {
  209. return nil, err
  210. }
  211. return &ecPrivateKey{*publicKey, cryptoPrivateKey}, nil
  212. }
  213. // PublicKey returns the Public Key data associated with this Private Key.
  214. func (k *ecPrivateKey) PublicKey() PublicKey {
  215. return &k.ecPublicKey
  216. }
  217. func (k *ecPrivateKey) String() string {
  218. return fmt.Sprintf("EC Private Key <%s>", k.KeyID())
  219. }
  220. // Sign signs the data read from the io.Reader using a signature algorithm supported
  221. // by the elliptic curve private key. If the specified hashing algorithm is
  222. // supported by this key, that hash function is used to generate the signature
  223. // otherwise the the default hashing algorithm for this key is used. Returns
  224. // the signature and the name of the JWK signature algorithm used, e.g.,
  225. // "ES256", "ES384", "ES512".
  226. func (k *ecPrivateKey) Sign(data io.Reader, hashID crypto.Hash) (signature []byte, alg string, err error) {
  227. // Generate a signature of the data using the internal alg.
  228. // The given hashId is only a suggestion, and since EC keys only support
  229. // on signature/hash algorithm given the curve name, we disregard it for
  230. // the elliptic curve JWK signature implementation.
  231. hasher := k.signatureAlgorithm.HashID().New()
  232. _, err = io.Copy(hasher, data)
  233. if err != nil {
  234. return nil, "", fmt.Errorf("error reading data to sign: %s", err)
  235. }
  236. hash := hasher.Sum(nil)
  237. r, s, err := ecdsa.Sign(rand.Reader, k.PrivateKey, hash)
  238. if err != nil {
  239. return nil, "", fmt.Errorf("error producing signature: %s", err)
  240. }
  241. rBytes, sBytes := r.Bytes(), s.Bytes()
  242. octetLength := (k.ecPublicKey.Params().BitSize + 7) >> 3
  243. // MUST include leading zeros in the output
  244. rBuf := make([]byte, octetLength-len(rBytes), octetLength)
  245. sBuf := make([]byte, octetLength-len(sBytes), octetLength)
  246. rBuf = append(rBuf, rBytes...)
  247. sBuf = append(sBuf, sBytes...)
  248. signature = append(rBuf, sBuf...)
  249. alg = k.signatureAlgorithm.HeaderParam()
  250. return
  251. }
  252. // CryptoPrivateKey returns the internal object which can be used as a
  253. // crypto.PublicKey for use with other standard library operations. The type
  254. // is either *rsa.PublicKey or *ecdsa.PublicKey
  255. func (k *ecPrivateKey) CryptoPrivateKey() crypto.PrivateKey {
  256. return k.PrivateKey
  257. }
  258. func (k *ecPrivateKey) toMap() map[string]interface{} {
  259. jwk := k.ecPublicKey.toMap()
  260. dBytes := k.D.Bytes()
  261. // The length of this octet string MUST be ceiling(log-base-2(n)/8)
  262. // octets (where n is the order of the curve). This is because the private
  263. // key d must be in the interval [1, n-1] so the bitlength of d should be
  264. // no larger than the bitlength of n-1. The easiest way to find the octet
  265. // length is to take bitlength(n-1), add 7 to force a carry, and shift this
  266. // bit sequence right by 3, which is essentially dividing by 8 and adding
  267. // 1 if there is any remainder. Thus, the private key value d should be
  268. // output to (bitlength(n-1)+7)>>3 octets.
  269. n := k.ecPublicKey.Params().N
  270. octetLength := (new(big.Int).Sub(n, big.NewInt(1)).BitLen() + 7) >> 3
  271. // Create a buffer with the necessary zero-padding.
  272. dBuf := make([]byte, octetLength-len(dBytes), octetLength)
  273. dBuf = append(dBuf, dBytes...)
  274. jwk["d"] = joseBase64UrlEncode(dBuf)
  275. return jwk
  276. }
  277. // MarshalJSON serializes this Private Key using the JWK JSON serialization format for
  278. // elliptic curve keys.
  279. func (k *ecPrivateKey) MarshalJSON() (data []byte, err error) {
  280. return json.Marshal(k.toMap())
  281. }
  282. // PEMBlock serializes this Private Key to DER-encoded PKIX format.
  283. func (k *ecPrivateKey) PEMBlock() (*pem.Block, error) {
  284. derBytes, err := x509.MarshalECPrivateKey(k.PrivateKey)
  285. if err != nil {
  286. return nil, fmt.Errorf("unable to serialize EC PrivateKey to DER-encoded PKIX format: %s", err)
  287. }
  288. k.extended["keyID"] = k.KeyID() // For display purposes.
  289. return createPemBlock("EC PRIVATE KEY", derBytes, k.extended)
  290. }
  291. func ecPrivateKeyFromMap(jwk map[string]interface{}) (*ecPrivateKey, error) {
  292. dB64Url, err := stringFromMap(jwk, "d")
  293. if err != nil {
  294. return nil, fmt.Errorf("JWK EC Private Key: %s", err)
  295. }
  296. // JWK key type (kty) has already been determined to be "EC".
  297. // Need to extract the public key information, then extract the private
  298. // key value 'd'.
  299. publicKey, err := ecPublicKeyFromMap(jwk)
  300. if err != nil {
  301. return nil, err
  302. }
  303. d, err := parseECPrivateParam(dB64Url, publicKey.Curve)
  304. if err != nil {
  305. return nil, fmt.Errorf("JWK EC Private Key d-param: %s", err)
  306. }
  307. key := &ecPrivateKey{
  308. ecPublicKey: *publicKey,
  309. PrivateKey: &ecdsa.PrivateKey{
  310. PublicKey: *publicKey.PublicKey,
  311. D: d,
  312. },
  313. }
  314. return key, nil
  315. }
  316. /*
  317. * Key Generation Functions.
  318. */
  319. func generateECPrivateKey(curve elliptic.Curve) (k *ecPrivateKey, err error) {
  320. k = new(ecPrivateKey)
  321. k.PrivateKey, err = ecdsa.GenerateKey(curve, rand.Reader)
  322. if err != nil {
  323. return nil, err
  324. }
  325. k.ecPublicKey.PublicKey = &k.PrivateKey.PublicKey
  326. k.extended = make(map[string]interface{})
  327. return
  328. }
  329. // GenerateECP256PrivateKey generates a key pair using elliptic curve P-256.
  330. func GenerateECP256PrivateKey() (PrivateKey, error) {
  331. k, err := generateECPrivateKey(elliptic.P256())
  332. if err != nil {
  333. return nil, fmt.Errorf("error generating EC P-256 key: %s", err)
  334. }
  335. k.curveName = "P-256"
  336. k.signatureAlgorithm = es256
  337. return k, nil
  338. }
  339. // GenerateECP384PrivateKey generates a key pair using elliptic curve P-384.
  340. func GenerateECP384PrivateKey() (PrivateKey, error) {
  341. k, err := generateECPrivateKey(elliptic.P384())
  342. if err != nil {
  343. return nil, fmt.Errorf("error generating EC P-384 key: %s", err)
  344. }
  345. k.curveName = "P-384"
  346. k.signatureAlgorithm = es384
  347. return k, nil
  348. }
  349. // GenerateECP521PrivateKey generates aß key pair using elliptic curve P-521.
  350. func GenerateECP521PrivateKey() (PrivateKey, error) {
  351. k, err := generateECPrivateKey(elliptic.P521())
  352. if err != nil {
  353. return nil, fmt.Errorf("error generating EC P-521 key: %s", err)
  354. }
  355. k.curveName = "P-521"
  356. k.signatureAlgorithm = es512
  357. return k, nil
  358. }