ecdsa.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. package jwk
  2. import (
  3. "crypto"
  4. "crypto/ecdsa"
  5. "crypto/elliptic"
  6. "encoding/json"
  7. "fmt"
  8. "math/big"
  9. "github.com/lestrrat/go-jwx/internal/base64"
  10. "github.com/lestrrat/go-jwx/jwa"
  11. pdebug "github.com/lestrrat/go-pdebug"
  12. "github.com/pkg/errors"
  13. )
  14. func newECDSAPublicKey(key *ecdsa.PublicKey) (*ECDSAPublicKey, error) {
  15. if key == nil {
  16. return nil, errors.New(`non-nil ecdsa.PublicKey required`)
  17. }
  18. var hdr StandardHeaders
  19. hdr.Set(KeyTypeKey, jwa.EC)
  20. return &ECDSAPublicKey{
  21. headers: &hdr,
  22. key: key,
  23. }, nil
  24. }
  25. func newECDSAPrivateKey(key *ecdsa.PrivateKey) (*ECDSAPrivateKey, error) {
  26. if key == nil {
  27. return nil, errors.New(`non-nil ecdsa.PrivateKey required`)
  28. }
  29. var hdr StandardHeaders
  30. hdr.Set(KeyTypeKey, jwa.EC)
  31. return &ECDSAPrivateKey{
  32. headers: &hdr,
  33. key: key,
  34. }, nil
  35. }
  36. func (k ECDSAPrivateKey) PublicKey() (*ECDSAPublicKey, error) {
  37. return newECDSAPublicKey(&k.key.PublicKey)
  38. }
  39. // Materialize returns the EC-DSA public key represented by this JWK
  40. func (k ECDSAPublicKey) Materialize() (interface{}, error) {
  41. return k.key, nil
  42. }
  43. func (k ECDSAPublicKey) Curve() jwa.EllipticCurveAlgorithm {
  44. return jwa.EllipticCurveAlgorithm(k.key.Curve.Params().Name)
  45. }
  46. func (k ECDSAPrivateKey) Curve() jwa.EllipticCurveAlgorithm {
  47. return jwa.EllipticCurveAlgorithm(k.key.PublicKey.Curve.Params().Name)
  48. }
  49. func ecdsaThumbprint(hash crypto.Hash, crv, x, y string) []byte {
  50. h := hash.New()
  51. fmt.Fprintf(h, `{"crv":"`)
  52. fmt.Fprintf(h, crv)
  53. fmt.Fprintf(h, `","kty":"EC","x":"`)
  54. fmt.Fprintf(h, x)
  55. fmt.Fprintf(h, `","y":"`)
  56. fmt.Fprintf(h, y)
  57. fmt.Fprintf(h, `"}`)
  58. return h.Sum(nil)
  59. }
  60. // Thumbprint returns the JWK thumbprint using the indicated
  61. // hashing algorithm, according to RFC 7638
  62. func (k ECDSAPublicKey) Thumbprint(hash crypto.Hash) ([]byte, error) {
  63. return ecdsaThumbprint(
  64. hash,
  65. k.key.Curve.Params().Name,
  66. base64.EncodeToString(k.key.X.Bytes()),
  67. base64.EncodeToString(k.key.Y.Bytes()),
  68. ), nil
  69. }
  70. // Thumbprint returns the JWK thumbprint using the indicated
  71. // hashing algorithm, according to RFC 7638
  72. func (k ECDSAPrivateKey) Thumbprint(hash crypto.Hash) ([]byte, error) {
  73. return ecdsaThumbprint(
  74. hash,
  75. k.key.Curve.Params().Name,
  76. base64.EncodeToString(k.key.X.Bytes()),
  77. base64.EncodeToString(k.key.Y.Bytes()),
  78. ), nil
  79. }
  80. // Materialize returns the EC-DSA private key represented by this JWK
  81. func (k ECDSAPrivateKey) Materialize() (interface{}, error) {
  82. return k.key, nil
  83. }
  84. func (k ECDSAPublicKey) MarshalJSON() (buf []byte, err error) {
  85. if pdebug.Enabled {
  86. g := pdebug.Marker("jwk.ECDSAPublicKey.MarshalJSON").BindError(&err)
  87. defer g.End()
  88. }
  89. m := make(map[string]interface{})
  90. if err := k.PopulateMap(m); err != nil {
  91. return nil, errors.Wrap(err, `failed to populate pulibc key values`)
  92. }
  93. return json.Marshal(m)
  94. }
  95. func (k ECDSAPublicKey) PopulateMap(m map[string]interface{}) (err error) {
  96. if pdebug.Enabled {
  97. g := pdebug.Marker("jwk.ECDSAPublicKey.PopulateJSON").BindError(&err)
  98. defer g.End()
  99. }
  100. if err := k.headers.PopulateMap(m); err != nil {
  101. return errors.Wrap(err, `failed to populate header values`)
  102. }
  103. const (
  104. xKey = `x`
  105. yKey = `y`
  106. crvKey = `crv`
  107. )
  108. m[xKey] = base64.EncodeToString(k.key.X.Bytes())
  109. m[yKey] = base64.EncodeToString(k.key.Y.Bytes())
  110. m[crvKey] = k.key.Curve.Params().Name
  111. return nil
  112. }
  113. func (k ECDSAPrivateKey) MarshalJSON() (buf []byte, err error) {
  114. if pdebug.Enabled {
  115. g := pdebug.Marker("jwk.ECDSAPrivateKey.MarshalJSON").BindError(&err)
  116. defer g.End()
  117. }
  118. m := make(map[string]interface{})
  119. if err := k.PopulateMap(m); err != nil {
  120. return nil, errors.Wrap(err, `failed to populate pulibc key values`)
  121. }
  122. return json.Marshal(m)
  123. }
  124. func (k ECDSAPrivateKey) PopulateMap(m map[string]interface{}) (err error) {
  125. if pdebug.Enabled {
  126. g := pdebug.Marker("jwk.ECDSAPrivateKey.PopulateJSON").BindError(&err)
  127. defer g.End()
  128. }
  129. if err := k.headers.PopulateMap(m); err != nil {
  130. return errors.Wrap(err, `failed to populate header values`)
  131. }
  132. pubkey, err := newECDSAPublicKey(&k.key.PublicKey)
  133. if err != nil {
  134. return errors.Wrap(err, `failed to construct public key from private key`)
  135. }
  136. if err := pubkey.PopulateMap(m); err != nil {
  137. return errors.Wrap(err, `failed to populate public key values`)
  138. }
  139. m[`d`] = base64.EncodeToString(k.key.D.Bytes())
  140. return nil
  141. }
  142. func (k *ECDSAPublicKey) UnmarshalJSON(data []byte) (err error) {
  143. if pdebug.Enabled {
  144. g := pdebug.Marker("jwk.ECDSAPublicKey.UnmarshalJSON").BindError(&err)
  145. defer g.End()
  146. }
  147. m := map[string]interface{}{}
  148. if err := json.Unmarshal(data, &m); err != nil {
  149. return errors.Wrap(err, `failed to unmarshal public key`)
  150. }
  151. if err := k.ExtractMap(m); err != nil {
  152. return errors.Wrap(err, `failed to extract data from map`)
  153. }
  154. return nil
  155. }
  156. func (k *ECDSAPublicKey) ExtractMap(m map[string]interface{}) (err error) {
  157. if pdebug.Enabled {
  158. g := pdebug.Marker("jwk.ECDSAPublicKey.ExtractMap").BindError(&err)
  159. defer g.End()
  160. }
  161. const (
  162. xKey = `x`
  163. yKey = `y`
  164. crvKey = `crv`
  165. )
  166. crvname, ok := m[crvKey]
  167. if !ok {
  168. return errors.Errorf(`failed to get required key crv`)
  169. }
  170. delete(m, crvKey)
  171. var crv jwa.EllipticCurveAlgorithm
  172. if err := crv.Accept(crvname); err != nil {
  173. return errors.Wrap(err, `failed to accept value for crv key`)
  174. }
  175. var curve elliptic.Curve
  176. switch crv {
  177. case jwa.P256:
  178. curve = elliptic.P256()
  179. case jwa.P384:
  180. curve = elliptic.P384()
  181. case jwa.P521:
  182. curve = elliptic.P521()
  183. default:
  184. return errors.Errorf(`invalid curve name %s`, crv)
  185. }
  186. xbuf, err := getRequiredKey(m, xKey)
  187. if err != nil {
  188. return errors.Wrapf(err, `failed to get required key %s`, xKey)
  189. }
  190. delete(m, xKey)
  191. ybuf, err := getRequiredKey(m, yKey)
  192. if err != nil {
  193. return errors.Wrapf(err, `failed to get required key %s`, yKey)
  194. }
  195. delete(m, yKey)
  196. var x, y big.Int
  197. x.SetBytes(xbuf)
  198. y.SetBytes(ybuf)
  199. var hdrs StandardHeaders
  200. if err := hdrs.ExtractMap(m); err != nil {
  201. return errors.Wrap(err, `failed to extract header values`)
  202. }
  203. *k = ECDSAPublicKey{
  204. headers: &hdrs,
  205. key: &ecdsa.PublicKey{
  206. Curve: curve,
  207. X: &x,
  208. Y: &y,
  209. },
  210. }
  211. return nil
  212. }
  213. func (k *ECDSAPrivateKey) UnmarshalJSON(data []byte) (err error) {
  214. if pdebug.Enabled {
  215. g := pdebug.Marker("jwk.ECDSAPrivateKey.UnmarshalJSON").BindError(&err)
  216. defer g.End()
  217. }
  218. m := map[string]interface{}{}
  219. if err := json.Unmarshal(data, &m); err != nil {
  220. return errors.Wrap(err, `failed to unmarshal public key`)
  221. }
  222. if err := k.ExtractMap(m); err != nil {
  223. return errors.Wrap(err, `failed to extract data from map`)
  224. }
  225. return nil
  226. }
  227. func (k *ECDSAPrivateKey) ExtractMap(m map[string]interface{}) (err error) {
  228. if pdebug.Enabled {
  229. g := pdebug.Marker("jwk.ECDSAPrivateKey.ExtractMap").BindError(&err)
  230. defer g.End()
  231. }
  232. const (
  233. dKey = `d`
  234. )
  235. dbuf, err := getRequiredKey(m, dKey)
  236. if err != nil {
  237. return errors.Wrapf(err, `failed to get required key %s`, dKey)
  238. }
  239. delete(m, dKey)
  240. var pubkey ECDSAPublicKey
  241. if err := pubkey.ExtractMap(m); err != nil {
  242. return errors.Wrap(err, `failed to extract public key values`)
  243. }
  244. var d big.Int
  245. d.SetBytes(dbuf)
  246. *k = ECDSAPrivateKey{
  247. headers: pubkey.headers,
  248. key: &ecdsa.PrivateKey{
  249. PublicKey: *(pubkey.key),
  250. D: &d,
  251. },
  252. }
  253. pubkey.headers = nil
  254. return nil
  255. }