eddsa.go 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. package jws
  2. import (
  3. "crypto"
  4. "crypto/ed25519"
  5. "crypto/rand"
  6. "github.com/lestrrat-go/jwx/internal/keyconv"
  7. "github.com/lestrrat-go/jwx/jwa"
  8. "github.com/pkg/errors"
  9. )
  10. type eddsaSigner struct{}
  11. func newEdDSASigner() Signer {
  12. return &eddsaSigner{}
  13. }
  14. func (s eddsaSigner) Algorithm() jwa.SignatureAlgorithm {
  15. return jwa.EdDSA
  16. }
  17. func (s eddsaSigner) Sign(payload []byte, key interface{}) ([]byte, error) {
  18. if key == nil {
  19. return nil, errors.New(`missing private key while signing payload`)
  20. }
  21. // The ed25519.PrivateKey object implements crypto.Signer, so we should
  22. // simply accept a crypto.Signer here.
  23. signer, ok := key.(crypto.Signer)
  24. if !ok {
  25. // This fallback exists for cases when jwk.Key was passed, or
  26. // users gave us a pointer instead of non-pointer, etc.
  27. var privkey ed25519.PrivateKey
  28. if err := keyconv.Ed25519PrivateKey(&privkey, key); err != nil {
  29. return nil, errors.Wrapf(err, `failed to retrieve ed25519.PrivateKey out of %T`, key)
  30. }
  31. signer = privkey
  32. }
  33. return signer.Sign(rand.Reader, payload, crypto.Hash(0))
  34. }
  35. type eddsaVerifier struct{}
  36. func newEdDSAVerifier() Verifier {
  37. return &eddsaVerifier{}
  38. }
  39. func (v eddsaVerifier) Verify(payload, signature []byte, key interface{}) (err error) {
  40. if key == nil {
  41. return errors.New(`missing public key while verifying payload`)
  42. }
  43. var pubkey ed25519.PublicKey
  44. signer, ok := key.(crypto.Signer)
  45. if ok {
  46. v := signer.Public()
  47. pubkey, ok = v.(ed25519.PublicKey)
  48. if !ok {
  49. return errors.Errorf(`expected crypto.Signer.Public() to return ed25519.PublicKey, but got %T`, v)
  50. }
  51. } else {
  52. if err := keyconv.Ed25519PublicKey(&pubkey, key); err != nil {
  53. return errors.Wrapf(err, `failed to retrieve ed25519.PublicKey out of %T`, key)
  54. }
  55. }
  56. if !ed25519.Verify(pubkey, payload, signature) {
  57. return errors.New(`failed to match EdDSA signature`)
  58. }
  59. return nil
  60. }