Not able to use 256 bit Key in JWE A256KW Key encryption

I was using inbuild policy to generate and encrypt token. Selected A256KW for key encryption. However, when I am giving 256 bit key, I am getting an error regarding length of the key. It is working for me once I make the key 128 bit. 

Key samples:

E9DB7E89123F52A9F2DB04EF04C7FE88 (working).

E9DB7E89123F52A9F2DB04EF04C7FE8874C737410EFCFE2277574F35ABD7A894 (not working).

Solved Solved
0 11 4,988
2 ACCEPTED SOLUTIONS

Thanks for that information. For A256KW, the length of the Key Encryption Key must be 256 bits.

Your configuration shows the SecretKey element like this:

 

  <SecretKey>
    <Value ref='private.key'/>
  </SecretKey>

 

You did not specify an encoding attribute on the Value element. By default, Apigee will decode the string you pass as the secret key, via UTF-8. That means for each character in the string, Apigee will decode 8 bits. If you pass a string of length 64, Apigee will return a key that is 64 * 8 = 512 bits long. That's too long! Which is why you see the error you see.

Actually the error message indicates "Insufficient Key Length" which suggests the key you provided is too short. But that's not correct. Really the message should read "Inappropriate Key Length", meaning that the key is not the right length for the algorithm you specified. Sorry about the confusion here! The exception is expected, the message could be better.

From the format of the key value, I am guessing that your intent is for Apigee to decode that string from a HEX (or base16) encoding. 64 characters of Hex would give you 4 bits per character, which is 64 *4 = 256 bits total, and that is the correct length of key for A256KW. To do that, you need this configuration:

 

  <SecretKey encoding='hex'>
    <Value ref='private.key' />
  </SecretKey>

 

Hex decoding will work only for keys that use only HEX digits in the key string: 0-9A-F.

When I try this without the encoding attribute, I see the behavior you reported. When I try it with the encoding attribute specifying "hex", the policy succeeds in generating the encrypted JWT.

Looking now at the documentation for the policy, I can see that the encoding attribute is not documented! I'll get that fixed.

In lieu of official documentation: you can use hex, base16 , base64, base64url or utf-8 for the value of the encoding attribute for the SecretKey/Value. base16 is a synonym for hex. The default is to decode via UTF-8.

View solution in original post

I'm SORRY! I gave the wrong configuration above. The encoding attribute needs to be on the SecretKey element. You should use THIS:

 

  <SecretKey encoding='hex'>
    <Value ref='private.key' />
  </SecretKey>

 

View solution in original post

11 REPLIES 11

I was using inbuild policy to generate and encrypt token.

Can you show the policy configuration you are using? And the specific error?

1. This is the error I received. Getting the same while debugging.

{
    "fault": {
        "faultstring""The symmetric key is of the wrong length: policy(GJWT-Session-Token)",
        "detail": {
            "errorcode""steps.jwt.InsufficientKeyLength"
        }
    }
}
 
2. Used Assign Message policy to hardcode the private key for now
 
<AssignVariable>
<Name>private.key</Name>
<Value>D8A2209DF448D653592FBB3519781A4DD8A2209DF448D653592FBB3519781A4D</Value>
</AssignVariable>
 
3. This is the Generate JWT policy.
 
<GenerateJWT continueOnError="false" enabled="true" name="GJWT-Session-Token">
<DisplayName>GJWT-Session-Token</DisplayName>
<Algorithms>
<Key>A256KW</Key>
<Content>A256GCM</Content>
</Algorithms>
<SecretKey>
<Value ref="private.key"/>
</SecretKey>
<Subject>{jwt-subject}</Subject>
<Issuer>urn://apigee-edge-JWT-policy-test</Issuer>
<Audience>audience1,audience2</Audience>
<ExpiresIn>1h</ExpiresIn>
<AdditionalClaims>
<Claim name="apis" type="string" ref="api-list"/>
</AdditionalClaims>
<OutputVariable>jwt-session-token</OutputVariable>
</GenerateJWT>

