github.com/hyperledger/aries-framework-go@v0.3.2/pkg/doc/jwt/verifier.go (about)

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package jwt
     8  
     9  import (
    10  	"crypto"
    11  	"crypto/rsa"
    12  	"crypto/x509"
    13  	"errors"
    14  	"fmt"
    15  	"strings"
    16  
    17  	"golang.org/x/crypto/ed25519"
    18  
    19  	"github.com/hyperledger/aries-framework-go/component/models/signature/verifier"
    20  	"github.com/hyperledger/aries-framework-go/pkg/doc/jose"
    21  	kmsapi "github.com/hyperledger/aries-framework-go/pkg/kms"
    22  )
    23  
    24  const (
    25  	// signatureEdDSA defines EdDSA alg.
    26  	signatureEdDSA = "EdDSA"
    27  
    28  	// signatureRS256 defines RS256 alg.
    29  	signatureRS256 = "RS256"
    30  )
    31  
    32  // KeyResolver resolves public key based on what and kid.
    33  type KeyResolver interface {
    34  
    35  	// Resolve resolves public key.
    36  	Resolve(what, kid string) (*verifier.PublicKey, error)
    37  }
    38  
    39  // KeyResolverFunc defines function.
    40  type KeyResolverFunc func(what, kid string) (*verifier.PublicKey, error)
    41  
    42  // Resolve resolves public key.
    43  func (k KeyResolverFunc) Resolve(what, kid string) (*verifier.PublicKey, error) {
    44  	return k(what, kid)
    45  }
    46  
    47  // BasicVerifier defines basic Signed JWT verifier based on Issuer Claim and Key ID JOSE Header.
    48  type BasicVerifier struct {
    49  	resolver          KeyResolver
    50  	compositeVerifier *jose.CompositeAlgSigVerifier
    51  }
    52  
    53  // NewVerifier creates a new basic Verifier.
    54  func NewVerifier(resolver KeyResolver) *BasicVerifier {
    55  	// TODO Support pluggable JWS verifiers
    56  	//  (https://github.com/hyperledger/aries-framework-go/issues/1267)
    57  	verifiers := []verifier.SignatureVerifier{
    58  		verifier.NewECDSAES256SignatureVerifier(),
    59  		verifier.NewECDSAES384SignatureVerifier(),
    60  		verifier.NewECDSAES521SignatureVerifier(),
    61  		verifier.NewEd25519SignatureVerifier(),
    62  		verifier.NewECDSASecp256k1SignatureVerifier(),
    63  		verifier.NewRSAPS256SignatureVerifier(),
    64  		verifier.NewRSARS256SignatureVerifier(),
    65  	}
    66  
    67  	algVerifiers := make([]jose.AlgSignatureVerifier, 0, len(verifiers))
    68  	for _, v := range verifiers {
    69  		algVerifiers = append(algVerifiers, jose.AlgSignatureVerifier{
    70  			Alg:      v.Algorithm(),
    71  			Verifier: getVerifier(resolver, v.Verify),
    72  		})
    73  	}
    74  
    75  	compositeVerifier := jose.NewCompositeAlgSigVerifier(algVerifiers[0], algVerifiers[1:]...)
    76  	// TODO ECDSA to support NIST P256 curve
    77  	//  https://github.com/hyperledger/aries-framework-go/issues/1266
    78  
    79  	return &BasicVerifier{resolver: resolver, compositeVerifier: compositeVerifier}
    80  }
    81  
    82  // GetVerifier returns new BasicVerifier based on *verifier.PublicKey.
    83  func GetVerifier(publicKey *verifier.PublicKey) (*BasicVerifier, error) {
    84  	keyType, err := publicKey.JWK.KeyType()
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  
    89  	var v verifier.SignatureVerifier
    90  
    91  	switch keyType {
    92  	case kmsapi.ECDSAP256TypeDER, kmsapi.ECDSAP256TypeIEEEP1363:
    93  		v = verifier.NewECDSAES256SignatureVerifier()
    94  	case kmsapi.ECDSAP384TypeDER, kmsapi.ECDSAP384TypeIEEEP1363:
    95  		v = verifier.NewECDSAES384SignatureVerifier()
    96  	case kmsapi.ECDSAP521TypeDER, kmsapi.ECDSAP521TypeIEEEP1363:
    97  		v = verifier.NewECDSAES521SignatureVerifier()
    98  	case kmsapi.ED25519Type:
    99  		v = verifier.NewEd25519SignatureVerifier()
   100  	case kmsapi.ECDSASecp256k1DER, kmsapi.ECDSASecp256k1TypeIEEEP1363:
   101  		v = verifier.NewECDSASecp256k1SignatureVerifier()
   102  	case kmsapi.RSAPS256Type:
   103  		v = verifier.NewRSAPS256SignatureVerifier()
   104  	case kmsapi.RSARS256Type:
   105  		v = verifier.NewRSARS256SignatureVerifier()
   106  
   107  	default:
   108  		return nil, errors.New("unsupported key type")
   109  	}
   110  
   111  	compositeVerifier := jose.NewCompositeAlgSigVerifier(
   112  		jose.AlgSignatureVerifier{
   113  			Alg:      v.Algorithm(),
   114  			Verifier: getPublicKeyVerifier(publicKey, v),
   115  		},
   116  	)
   117  
   118  	return &BasicVerifier{compositeVerifier: compositeVerifier}, nil
   119  }
   120  
   121  type signatureVerifier func(pubKey *verifier.PublicKey, message, signature []byte) error
   122  
   123  func getVerifier(resolver KeyResolver, signatureVerifier signatureVerifier) jose.SignatureVerifier {
   124  	return jose.SignatureVerifierFunc(func(joseHeaders jose.Headers, payload, signingInput, signature []byte) error {
   125  		return verifySignature(resolver, signatureVerifier, joseHeaders, payload, signingInput, signature)
   126  	})
   127  }
   128  
   129  func getPublicKeyVerifier(publicKey *verifier.PublicKey, v verifier.SignatureVerifier) jose.SignatureVerifier {
   130  	return jose.SignatureVerifierFunc(func(joseHeaders jose.Headers, payload, signingInput, signature []byte) error {
   131  		alg, ok := joseHeaders.Algorithm()
   132  		if !ok {
   133  			return errors.New("'alg' JOSE header is not present")
   134  		}
   135  		if alg != v.Algorithm() {
   136  			return fmt.Errorf("alg is not %s", v.Algorithm())
   137  		}
   138  
   139  		return v.Verify(publicKey, signingInput, signature)
   140  	})
   141  }
   142  
   143  func verifySignature(resolver KeyResolver, signatureVerifier signatureVerifier,
   144  	joseHeaders jose.Headers, _, signingInput, signature []byte) error {
   145  	kid, _ := joseHeaders.KeyID()
   146  
   147  	if !strings.HasPrefix(kid, "did:") {
   148  		return fmt.Errorf("kid %s is not DID", kid)
   149  	}
   150  
   151  	pubKey, err := resolver.Resolve(strings.Split(kid, "#")[0], strings.Split(kid, "#")[1])
   152  	if err != nil {
   153  		return err
   154  	}
   155  
   156  	return signatureVerifier(pubKey, signingInput, signature)
   157  }
   158  
   159  // Verify verifies JSON Web Token. Public key is fetched using Issuer Claim and Key ID JOSE Header.
   160  func (v BasicVerifier) Verify(joseHeaders jose.Headers, payload, signingInput, signature []byte) error {
   161  	return v.compositeVerifier.Verify(joseHeaders, payload, signingInput, signature)
   162  }
   163  
   164  // VerifyEdDSA verifies EdDSA signature.
   165  func VerifyEdDSA(pubKey *verifier.PublicKey, message, signature []byte) error {
   166  	// TODO Use crypto for signing/verification logic
   167  	//  https://github.com/hyperledger/aries-framework-go/issues/1278
   168  	if l := len(pubKey.Value); l != ed25519.PublicKeySize {
   169  		return errors.New("bad ed25519 public key length")
   170  	}
   171  
   172  	if ok := ed25519.Verify(pubKey.Value, message, signature); !ok {
   173  		return errors.New("signature doesn't match")
   174  	}
   175  
   176  	return nil
   177  }
   178  
   179  // VerifyRS256 verifies RS256 signature.
   180  func VerifyRS256(pubKey *verifier.PublicKey, message, signature []byte) error {
   181  	// TODO Use crypto for signing/verification logic
   182  	//  https://github.com/hyperledger/aries-framework-go/issues/1278
   183  	pubKeyRsa, err := x509.ParsePKCS1PublicKey(pubKey.Value)
   184  	if err != nil {
   185  		return errors.New("not *rsa.VerificationMethod public key")
   186  	}
   187  
   188  	hash := crypto.SHA256.New()
   189  
   190  	_, err = hash.Write(message)
   191  	if err != nil {
   192  		return err
   193  	}
   194  
   195  	hashed := hash.Sum(nil)
   196  
   197  	return rsa.VerifyPKCS1v15(pubKeyRsa, crypto.SHA256, hashed, signature)
   198  }