okp.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. package jwk
  2. import (
  3. "bytes"
  4. "crypto"
  5. "crypto/ed25519"
  6. "fmt"
  7. "github.com/lestrrat-go/blackmagic"
  8. "github.com/lestrrat-go/jwx/internal/base64"
  9. "github.com/lestrrat-go/jwx/jwa"
  10. "github.com/lestrrat-go/jwx/x25519"
  11. "github.com/pkg/errors"
  12. )
  13. func (k *okpPublicKey) FromRaw(rawKeyIf interface{}) error {
  14. k.mu.Lock()
  15. defer k.mu.Unlock()
  16. var crv jwa.EllipticCurveAlgorithm
  17. switch rawKey := rawKeyIf.(type) {
  18. case ed25519.PublicKey:
  19. k.x = rawKey
  20. crv = jwa.Ed25519
  21. k.crv = &crv
  22. case x25519.PublicKey:
  23. k.x = rawKey
  24. crv = jwa.X25519
  25. k.crv = &crv
  26. default:
  27. return errors.Errorf(`unknown key type %T`, rawKeyIf)
  28. }
  29. return nil
  30. }
  31. func (k *okpPrivateKey) FromRaw(rawKeyIf interface{}) error {
  32. k.mu.Lock()
  33. defer k.mu.Unlock()
  34. var crv jwa.EllipticCurveAlgorithm
  35. switch rawKey := rawKeyIf.(type) {
  36. case ed25519.PrivateKey:
  37. k.d = rawKey.Seed()
  38. k.x = rawKey.Public().(ed25519.PublicKey) //nolint:forcetypeassert
  39. crv = jwa.Ed25519
  40. k.crv = &crv
  41. case x25519.PrivateKey:
  42. k.d = rawKey.Seed()
  43. k.x = rawKey.Public().(x25519.PublicKey) //nolint:forcetypeassert
  44. crv = jwa.X25519
  45. k.crv = &crv
  46. default:
  47. return errors.Errorf(`unknown key type %T`, rawKeyIf)
  48. }
  49. return nil
  50. }
  51. func buildOKPPublicKey(alg jwa.EllipticCurveAlgorithm, xbuf []byte) (interface{}, error) {
  52. switch alg {
  53. case jwa.Ed25519:
  54. return ed25519.PublicKey(xbuf), nil
  55. case jwa.X25519:
  56. return x25519.PublicKey(xbuf), nil
  57. default:
  58. return nil, errors.Errorf(`invalid curve algorithm %s`, alg)
  59. }
  60. }
  61. // Raw returns the EC-DSA public key represented by this JWK
  62. func (k *okpPublicKey) Raw(v interface{}) error {
  63. k.mu.RLock()
  64. defer k.mu.RUnlock()
  65. pubk, err := buildOKPPublicKey(k.Crv(), k.x)
  66. if err != nil {
  67. return errors.Wrap(err, `failed to build public key`)
  68. }
  69. return blackmagic.AssignIfCompatible(v, pubk)
  70. }
  71. func buildOKPPrivateKey(alg jwa.EllipticCurveAlgorithm, xbuf []byte, dbuf []byte) (interface{}, error) {
  72. switch alg {
  73. case jwa.Ed25519:
  74. ret := ed25519.NewKeyFromSeed(dbuf)
  75. //nolint:forcetypeassert
  76. if !bytes.Equal(xbuf, ret.Public().(ed25519.PublicKey)) {
  77. return nil, errors.Errorf(`invalid x value given d value`)
  78. }
  79. return ret, nil
  80. case jwa.X25519:
  81. ret, err := x25519.NewKeyFromSeed(dbuf)
  82. if err != nil {
  83. return nil, errors.Wrap(err, `unable to construct x25519 private key from seed`)
  84. }
  85. //nolint:forcetypeassert
  86. if !bytes.Equal(xbuf, ret.Public().(x25519.PublicKey)) {
  87. return nil, errors.Errorf(`invalid x value given d value`)
  88. }
  89. return ret, nil
  90. default:
  91. return nil, errors.Errorf(`invalid curve algorithm %s`, alg)
  92. }
  93. }
  94. func (k *okpPrivateKey) Raw(v interface{}) error {
  95. k.mu.RLock()
  96. defer k.mu.RUnlock()
  97. privk, err := buildOKPPrivateKey(k.Crv(), k.x, k.d)
  98. if err != nil {
  99. return errors.Wrap(err, `failed to build public key`)
  100. }
  101. return blackmagic.AssignIfCompatible(v, privk)
  102. }
  103. func makeOKPPublicKey(v interface {
  104. makePairs() []*HeaderPair
  105. }) (Key, error) {
  106. newKey := NewOKPPublicKey()
  107. // Iterate and copy everything except for the bits that should not be in the public key
  108. for _, pair := range v.makePairs() {
  109. switch pair.Key {
  110. case OKPDKey:
  111. continue
  112. default:
  113. //nolint:forcetypeassert
  114. key := pair.Key.(string)
  115. if err := newKey.Set(key, pair.Value); err != nil {
  116. return nil, errors.Wrapf(err, `failed to set field %q`, key)
  117. }
  118. }
  119. }
  120. return newKey, nil
  121. }
  122. func (k *okpPrivateKey) PublicKey() (Key, error) {
  123. return makeOKPPublicKey(k)
  124. }
  125. func (k *okpPublicKey) PublicKey() (Key, error) {
  126. return makeOKPPublicKey(k)
  127. }
  128. func okpThumbprint(hash crypto.Hash, crv, x string) []byte {
  129. h := hash.New()
  130. fmt.Fprint(h, `{"crv":"`)
  131. fmt.Fprint(h, crv)
  132. fmt.Fprint(h, `","kty":"OKP","x":"`)
  133. fmt.Fprint(h, x)
  134. fmt.Fprint(h, `"}`)
  135. return h.Sum(nil)
  136. }
  137. // Thumbprint returns the JWK thumbprint using the indicated
  138. // hashing algorithm, according to RFC 7638 / 8037
  139. func (k okpPublicKey) Thumbprint(hash crypto.Hash) ([]byte, error) {
  140. k.mu.RLock()
  141. defer k.mu.RUnlock()
  142. return okpThumbprint(
  143. hash,
  144. k.Crv().String(),
  145. base64.EncodeToString(k.x),
  146. ), nil
  147. }
  148. // Thumbprint returns the JWK thumbprint using the indicated
  149. // hashing algorithm, according to RFC 7638 / 8037
  150. func (k okpPrivateKey) Thumbprint(hash crypto.Hash) ([]byte, error) {
  151. k.mu.RLock()
  152. defer k.mu.RUnlock()
  153. return okpThumbprint(
  154. hash,
  155. k.Crv().String(),
  156. base64.EncodeToString(k.x),
  157. ), nil
  158. }