diff --git a/README.md b/README.md index c1d5bc483..bc1979c86 100644 --- a/README.md +++ b/README.md @@ -374,7 +374,7 @@ Supported key encryption algorithm: | AES key wrap (192) | YES | jwa.A192KW | | AES key wrap (256) | YES | jwa.A256KW | | Direct encryption | NO | jwa.DIRECT | -| ECDH-ES | NO (see #234) | jwa.ECDH_ES | +| ECDH-ES | YES (1) | jwa.ECDH_ES | | ECDH-ES + AES key wrap (128) | YES | jwa.ECDH_ES_A128KW | | ECDH-ES + AES key wrap (192) | YES | jwa.ECDH_ES_A192KW | | ECDH-ES + AES key wrap (256) | YES | jwa.ECDH_ES_A256KW | @@ -385,6 +385,8 @@ Supported key encryption algorithm: | PBES2 + HMAC-SHA384 + AES key wrap (192) | YES | jwa.PBES2_HS384_A192KW | | PBES2 + HMAC-SHA512 + AES key wrap (256) | YES | jwa.PBES2_HS512_A256KW | +Note 1: Single-recipient only + Supported content encryption algorithm: | Algorithm | Supported? | Constant in go-jwx | diff --git a/jwe/encrypt.go b/jwe/encrypt.go index 96175e646..f8c95a9e7 100644 --- a/jwe/encrypt.go +++ b/jwe/encrypt.go @@ -82,8 +82,15 @@ func (e encryptCtx) Encrypt(plaintext []byte) (*Message, error) { } return nil, errors.Wrap(err, `failed to encrypt key`) } - if err := r.SetEncryptedKey(enckey.Bytes()); err != nil { - return nil, errors.Wrap(err, "failed to set encrypted key") + if enc.Algorithm() == jwa.ECDH_ES { + if len(e.keyEncrypters) > 1 { + return nil, errors.Errorf("unable to support multiple recipients for ECDH-ES") + } + cek = enckey.Bytes() + } else { + if err := r.SetEncryptedKey(enckey.Bytes()); err != nil { + return nil, errors.Wrap(err, "failed to set encrypted key") + } } if hp, ok := enckey.(populater); ok { if err := hp.Populate(r.Headers()); err != nil { diff --git a/jwe/jwe_test.go b/jwe/jwe_test.go index 90974723b..c53543c94 100644 --- a/jwe/jwe_test.go +++ b/jwe/jwe_test.go @@ -375,9 +375,7 @@ func TestEncode_ECDH(t *testing.T) { } algorithms := []jwa.KeyEncryptionAlgorithm{ - // XXX for ECDH-ES - // uncomment the next line - // jwa.ECDH_ES, + jwa.ECDH_ES, jwa.ECDH_ES_A256KW, jwa.ECDH_ES_A192KW, jwa.ECDH_ES_A128KW, @@ -417,10 +415,6 @@ func TestEncode_ECDH(t *testing.T) { } func Test_GHIssue207(t *testing.T) { - // XXX for ECDH-ES - // Remove the t.SkipNow() - t.SkipNow() - const plaintext = "hi\n" var testcases = []struct { Algorithm jwa.KeyEncryptionAlgorithm diff --git a/jwe/message.go b/jwe/message.go index 3f818cb14..abfbd7da5 100644 --- a/jwe/message.go +++ b/jwe/message.go @@ -476,15 +476,7 @@ func (m *Message) Decrypt(alg jwa.KeyEncryptionAlgorithm, key interface{}) ([]by } switch alg { - case jwa.ECDH_ES: - // XXX for ECDH-ES - // disable this entire case, and replace the next case statement with the following: - // - // ```START - // case jwa.ECDH_ES, jwa.ECDH_ES_A128KW, jwa.ECDH_ES_A192KW, jwa.ECDH_ES_A256KW: - // ```END - return nil, errors.New(`ECDH-ES is not yet supported`) - case jwa.ECDH_ES_A128KW, jwa.ECDH_ES_A192KW, jwa.ECDH_ES_A256KW: + case jwa.ECDH_ES, jwa.ECDH_ES_A128KW, jwa.ECDH_ES_A192KW, jwa.ECDH_ES_A256KW: epkif, ok := h2.Get(EphemeralPublicKeyKey) if !ok { return nil, errors.New("failed to get 'epk' field") diff --git a/jwx_test.go b/jwx_test.go index 4e09ec60e..2cd82b269 100644 --- a/jwx_test.go +++ b/jwx_test.go @@ -169,7 +169,10 @@ func TestJoseCompatibility(t *testing.T) { {jwa.RSA_OAEP_256, jwa.A128GCM}, {jwa.RSA_OAEP_256, jwa.A128CBC_HS256}, {jwa.RSA_OAEP_256, jwa.A256CBC_HS512}, - // {jwa.ECDH_ES, jwa.A256CBC_HS512}, + {jwa.ECDH_ES, jwa.A128GCM}, + {jwa.ECDH_ES, jwa.A256GCM}, + {jwa.ECDH_ES, jwa.A128CBC_HS256}, + {jwa.ECDH_ES, jwa.A256CBC_HS512}, {jwa.ECDH_ES_A128KW, jwa.A128GCM}, {jwa.ECDH_ES_A128KW, jwa.A128CBC_HS256}, {jwa.ECDH_ES_A256KW, jwa.A256GCM},