Try Encryption Key Generator online & use it. I tested it and works fine normally.

The Key Encryption Key length must be  256 bits (32 bytes)

example:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage name="AM-TestKey">
<Name>private.key2</Name>
<Value>RfUjXnZr4u7x!A%D*G-KaPdSgVkYp3s5</Value>
</AssignVariable>
</AssignMessage>

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<GenerateJWT async="false" continueOnError="false" enabled="true" name="Generate-JWT-UsingA256KW-A256GCM">
<DisplayName>Generate JWT-UsingA256KW-A256GCM</DisplayName>
<Algorithms>
<Key>A256KW</Key>
<Content>A256GCM</Content>
</Algorithms>
<SecretKey>
<Value ref="private.key2"/>
</SecretKey>
<Subject>subject-subject</Subject>
<Issuer>urn://apigee-edge-JWT-policy-test</Issuer>
<Audience>audience1,audience2</Audience>
<ExpiresIn>8h</ExpiresIn>
<AdditionalClaims>
<Claim name="additional-claim-name" type="string">additional-claim-value-goes-here</Claim>
</AdditionalClaims>
<OutputVariable>jwt-variable</OutputVariable>
</GenerateJWT>

 

 

Ref:

https://www.allkeysgenerator.com/Random/Security-Encryption-Key-Generator.aspx

https://datatracker.ietf.org/doc/html/rfc7518#section-5.1

https://datatracker.ietf.org/doc/html/rfc7518#section-4.1

 

However

@dchiesa1 Using 64 char hex it is failing with encoding specified in the policy.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage name="AM-TestKey-Base64Encoded">

<AssignVariable>
<Name>private.key2</Name>
<Value>bcdcbff90b822814c1266307c5c8bb4d2c3637aa5e2d3fd9d6b844b0d1f3ddef</Value>
<!--<Value>jXnZr4u7x!A%D*G-KaPdSgVkYp3s5v8y</Value>-->
</AssignVariable>

</AssignMessage>

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<GenerateJWT async="false" continueOnError="false" enabled="true" name="Generate-JWT-UsingA256KW-A256GCM">
<DisplayName>Generate JWT-UsingA256KW-A256GCM</DisplayName>
<Algorithms>
<Key>A256KW</Key>
<Content>A256GCM</Content>
</Algorithms>
<SecretKey>
<Value ref="private.key2" encoding="hex"/>
</SecretKey>
<Subject>subject-subject</Subject>
<Issuer>urn://apigee-edge-JWT-policy-test</Issuer>
<Audience>audience1,audience2</Audience>
<ExpiresIn>8h</ExpiresIn>
<AdditionalClaims>
<Claim name="additional-claim-name" type="string">additional-claim-value-goes-here</Claim>
</AdditionalClaims>
<OutputVariable>jwt-variable</OutputVariable>
</GenerateJWT>

Fails with

The Key Encryption Key length must be 128 bits (16 bytes), 192 bits (24 bytes) or 256 bits (32 bytes) 

 

Using 64 char hex it is failing with encoding specified in the policy.

Yes, that is expected. See my answer below. It's a matter of encoding / decoding. If you have 64 characters and decode it as UTF-8, you will get 64*8 = 512 bits. That's too much. With that key string, I suspect you want to use base16 or hex decoding. This is all explained in my other answer (previously posted!)

Thanks for that information. For A256KW, the length of the Key Encryption Key must be 256 bits.

Your configuration shows the SecretKey element like this:

 

  <SecretKey>
    <Value ref='private.key'/>
  </SecretKey>

 

You did not specify an encoding attribute on the Value element. By default, Apigee will decode the string you pass as the secret key, via UTF-8. That means for each character in the string, Apigee will decode 8 bits. If you pass a string of length 64, Apigee will return a key that is 64 * 8 = 512 bits long. That's too long! Which is why you see the error you see.

