...

Source file src/github.com/lestrrat-go/jwx/jws/eddsa.go

Documentation: github.com/lestrrat-go/jwx/jws

     1  package jws
     2  
     3  import (
     4  	"crypto"
     5  	"crypto/ed25519"
     6  	"crypto/rand"
     7  
     8  	"github.com/lestrrat-go/jwx/internal/keyconv"
     9  	"github.com/lestrrat-go/jwx/jwa"
    10  	"github.com/pkg/errors"
    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, errors.New(`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  		// This fallback exists for cases when jwk.Key was passed, or
    33  		// users gave us a pointer instead of non-pointer, etc.
    34  		var privkey ed25519.PrivateKey
    35  		if err := keyconv.Ed25519PrivateKey(&privkey, key); err != nil {
    36  			return nil, errors.Wrapf(err, `failed to retrieve ed25519.PrivateKey out of %T`, key)
    37  		}
    38  		signer = privkey
    39  	}
    40  	return signer.Sign(rand.Reader, payload, crypto.Hash(0))
    41  }
    42  
    43  type eddsaVerifier struct{}
    44  
    45  func newEdDSAVerifier() Verifier {
    46  	return &eddsaVerifier{}
    47  }
    48  
    49  func (v eddsaVerifier) Verify(payload, signature []byte, key interface{}) (err error) {
    50  	if key == nil {
    51  		return errors.New(`missing public key while verifying payload`)
    52  	}
    53  
    54  	var pubkey ed25519.PublicKey
    55  	signer, ok := key.(crypto.Signer)
    56  	if ok {
    57  		v := signer.Public()
    58  		pubkey, ok = v.(ed25519.PublicKey)
    59  		if !ok {
    60  			return errors.Errorf(`expected crypto.Signer.Public() to return ed25519.PublicKey, but got %T`, v)
    61  		}
    62  	} else {
    63  		if err := keyconv.Ed25519PublicKey(&pubkey, key); err != nil {
    64  			return errors.Wrapf(err, `failed to retrieve ed25519.PublicKey out of %T`, key)
    65  		}
    66  	}
    67  
    68  	if !ed25519.Verify(pubkey, payload, signature) {
    69  		return errors.New(`failed to match EdDSA signature`)
    70  	}
    71  
    72  	return nil
    73  }
    74  

View as plain text