Score:0

How secure is AES 256bitkey generated from PBKDF2

cn flag

I am using CryptoJS AES 256 encryption:

CryptoJS.AES.encrypt(realData, generateKey(passphrase), {iv: iv});

The secret is generated through:

function generateKey(passphrase) {
  const salt = CryptoJS.lib.WordArray.random(128 / 8);
  const key256Bits = CryptoJS.PBKDF2(passphrase, salt, {
    keySize: 256 / 32,
    iterations: randomNumber,
  });

  return key256Bits;
}

Im new to this and wondering how secure is the 256keybits above?

Can someone use brute force to find out the hex, base64 encoding strings of the 256keybits, iv without caring about the passphrase.

Then convert the real 256keybits, iv which used to decrypt the realData in AES encryption? Or can the 256keybits be brute force?

Thanks!

Score:1
ng flag

The value for iterations: randomNumber is not supposed to be a random number. It's an iteration count that controls the cost of PBKDF2. It's supposed to be set as high as tolerable in the application, and the protection afforded by PBKDF2 against password search grows about linearly with that parameter. In the following I assume a high iterations (say a baseline of a hundred thousand), and that salt gets stored someway. I also assume it's used HMAC-SHA-1 (the default) or HMAC-SHA-256 (also common).

As far a we know, the main weakness in what's described is that it's possible to test a passphrase, by running generateKey, and then testing the corresponding key using a known AES cryptogram. Is that "without caring about the passphrase"? That's unclear to me.

Problem is, PBKDF2 can be run at very high speed by attackers using GPUs, FPGAs or ASICs. When iterations is high (as it should), PBKDF2 is the bottleneck of generateKey and password search. So adversaries can search passwords orders of magnitude faster than normal users using CryptoJS. From the standpoint of making password search hard, which is it's main goal in the question, PBKDF2 is thus among the worst possible use of spare CPU power for key stretching when it comes to powerful adversaries. Much better options ar Argon2, scrypt, or even bcrypt.

You decide if it's coincidental that the NIST formerly recommended PBKDF2, and still does not mandate using something better; like it formerly pushed Dual_EC_DRBG, with the obvious intention of allowing US intelligence to break this crypto. Hanlon's razor may apply, but I hold NIST scientists in higher esteem.

Kim Mỹ avatar
cn flag
"without caring about the passphrase"? I mean the passphase passed into generateKey(passphrase) could contain special characters to make it strong for brute force. While the key returned from generateKey(passphrase) which I can use to encrypt and decrypt the realData in CryptoJS.AES.encrypt(realData, generateKey(passphrase), {iv: iv}) is array of bytes. Since bytes is new to me so I don't know if that is hard to brute foce and put back to decryption as key.
Kim Mỹ avatar
cn flag
Also the encoding readable(Hex, Base64) string of generateKey(passphrase) (which in Crypto-JS I can just use key256Bits.toString(<-- base64 or hex -->)) does not contain any special characters if hex or only '/,+' and wierd ending '==' if base64. And that is easy for brute force then convert back to array of bytes(the returned key from generateKey(passphrase)) then put into decrypt the realData? Sorry this is new to me and correct me if i'm wrong. Thanks!
Kim Mỹ avatar
cn flag
in Crypto-JS library, provided the encoding readable(Hex, Base64) string of generateKey(passphrase), I can just use CryptoJS.enc.Hex.parse() to get the real 256keybits and decrypt the realData without even care about the passphrase passed into generateKey(passphrase) to generate the decrypting key?
fgrieu avatar
ng flag
It's no easier to brute force a 256-bit key expressed as a 43-character Base64 string than it is to brute-force the 32-byte raw equivalent. And that's essentially impossible. Correctly encoding the output of PBKDF2 to make an AES key with all 256-bit is an important detail. I assumed its none right. That's a programming issue, highly dependent on CryptoJS, thus rather off-topic. I did not discuss it.
dave_thompson_085 avatar
cn flag
(@KimMỹ+) crypto-js.PBKDF2 returns a _WordArray_ which is a javascript 'object' type that _contains_ bytes (but is not e.g. javascript's builtin Unit8Array); if you convert this to a string (e.g. by console.log) that result is encoded in base64 but if you pass it as the key to a crypto-js.Cipher instance that uses the bytes in it, whereas if you pass a (builtin) _string_ to such an instance it applies an OpenSSL-defined and quite poor PBKDF (EVP_BytesToKey with niter=1) and also by default uses the OpenSSL-defined format with `Salted__`+8bytes prepended to the ciphertext and encoded in base64.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.