Actually the error message indicates "Insufficient Key Length" which suggests the key you provided is too short. But that's not correct. Really the message should read "Inappropriate Key Length", meaning that the key is not the right length for the algorithm you specified. Sorry about the confusion here! The exception is expected, the message could be better.

From the format of the key value, I am guessing that your intent is for Apigee to decode that string from a HEX (or base16) encoding. 64 characters of Hex would give you 4 bits per character, which is 64 *4 = 256 bits total, and that is the correct length of key for A256KW. To do that, you need this configuration:

 

  <SecretKey encoding='hex'>
    <Value ref='private.key' />
  </SecretKey>

 

Hex decoding will work only for keys that use only HEX digits in the key string: 0-9A-F.

When I try this without the encoding attribute, I see the behavior you reported. When I try it with the encoding attribute specifying "hex", the policy succeeds in generating the encrypted JWT.

Looking now at the documentation for the policy, I can see that the encoding attribute is not documented! I'll get that fixed.

In lieu of official documentation: you can use hex, base16 , base64, base64url or utf-8 for the value of the encoding attribute for the SecretKey/Value. base16 is a synonym for hex. The default is to decode via UTF-8.

Thanks you so much @dchiesa1 . This makes sense. I was totally confused seeing the error message. @API-Evangelist Thanks for your input.

Hello @dchiesa1 

Getting the same key length error even when using the encoding.

abhijithsh_0-1654682506227.png

 

this is my code :

1. Assign Key

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage continueOnError="false" enabled="true" name="Set-AES-Key">
<DisplayName>Set AES Key</DisplayName>
<Properties/>
<AssignVariable>
<Name>private.key</Name>
<Value>E9DB7E89123F52A9F2DB04EF04C7FE8874C737410EFCFE2277574F35ABD7A894</Value>
</AssignVariable>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<AssignTo createNew="false" transport="http" type="request"/>
</AssignMessage>

2. Generate token

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<GenerateJWT continueOnError="false" enabled="true" name="Generate-JWT-1">
<DisplayName>Generate JWT-1</DisplayName>
<Algorithms>
<Key>A256KW</Key>
<Content>A256GCM</Content>
</Algorithms>
<SecretKey>
<Value ref="private.key" encoding="hex"/>
</SecretKey>
<Subject>subject-subject</Subject>
<Issuer>urn://apigee-edge-JWT-policy-test</Issuer>
<Audience>audience1,audience2</Audience>
<ExpiresIn>8h</ExpiresIn>
<AdditionalClaims>
<Claim name="additional-claim-name" type="string">additional-claim-value-goes-here</Claim>
</AdditionalClaims>
<OutputVariable>session-token</OutputVariable>
</GenerateJWT>

I'm SORRY! I gave the wrong configuration above. The encoding attribute needs to be on the SecretKey element. You should use THIS:

 

  <SecretKey encoding='hex'>
    <Value ref='private.key' />
  </SecretKey>

 

I am using Apigee X

I used the encoding config too in my earlier comment 🙂

But yes, with new configuration it works fine. Thankyou 🙂

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<GenerateJWT async="false" continueOnError="false" enabled="true" name="Generate-JWT-UsingA256KW-A256GCM">
<DisplayName>Generate JWT-UsingA256KW-A256GCM</DisplayName>
<Algorithms>
<Key>A256KW</Key>
<Content>A256GCM</Content>
</Algorithms>
<SecretKey encoding="hex">
<Value ref="private.key"/>
</SecretKey>
<Subject>subject-subject</Subject>
<Issuer>urn://apigee-edge-JWT-policy-test</Issuer>
<Audience>audience1,audience2</Audience>
<ExpiresIn>8h</ExpiresIn>
<AdditionalClaims>
<Claim name="additional-claim-name" type="string">additional-claim-value-goes-here</Claim>
</AdditionalClaims>
<OutputVariable>jwt-variable</OutputVariable>
</GenerateJWT>

@dchiesa1 Thanks for clarifying. Now it is working.