github.com/trustbloc/kms-go@v1.1.2/doc/jose/jwk/jwksupport/jwk.go (about)

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package jwksupport
     8  
     9  import (
    10  	"crypto/ecdsa"
    11  	"crypto/ed25519"
    12  	"crypto/elliptic"
    13  	"crypto/rsa"
    14  	"crypto/x509"
    15  	"crypto/x509/pkix"
    16  	"encoding/asn1"
    17  	"encoding/json"
    18  	"errors"
    19  	"fmt"
    20  	"math/big"
    21  
    22  	"github.com/btcsuite/btcd/btcec/v2"
    23  	"github.com/go-jose/go-jose/v3"
    24  	"github.com/trustbloc/bbs-signature-go/bbs12381g2pub"
    25  
    26  	"github.com/trustbloc/kms-go/doc/jose/jwk"
    27  	cryptoapi "github.com/trustbloc/kms-go/spi/crypto"
    28  	"github.com/trustbloc/kms-go/spi/kms"
    29  )
    30  
    31  const (
    32  	ecKty          = "EC"
    33  	okpKty         = "OKP"
    34  	x25519Crv      = "X25519"
    35  	bls12381G2Crv  = "BLS12381_G2"
    36  	bls12381G2Size = 96
    37  )
    38  
    39  // JWKFromKey creates a JWK from an opaque key struct.
    40  // It's e.g. *ecdsa.PublicKey, *ecdsa.PrivateKey, ed25519.VerificationMethod, *bbs12381g2pub.PrivateKey or
    41  // *bbs12381g2pub.PublicKey.
    42  func JWKFromKey(opaqueKey interface{}) (*jwk.JWK, error) {
    43  	key := &jwk.JWK{
    44  		JSONWebKey: jose.JSONWebKey{
    45  			Key: opaqueKey,
    46  		},
    47  	}
    48  
    49  	// marshal/unmarshal to get all JWK's fields other than Key filled.
    50  	keyBytes, err := key.MarshalJSON()
    51  	if err != nil {
    52  		return nil, fmt.Errorf("create JWK: %w", err)
    53  	}
    54  
    55  	err = key.UnmarshalJSON(keyBytes)
    56  	if err != nil {
    57  		return nil, fmt.Errorf("create JWK: %w", err)
    58  	}
    59  
    60  	return key, nil
    61  }
    62  
    63  // PubKeyBytesToKey creates an opaque key struct from the given public key bytes.
    64  // It's e.g. *ecdsa.PublicKey, *ecdsa.PrivateKey, ed25519.VerificationMethod, *bbs12381g2pub.PrivateKey or
    65  // *bbs12381g2pub.PublicKey.
    66  func PubKeyBytesToKey(bytes []byte, keyType kms.KeyType) (interface{}, error) { // nolint:gocyclo,funlen
    67  	switch keyType {
    68  	case kms.ED25519Type:
    69  		return ed25519.PublicKey(bytes), nil
    70  	case kms.X25519ECDHKWType:
    71  		return bytes, nil
    72  	case kms.BLS12381G2Type:
    73  		return bbs12381g2pub.UnmarshalPublicKey(bytes)
    74  	case kms.ECDSAP256TypeIEEEP1363, kms.ECDSAP384TypeIEEEP1363, kms.ECDSAP521TypeIEEEP1363:
    75  		crv := getECDSACurve(keyType)
    76  		x, y := elliptic.Unmarshal(crv, bytes)
    77  
    78  		return &ecdsa.PublicKey{
    79  			Curve: crv,
    80  			X:     x,
    81  			Y:     y,
    82  		}, nil
    83  	case kms.ECDSASecp256k1TypeIEEEP1363:
    84  		pubKey, err := btcec.ParsePubKey(bytes)
    85  		if err != nil {
    86  			return nil, fmt.Errorf("failed to parse ecdsa secp 256k1 in IEEEP1363 format: %w", err)
    87  		}
    88  
    89  		return pubKey.ToECDSA(), nil
    90  
    91  	case kms.ECDSAP256TypeDER, kms.ECDSAP384TypeDER, kms.ECDSAP521TypeDER:
    92  		pubKey, err := x509.ParsePKIXPublicKey(bytes)
    93  		if err != nil {
    94  			return nil, fmt.Errorf("failed to parse ecdsa key in DER format: %w", err)
    95  		}
    96  
    97  		ecKey, ok := pubKey.(*ecdsa.PublicKey)
    98  		if !ok {
    99  			return nil, errors.New("invalid EC key")
   100  		}
   101  
   102  		return ecKey, nil
   103  	case kms.RSARS256, kms.RSAPS256:
   104  		pubKeyRsa, err := x509.ParsePKIXPublicKey(bytes)
   105  		if err != nil {
   106  			return nil, errors.New("rsa: invalid public key")
   107  		}
   108  
   109  		return pubKeyRsa, nil
   110  	case kms.ECDSASecp256k1TypeDER:
   111  		return parseSecp256k1DER(bytes)
   112  	case kms.NISTP256ECDHKWType, kms.NISTP384ECDHKWType, kms.NISTP521ECDHKWType:
   113  		crv := getECDSACurve(keyType)
   114  		pubKey := &cryptoapi.PublicKey{}
   115  
   116  		err := json.Unmarshal(bytes, pubKey)
   117  		if err != nil {
   118  			return nil, err
   119  		}
   120  
   121  		ecdsaKey := &ecdsa.PublicKey{
   122  			Curve: crv,
   123  			X:     new(big.Int).SetBytes(pubKey.X),
   124  			Y:     new(big.Int).SetBytes(pubKey.Y),
   125  		}
   126  
   127  		return ecdsaKey, nil
   128  	default:
   129  		return nil, fmt.Errorf("invalid key type: %s", keyType)
   130  	}
   131  }
   132  
   133  // JWKFromX25519Key is similar to JWKFromKey but is specific to X25519 keys when using a public key as raw []byte.
   134  // This builder function presets the curve and key type in the JWK.
   135  // Using JWKFromKey for X25519 raw keys will not have these fields set and will not provide the right JWK output.
   136  func JWKFromX25519Key(pubKey []byte) (*jwk.JWK, error) {
   137  	key := &jwk.JWK{
   138  		JSONWebKey: jose.JSONWebKey{
   139  			Key: pubKey,
   140  		},
   141  		Crv: x25519Crv,
   142  		Kty: okpKty,
   143  	}
   144  
   145  	// marshal/unmarshal to get all JWK's fields other than Key filled.
   146  	keyBytes, err := key.MarshalJSON()
   147  	if err != nil {
   148  		return nil, fmt.Errorf("create JWK: %w", err)
   149  	}
   150  
   151  	err = key.UnmarshalJSON(keyBytes)
   152  	if err != nil {
   153  		return nil, fmt.Errorf("create JWK: %w", err)
   154  	}
   155  
   156  	return key, nil
   157  }
   158  
   159  // PubKeyBytesToJWK converts marshalled bytes of keyType into JWK.
   160  func PubKeyBytesToJWK(bytes []byte, keyType kms.KeyType) (*jwk.JWK, error) {
   161  	switch keyType {
   162  	case kms.ED25519Type:
   163  		return &jwk.JWK{
   164  			JSONWebKey: jose.JSONWebKey{
   165  				Key: ed25519.PublicKey(bytes),
   166  			},
   167  			Kty: "OKP",
   168  			Crv: "Ed25519",
   169  		}, nil
   170  	case kms.X25519ECDHKWType:
   171  		return JWKFromX25519Key(bytes)
   172  	case kms.BLS12381G2Type,
   173  		kms.ECDSASecp256k1TypeIEEEP1363, kms.ECDSASecp256k1TypeDER,
   174  		kms.ECDSAP256TypeIEEEP1363, kms.ECDSAP384TypeIEEEP1363, kms.ECDSAP521TypeIEEEP1363,
   175  		kms.ECDSAP256TypeDER, kms.ECDSAP384TypeDER, kms.ECDSAP521TypeDER,
   176  		kms.NISTP256ECDHKWType, kms.NISTP384ECDHKWType, kms.NISTP521ECDHKWType,
   177  		kms.RSARS256, kms.RSAPS256:
   178  		key, err := PubKeyBytesToKey(bytes, keyType)
   179  		if err != nil {
   180  			return nil, err
   181  		}
   182  
   183  		return JWKFromKey(key)
   184  	default:
   185  		return nil, fmt.Errorf("convertPubKeyJWK: invalid key type: %s", keyType)
   186  	}
   187  }
   188  
   189  func getECDSACurve(keyType kms.KeyType) elliptic.Curve {
   190  	switch keyType {
   191  	case kms.ECDSAP256TypeIEEEP1363, kms.ECDSAP256TypeDER, kms.NISTP256ECDHKWType:
   192  		return elliptic.P256()
   193  	case kms.ECDSAP384TypeIEEEP1363, kms.ECDSAP384TypeDER, kms.NISTP384ECDHKWType:
   194  		return elliptic.P384()
   195  	case kms.ECDSAP521TypeIEEEP1363, kms.ECDSAP521TypeDER, kms.NISTP521ECDHKWType:
   196  		return elliptic.P521()
   197  	case kms.ECDSASecp256k1TypeIEEEP1363, kms.ECDSASecp256k1TypeDER:
   198  		return btcec.S256()
   199  	}
   200  
   201  	return nil
   202  }
   203  
   204  type publicKeyInfo struct {
   205  	Raw       asn1.RawContent
   206  	Algorithm pkix.AlgorithmIdentifier
   207  	PublicKey asn1.BitString
   208  }
   209  
   210  func parseSecp256k1DER(keyBytes []byte) (*ecdsa.PublicKey, error) {
   211  	var (
   212  		pki    publicKeyInfo
   213  		rest   []byte
   214  		err    error
   215  		pubKey *btcec.PublicKey
   216  	)
   217  
   218  	if rest, err = asn1.Unmarshal(keyBytes, &pki); err != nil {
   219  		return nil, err
   220  	} else if len(rest) != 0 {
   221  		return nil, fmt.Errorf("x509: trailing data after ASN.1 of public-key")
   222  	}
   223  
   224  	pubKey, err = btcec.ParsePubKey(pki.PublicKey.RightAlign())
   225  	if err != nil {
   226  		return nil, err
   227  	}
   228  
   229  	return pubKey.ToECDSA(), nil
   230  }
   231  
   232  // PublicKeyFromJWK builds a cryptoapi.PublicKey from jwkKey.
   233  func PublicKeyFromJWK(jwkKey *jwk.JWK) (*cryptoapi.PublicKey, error) {
   234  	if jwkKey != nil {
   235  		pubKey := &cryptoapi.PublicKey{
   236  			KID:   jwkKey.KeyID,
   237  			Curve: jwkKey.Crv,
   238  			Type:  jwkKey.Kty,
   239  		}
   240  
   241  		switch key := jwkKey.Key.(type) {
   242  		case *ecdsa.PublicKey:
   243  			pubKey.X = key.X.Bytes()
   244  			pubKey.Y = key.Y.Bytes()
   245  		case *ecdsa.PrivateKey:
   246  			pubKey.X = key.X.Bytes()
   247  			pubKey.Y = key.Y.Bytes()
   248  		case *bbs12381g2pub.PublicKey:
   249  			bbsKey, _ := key.Marshal() //nolint:errcheck // bbs marshal public key does not return any error
   250  
   251  			pubKey.X = bbsKey
   252  		case *bbs12381g2pub.PrivateKey:
   253  			bbsKey, _ := key.PublicKey().Marshal() //nolint:errcheck // bbs marshal public key does not return any error
   254  
   255  			pubKey.X = bbsKey
   256  		case ed25519.PublicKey:
   257  			pubKey.X = key
   258  		case *rsa.PublicKey:
   259  			pubKey.N = key.N.Bytes()
   260  			pubKey.E = big.NewInt(int64(key.E)).Bytes()
   261  		case ed25519.PrivateKey:
   262  			var ok bool
   263  
   264  			pubEdKey, ok := key.Public().(ed25519.PublicKey)
   265  			if !ok {
   266  				return nil, errors.New("publicKeyFromJWK: invalid 25519 private key")
   267  			}
   268  
   269  			pubKey.X = pubEdKey
   270  		default:
   271  			return nil, fmt.Errorf("publicKeyFromJWK: unsupported jwk key type %T", jwkKey.Key)
   272  		}
   273  
   274  		return pubKey, nil
   275  	}
   276  
   277  	return nil, errors.New("publicKeyFromJWK: jwk is empty")
   278  }