0
votes

According to the doc a simple example to derive a password with PBKDF2 is

  return window.crypto.subtle.importKey(
    'raw', 
    encoder.encode(password), 
    {name: 'PBKDF2'}, 
    false, 
    ['deriveBits', 'deriveKey']
  ).then(function(key) {
    return window.crypto.subtle.deriveKey(
      { "name": 'PBKDF2',
        "salt": encoder.encode(salt),
        "iterations": iterations,
        "hash": 'SHA-256'
      },
      key,
      { "name": 'AES-CTR', "length": 128 }, //api requires this to be set
      true, //extractable
      [ "encrypt", "decrypt" ] //allowed functions
    )
  }).then(function (webKey) {
    return crypto.subtle.exportKey("raw", webKey);
  })

As one can see the API lets you choose:

  • key derivation function (and it's underlying hash)
  • salt
  • iterations
  • raw key material (ie. password)

However as far as I can see there is no options for choosing the out-length. It seems that the cipher suite parameter { "name": 'AES-CTR', "length": 128 } influences the out length, but you can only choose 16 and 32 byte.

For example with 10,000 rounds, salt: 'salt', password: 'key material' with 128 it will result in the following 16 bytes:

26629f0e2b7b14ed4b84daa8071c648c

whereas with { "name": 'AES-CTR', "length": 256 } you will get

26629f0e2b7b14ed4b84daa8071c648c648d2cce067f93e2c5bde0c620030521

How do I set the out length apart from 16 or 32 byte? Do I have to truncate it myself?

1

1 Answers

1
votes

deriveKey function with AES algorithm option returns you AES key. Possible AES key length parameters are following (in bits):

  • 128
  • 192
  • 256

So, you are able to choose only from them when using AES cipher. In my opinion, it's a bad idea to modify a key generated from deriveKey function. First of all, you will break an algorithm standard, and also in future you will have a problem with using truncated keys.

But if you want just to use PBKDF2 and derive bits from a password, you can use deriveBits function. Here is an example:

window.crypto.subtle.deriveBits(
        {
            name: "PBKDF2",
            salt: window.crypto.getRandomValues(new Uint8Array(16)),
            iterations: 50000,
            hash: {name: "SHA-256"}, // can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
        },
        key, //your key from generateKey or importKey
        512 //the number of bits you want to derive, values: 8, 16, 32, 64, 128, 512, 1024, 2048
    )
    .then(function(bits){
        //returns the derived bits as an ArrayBuffer
        console.log(new Uint8Array(bits));
    })
    .catch(function(err){
        console.error(err);
    });

More examples here - https://github.com/diafygi/webcrypto-examples#pbkdf2---derivekey .

Also, I have tested possible values for derive bits, and they are powers of 2 (from 8 to 2048).

I hope it will help you. Remember, if you want just use AES cipher better use default values and deriveKey function.