...

Source file src/gopkg.in/go-jose/go-jose.v2/asymmetric.go

Documentation: gopkg.in/go-jose/go-jose.v2

     1  /*-
     2   * Copyright 2014 Square Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package jose
    18  
    19  import (
    20  	"crypto"
    21  	"crypto/aes"
    22  	"crypto/ecdsa"
    23  	"crypto/rand"
    24  	"crypto/rsa"
    25  	"crypto/sha1"
    26  	"crypto/sha256"
    27  	"errors"
    28  	"fmt"
    29  	"math/big"
    30  
    31  	"golang.org/x/crypto/ed25519"
    32  	josecipher "gopkg.in/go-jose/go-jose.v2/cipher"
    33  	"gopkg.in/go-jose/go-jose.v2/json"
    34  )
    35  
    36  // A generic RSA-based encrypter/verifier
    37  type rsaEncrypterVerifier struct {
    38  	publicKey *rsa.PublicKey
    39  }
    40  
    41  // A generic RSA-based decrypter/signer
    42  type rsaDecrypterSigner struct {
    43  	privateKey *rsa.PrivateKey
    44  }
    45  
    46  // A generic EC-based encrypter/verifier
    47  type ecEncrypterVerifier struct {
    48  	publicKey *ecdsa.PublicKey
    49  }
    50  
    51  type edEncrypterVerifier struct {
    52  	publicKey ed25519.PublicKey
    53  }
    54  
    55  // A key generator for ECDH-ES
    56  type ecKeyGenerator struct {
    57  	size      int
    58  	algID     string
    59  	publicKey *ecdsa.PublicKey
    60  }
    61  
    62  // A generic EC-based decrypter/signer
    63  type ecDecrypterSigner struct {
    64  	privateKey *ecdsa.PrivateKey
    65  }
    66  
    67  type edDecrypterSigner struct {
    68  	privateKey ed25519.PrivateKey
    69  }
    70  
    71  // newRSARecipient creates recipientKeyInfo based on the given key.
    72  func newRSARecipient(keyAlg KeyAlgorithm, publicKey *rsa.PublicKey) (recipientKeyInfo, error) {
    73  	// Verify that key management algorithm is supported by this encrypter
    74  	switch keyAlg {
    75  	case RSA1_5, RSA_OAEP, RSA_OAEP_256:
    76  	default:
    77  		return recipientKeyInfo{}, ErrUnsupportedAlgorithm
    78  	}
    79  
    80  	if publicKey == nil {
    81  		return recipientKeyInfo{}, errors.New("invalid public key")
    82  	}
    83  
    84  	return recipientKeyInfo{
    85  		keyAlg: keyAlg,
    86  		keyEncrypter: &rsaEncrypterVerifier{
    87  			publicKey: publicKey,
    88  		},
    89  	}, nil
    90  }
    91  
    92  // newRSASigner creates a recipientSigInfo based on the given key.
    93  func newRSASigner(sigAlg SignatureAlgorithm, privateKey *rsa.PrivateKey) (recipientSigInfo, error) {
    94  	// Verify that key management algorithm is supported by this encrypter
    95  	switch sigAlg {
    96  	case RS256, RS384, RS512, PS256, PS384, PS512:
    97  	default:
    98  		return recipientSigInfo{}, ErrUnsupportedAlgorithm
    99  	}
   100  
   101  	if privateKey == nil {
   102  		return recipientSigInfo{}, errors.New("invalid private key")
   103  	}
   104  
   105  	return recipientSigInfo{
   106  		sigAlg: sigAlg,
   107  		publicKey: staticPublicKey(&JSONWebKey{
   108  			Key: privateKey.Public(),
   109  		}),
   110  		signer: &rsaDecrypterSigner{
   111  			privateKey: privateKey,
   112  		},
   113  	}, nil
   114  }
   115  
   116  func newEd25519Signer(sigAlg SignatureAlgorithm, privateKey ed25519.PrivateKey) (recipientSigInfo, error) {
   117  	if sigAlg != EdDSA {
   118  		return recipientSigInfo{}, ErrUnsupportedAlgorithm
   119  	}
   120  
   121  	if privateKey == nil {
   122  		return recipientSigInfo{}, errors.New("invalid private key")
   123  	}
   124  	return recipientSigInfo{
   125  		sigAlg: sigAlg,
   126  		publicKey: staticPublicKey(&JSONWebKey{
   127  			Key: privateKey.Public(),
   128  		}),
   129  		signer: &edDecrypterSigner{
   130  			privateKey: privateKey,
   131  		},
   132  	}, nil
   133  }
   134  
   135  // newECDHRecipient creates recipientKeyInfo based on the given key.
   136  func newECDHRecipient(keyAlg KeyAlgorithm, publicKey *ecdsa.PublicKey) (recipientKeyInfo, error) {
   137  	// Verify that key management algorithm is supported by this encrypter
   138  	switch keyAlg {
   139  	case ECDH_ES, ECDH_ES_A128KW, ECDH_ES_A192KW, ECDH_ES_A256KW:
   140  	default:
   141  		return recipientKeyInfo{}, ErrUnsupportedAlgorithm
   142  	}
   143  
   144  	if publicKey == nil || !publicKey.Curve.IsOnCurve(publicKey.X, publicKey.Y) {
   145  		return recipientKeyInfo{}, errors.New("invalid public key")
   146  	}
   147  
   148  	return recipientKeyInfo{
   149  		keyAlg: keyAlg,
   150  		keyEncrypter: &ecEncrypterVerifier{
   151  			publicKey: publicKey,
   152  		},
   153  	}, nil
   154  }
   155  
   156  // newECDSASigner creates a recipientSigInfo based on the given key.
   157  func newECDSASigner(sigAlg SignatureAlgorithm, privateKey *ecdsa.PrivateKey) (recipientSigInfo, error) {
   158  	// Verify that key management algorithm is supported by this encrypter
   159  	switch sigAlg {
   160  	case ES256, ES384, ES512:
   161  	default:
   162  		return recipientSigInfo{}, ErrUnsupportedAlgorithm
   163  	}
   164  
   165  	if privateKey == nil {
   166  		return recipientSigInfo{}, errors.New("invalid private key")
   167  	}
   168  
   169  	return recipientSigInfo{
   170  		sigAlg: sigAlg,
   171  		publicKey: staticPublicKey(&JSONWebKey{
   172  			Key: privateKey.Public(),
   173  		}),
   174  		signer: &ecDecrypterSigner{
   175  			privateKey: privateKey,
   176  		},
   177  	}, nil
   178  }
   179  
   180  // Encrypt the given payload and update the object.
   181  func (ctx rsaEncrypterVerifier) encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) {
   182  	encryptedKey, err := ctx.encrypt(cek, alg)
   183  	if err != nil {
   184  		return recipientInfo{}, err
   185  	}
   186  
   187  	return recipientInfo{
   188  		encryptedKey: encryptedKey,
   189  		header:       &rawHeader{},
   190  	}, nil
   191  }
   192  
   193  // Encrypt the given payload. Based on the key encryption algorithm,
   194  // this will either use RSA-PKCS1v1.5 or RSA-OAEP (with SHA-1 or SHA-256).
   195  func (ctx rsaEncrypterVerifier) encrypt(cek []byte, alg KeyAlgorithm) ([]byte, error) {
   196  	switch alg {
   197  	case RSA1_5:
   198  		return rsa.EncryptPKCS1v15(RandReader, ctx.publicKey, cek)
   199  	case RSA_OAEP:
   200  		return rsa.EncryptOAEP(sha1.New(), RandReader, ctx.publicKey, cek, []byte{})
   201  	case RSA_OAEP_256:
   202  		return rsa.EncryptOAEP(sha256.New(), RandReader, ctx.publicKey, cek, []byte{})
   203  	}
   204  
   205  	return nil, ErrUnsupportedAlgorithm
   206  }
   207  
   208  // Decrypt the given payload and return the content encryption key.
   209  func (ctx rsaDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) {
   210  	return ctx.decrypt(recipient.encryptedKey, headers.getAlgorithm(), generator)
   211  }
   212  
   213  // Decrypt the given payload. Based on the key encryption algorithm,
   214  // this will either use RSA-PKCS1v1.5 or RSA-OAEP (with SHA-1 or SHA-256).
   215  func (ctx rsaDecrypterSigner) decrypt(jek []byte, alg KeyAlgorithm, generator keyGenerator) ([]byte, error) {
   216  	// Note: The random reader on decrypt operations is only used for blinding,
   217  	// so stubbing is meanlingless (hence the direct use of rand.Reader).
   218  	switch alg {
   219  	case RSA1_5:
   220  		defer func() {
   221  			// DecryptPKCS1v15SessionKey sometimes panics on an invalid payload
   222  			// because of an index out of bounds error, which we want to ignore.
   223  			// This has been fixed in Go 1.3.1 (released 2014/08/13), the recover()
   224  			// only exists for preventing crashes with unpatched versions.
   225  			// See: https://groups.google.com/forum/#!topic/golang-dev/7ihX6Y6kx9k
   226  			// See: https://code.google.com/p/go/source/detail?r=58ee390ff31602edb66af41ed10901ec95904d33
   227  			_ = recover()
   228  		}()
   229  
   230  		// Perform some input validation.
   231  		keyBytes := ctx.privateKey.PublicKey.N.BitLen() / 8
   232  		if keyBytes != len(jek) {
   233  			// Input size is incorrect, the encrypted payload should always match
   234  			// the size of the public modulus (e.g. using a 2048 bit key will
   235  			// produce 256 bytes of output). Reject this since it's invalid input.
   236  			return nil, ErrCryptoFailure
   237  		}
   238  
   239  		cek, _, err := generator.genKey()
   240  		if err != nil {
   241  			return nil, ErrCryptoFailure
   242  		}
   243  
   244  		// When decrypting an RSA-PKCS1v1.5 payload, we must take precautions to
   245  		// prevent chosen-ciphertext attacks as described in RFC 3218, "Preventing
   246  		// the Million Message Attack on Cryptographic Message Syntax". We are
   247  		// therefore deliberately ignoring errors here.
   248  		_ = rsa.DecryptPKCS1v15SessionKey(rand.Reader, ctx.privateKey, jek, cek)
   249  
   250  		return cek, nil
   251  	case RSA_OAEP:
   252  		// Use rand.Reader for RSA blinding
   253  		return rsa.DecryptOAEP(sha1.New(), rand.Reader, ctx.privateKey, jek, []byte{})
   254  	case RSA_OAEP_256:
   255  		// Use rand.Reader for RSA blinding
   256  		return rsa.DecryptOAEP(sha256.New(), rand.Reader, ctx.privateKey, jek, []byte{})
   257  	}
   258  
   259  	return nil, ErrUnsupportedAlgorithm
   260  }
   261  
   262  // Sign the given payload
   263  func (ctx rsaDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
   264  	var hash crypto.Hash
   265  
   266  	switch alg {
   267  	case RS256, PS256:
   268  		hash = crypto.SHA256
   269  	case RS384, PS384:
   270  		hash = crypto.SHA384
   271  	case RS512, PS512:
   272  		hash = crypto.SHA512
   273  	default:
   274  		return Signature{}, ErrUnsupportedAlgorithm
   275  	}
   276  
   277  	hasher := hash.New()
   278  
   279  	// According to documentation, Write() on hash never fails
   280  	_, _ = hasher.Write(payload)
   281  	hashed := hasher.Sum(nil)
   282  
   283  	var out []byte
   284  	var err error
   285  
   286  	switch alg {
   287  	case RS256, RS384, RS512:
   288  		// TODO(https://github.com/go-jose/go-jose/issues/40): As of go1.20, the
   289  		// random parameter is legacy and ignored, and it can be nil.
   290  		// https://cs.opensource.google/go/go/+/refs/tags/go1.20:src/crypto/rsa/pkcs1v15.go;l=263;bpv=0;bpt=1
   291  		out, err = rsa.SignPKCS1v15(RandReader, ctx.privateKey, hash, hashed)
   292  	case PS256, PS384, PS512:
   293  		out, err = rsa.SignPSS(RandReader, ctx.privateKey, hash, hashed, &rsa.PSSOptions{
   294  			SaltLength: rsa.PSSSaltLengthEqualsHash,
   295  		})
   296  	}
   297  
   298  	if err != nil {
   299  		return Signature{}, err
   300  	}
   301  
   302  	return Signature{
   303  		Signature: out,
   304  		protected: &rawHeader{},
   305  	}, nil
   306  }
   307  
   308  // Verify the given payload
   309  func (ctx rsaEncrypterVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error {
   310  	var hash crypto.Hash
   311  
   312  	switch alg {
   313  	case RS256, PS256:
   314  		hash = crypto.SHA256
   315  	case RS384, PS384:
   316  		hash = crypto.SHA384
   317  	case RS512, PS512:
   318  		hash = crypto.SHA512
   319  	default:
   320  		return ErrUnsupportedAlgorithm
   321  	}
   322  
   323  	hasher := hash.New()
   324  
   325  	// According to documentation, Write() on hash never fails
   326  	_, _ = hasher.Write(payload)
   327  	hashed := hasher.Sum(nil)
   328  
   329  	switch alg {
   330  	case RS256, RS384, RS512:
   331  		return rsa.VerifyPKCS1v15(ctx.publicKey, hash, hashed, signature)
   332  	case PS256, PS384, PS512:
   333  		return rsa.VerifyPSS(ctx.publicKey, hash, hashed, signature, nil)
   334  	}
   335  
   336  	return ErrUnsupportedAlgorithm
   337  }
   338  
   339  // Encrypt the given payload and update the object.
   340  func (ctx ecEncrypterVerifier) encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) {
   341  	switch alg {
   342  	case ECDH_ES:
   343  		// ECDH-ES mode doesn't wrap a key, the shared secret is used directly as the key.
   344  		return recipientInfo{
   345  			header: &rawHeader{},
   346  		}, nil
   347  	case ECDH_ES_A128KW, ECDH_ES_A192KW, ECDH_ES_A256KW:
   348  	default:
   349  		return recipientInfo{}, ErrUnsupportedAlgorithm
   350  	}
   351  
   352  	generator := ecKeyGenerator{
   353  		algID:     string(alg),
   354  		publicKey: ctx.publicKey,
   355  	}
   356  
   357  	switch alg {
   358  	case ECDH_ES_A128KW:
   359  		generator.size = 16
   360  	case ECDH_ES_A192KW:
   361  		generator.size = 24
   362  	case ECDH_ES_A256KW:
   363  		generator.size = 32
   364  	}
   365  
   366  	kek, header, err := generator.genKey()
   367  	if err != nil {
   368  		return recipientInfo{}, err
   369  	}
   370  
   371  	block, err := aes.NewCipher(kek)
   372  	if err != nil {
   373  		return recipientInfo{}, err
   374  	}
   375  
   376  	jek, err := josecipher.KeyWrap(block, cek)
   377  	if err != nil {
   378  		return recipientInfo{}, err
   379  	}
   380  
   381  	return recipientInfo{
   382  		encryptedKey: jek,
   383  		header:       &header,
   384  	}, nil
   385  }
   386  
   387  // Get key size for EC key generator
   388  func (ctx ecKeyGenerator) keySize() int {
   389  	return ctx.size
   390  }
   391  
   392  // Get a content encryption key for ECDH-ES
   393  func (ctx ecKeyGenerator) genKey() ([]byte, rawHeader, error) {
   394  	priv, err := ecdsa.GenerateKey(ctx.publicKey.Curve, RandReader)
   395  	if err != nil {
   396  		return nil, rawHeader{}, err
   397  	}
   398  
   399  	out := josecipher.DeriveECDHES(ctx.algID, []byte{}, []byte{}, priv, ctx.publicKey, ctx.size)
   400  
   401  	b, err := json.Marshal(&JSONWebKey{
   402  		Key: &priv.PublicKey,
   403  	})
   404  	if err != nil {
   405  		return nil, nil, err
   406  	}
   407  
   408  	headers := rawHeader{
   409  		headerEPK: makeRawMessage(b),
   410  	}
   411  
   412  	return out, headers, nil
   413  }
   414  
   415  // Decrypt the given payload and return the content encryption key.
   416  func (ctx ecDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) {
   417  	epk, err := headers.getEPK()
   418  	if err != nil {
   419  		return nil, errors.New("go-jose/go-jose: invalid epk header")
   420  	}
   421  	if epk == nil {
   422  		return nil, errors.New("go-jose/go-jose: missing epk header")
   423  	}
   424  
   425  	publicKey, ok := epk.Key.(*ecdsa.PublicKey)
   426  	if publicKey == nil || !ok {
   427  		return nil, errors.New("go-jose/go-jose: invalid epk header")
   428  	}
   429  
   430  	if !ctx.privateKey.Curve.IsOnCurve(publicKey.X, publicKey.Y) {
   431  		return nil, errors.New("go-jose/go-jose: invalid public key in epk header")
   432  	}
   433  
   434  	apuData, err := headers.getAPU()
   435  	if err != nil {
   436  		return nil, errors.New("go-jose/go-jose: invalid apu header")
   437  	}
   438  	apvData, err := headers.getAPV()
   439  	if err != nil {
   440  		return nil, errors.New("go-jose/go-jose: invalid apv header")
   441  	}
   442  
   443  	deriveKey := func(algID string, size int) []byte {
   444  		return josecipher.DeriveECDHES(algID, apuData.bytes(), apvData.bytes(), ctx.privateKey, publicKey, size)
   445  	}
   446  
   447  	var keySize int
   448  
   449  	algorithm := headers.getAlgorithm()
   450  	switch algorithm {
   451  	case ECDH_ES:
   452  		// ECDH-ES uses direct key agreement, no key unwrapping necessary.
   453  		return deriveKey(string(headers.getEncryption()), generator.keySize()), nil
   454  	case ECDH_ES_A128KW:
   455  		keySize = 16
   456  	case ECDH_ES_A192KW:
   457  		keySize = 24
   458  	case ECDH_ES_A256KW:
   459  		keySize = 32
   460  	default:
   461  		return nil, ErrUnsupportedAlgorithm
   462  	}
   463  
   464  	key := deriveKey(string(algorithm), keySize)
   465  	block, err := aes.NewCipher(key)
   466  	if err != nil {
   467  		return nil, err
   468  	}
   469  
   470  	return josecipher.KeyUnwrap(block, recipient.encryptedKey)
   471  }
   472  
   473  func (ctx edDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
   474  	if alg != EdDSA {
   475  		return Signature{}, ErrUnsupportedAlgorithm
   476  	}
   477  
   478  	sig, err := ctx.privateKey.Sign(RandReader, payload, crypto.Hash(0))
   479  	if err != nil {
   480  		return Signature{}, err
   481  	}
   482  
   483  	return Signature{
   484  		Signature: sig,
   485  		protected: &rawHeader{},
   486  	}, nil
   487  }
   488  
   489  func (ctx edEncrypterVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error {
   490  	if alg != EdDSA {
   491  		return ErrUnsupportedAlgorithm
   492  	}
   493  	ok := ed25519.Verify(ctx.publicKey, payload, signature)
   494  	if !ok {
   495  		return errors.New("go-jose/go-jose: ed25519 signature failed to verify")
   496  	}
   497  	return nil
   498  }
   499  
   500  // Sign the given payload
   501  func (ctx ecDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
   502  	var expectedBitSize int
   503  	var hash crypto.Hash
   504  
   505  	switch alg {
   506  	case ES256:
   507  		expectedBitSize = 256
   508  		hash = crypto.SHA256
   509  	case ES384:
   510  		expectedBitSize = 384
   511  		hash = crypto.SHA384
   512  	case ES512:
   513  		expectedBitSize = 521
   514  		hash = crypto.SHA512
   515  	}
   516  
   517  	curveBits := ctx.privateKey.Curve.Params().BitSize
   518  	if expectedBitSize != curveBits {
   519  		return Signature{}, fmt.Errorf("go-jose/go-jose: expected %d bit key, got %d bits instead", expectedBitSize, curveBits)
   520  	}
   521  
   522  	hasher := hash.New()
   523  
   524  	// According to documentation, Write() on hash never fails
   525  	_, _ = hasher.Write(payload)
   526  	hashed := hasher.Sum(nil)
   527  
   528  	r, s, err := ecdsa.Sign(RandReader, ctx.privateKey, hashed)
   529  	if err != nil {
   530  		return Signature{}, err
   531  	}
   532  
   533  	keyBytes := curveBits / 8
   534  	if curveBits%8 > 0 {
   535  		keyBytes++
   536  	}
   537  
   538  	// We serialize the outputs (r and s) into big-endian byte arrays and pad
   539  	// them with zeros on the left to make sure the sizes work out. Both arrays
   540  	// must be keyBytes long, and the output must be 2*keyBytes long.
   541  	rBytes := r.Bytes()
   542  	rBytesPadded := make([]byte, keyBytes)
   543  	copy(rBytesPadded[keyBytes-len(rBytes):], rBytes)
   544  
   545  	sBytes := s.Bytes()
   546  	sBytesPadded := make([]byte, keyBytes)
   547  	copy(sBytesPadded[keyBytes-len(sBytes):], sBytes)
   548  
   549  	out := append(rBytesPadded, sBytesPadded...)
   550  
   551  	return Signature{
   552  		Signature: out,
   553  		protected: &rawHeader{},
   554  	}, nil
   555  }
   556  
   557  // Verify the given payload
   558  func (ctx ecEncrypterVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error {
   559  	var keySize int
   560  	var hash crypto.Hash
   561  
   562  	switch alg {
   563  	case ES256:
   564  		keySize = 32
   565  		hash = crypto.SHA256
   566  	case ES384:
   567  		keySize = 48
   568  		hash = crypto.SHA384
   569  	case ES512:
   570  		keySize = 66
   571  		hash = crypto.SHA512
   572  	default:
   573  		return ErrUnsupportedAlgorithm
   574  	}
   575  
   576  	if len(signature) != 2*keySize {
   577  		return fmt.Errorf("go-jose/go-jose: invalid signature size, have %d bytes, wanted %d", len(signature), 2*keySize)
   578  	}
   579  
   580  	hasher := hash.New()
   581  
   582  	// According to documentation, Write() on hash never fails
   583  	_, _ = hasher.Write(payload)
   584  	hashed := hasher.Sum(nil)
   585  
   586  	r := big.NewInt(0).SetBytes(signature[:keySize])
   587  	s := big.NewInt(0).SetBytes(signature[keySize:])
   588  
   589  	match := ecdsa.Verify(ctx.publicKey, hashed, r, s)
   590  	if !match {
   591  		return errors.New("go-jose/go-jose: ecdsa signature failed to verify")
   592  	}
   593  
   594  	return nil
   595  }
   596  

View as plain text