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