Search code examples
javascriptencryptionaessubtlecrypto

JavaScript SubtleCrypto generating 176-bit AES keys instead of 128-bit?


I'm working on a game that will be communicating with a NodeJS server for various purposes, and I'm currently trying to implement some AES encryption on the request payloads. Everything was working fine while testing between the server and a test tool made in JS, but when I tried to port the client code to another language that doesn't have a Web Crypto / Subtle Crypto implementation, I started getting errors about the AES key length.

Looking into it, I found that the AES key being generated (through window.crypto.subtle.generateKey) is 176 bits long, even though I specified an AES key length of 128. I'm exporting the key in JWK format, and the weird thing is the algorithm is listed as A128CBC, suggesting that it should be 128 bits.

As I'll be generating a new key anyway, I have no qualms posting the exported JWK in question here:

{
  "alg": "A128CBC",
  "ext": true,
  "k": "J3SQ0IjwlJnJwu0EadenLg",
  "key_ops": [
    "encrypt",
    "decrypt"
  ],
  "kty": "oct"
}

Can anyone explain where those extra 6 bytes are coming from? The AES implementation on the ported client-side requires 128-bit keys and just throws errors if it's not 128, grinding the entire project to a halt until this is resolved.


Solution

  • The key in your JWK is base64-encoded (actually, base64url with padding omitted).

    If you decode that J3SQ0IjwlJnJwu0EadenLg value, you get the following bytes:

     27 74 90 D0 88 F0 94 99 C9 C2 ED 04 69 D7 A7 2E 
    

    That's 16 bytes, so 128 bits. The key length is correct, you just need to add an additional base64-decoding step before using the key.