1

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: randomBigNumber,
  });

  return key256Bits;
}

I plan on storing on an SQL(or a text file) database the encoding readable HEX or Base64 of key256Bits returned from generateKey(passphrase) and then later retriving those encoding readable string to parse back to the key256Bits to decrypt the realData in CryptoJS.AES.encrypt(realData, generateKey(passphrase), {iv: iv});

Is it the correct way? Can the key256Bits be stored in SQL(or a file) database then retrived later for decrypting?

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?

So what should be the correct way to store the key256Bits and can be easily to retrive later? I'm new to this, correct me if wrong. Thanks!

8
  • 6
    Safe against what? Base64, hex ... are just different ways to represent binary data as text. They don't actually protect the data. Brute forcing a base64 or hex string has exactly the same complexity as brute forcing the original binary representation. Jun 28, 2021 at 9:01
  • 1
    This looks like an XY problem to me. Why are you storing generateKey(passphrase)? If you are storing the key that was derived from the password, then why is the password needed going forward? How does the password come in to play going forward?
    – mti2935
    Jun 28, 2021 at 9:11
  • 1
    Also, where are the salt and the number of iterations stored? You'll need these if you ever want to be able to derive the same key from the password again. On the other hand, if there is no need to ever derive the key from the password again (and basically all you need is a randomly generated key), then skip the whole PBKDF2 process, and just generate 32 random bytes, which you can do with: window.crypto.getRandomValues(new Uint8Array(32)).
    – mti2935
    Jun 28, 2021 at 9:28
  • 1
    OP, Thanks for your reply, this is staring to make more sense now. Yes, getRandomValues() is secure. see developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues, where it reads, 'The Crypto.getRandomValues() method lets you get cryptographically strong random values'. You can derive a 256-bit key using this function. I'm npt familiar wiith CryptoJS, but you can use (the native) Web Crypto API to do in-browser crypto with javascript, including AES and the whole nine yards. See developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto.
    – mti2935
    Jun 28, 2021 at 9:44
  • 1
    Why not use the native crypto API instead of of crypto.js? It's faster, pro maintained, requires no libs, integrates with OS/hardware where possible, yada yada; it has virtually every advantage possible.
    – dandavis
    Jun 30, 2021 at 4:28

1 Answer 1

2

You seem dangerously confused about this whole topic, so I'm going to answer the question as asked, and then a few others you might have meant (or should have meant), and explain what's going on and what you should actually do.


You asked: How safe is AES 256bitkey encoded in HEX, Base64? Exactly as safe as any other data stored in the same place or transmitted via the same connection as the key.

Your confusion might be based on: How much security is added or lost by encoding a secret, such as a key, in Hex or Base64? None whatsoever, in either direction, for either encoding (or even both of them together, if you want to waste space and CPU cycles).

Encodings are fully reversible and easily recognizable; they are not keyed, there's no secret to them whatsoever. As such, they can't add any security, because there's nothing that the attacker doesn't know. At the same time, they don't cost any security, because while there is less entropy (unguessability) per encoded byte, the encoding makes the secret (or any other data) longer by exactly the amount necessary to preserve the total entropy it had before (this follows necessarily from the "fully reversible" property).

You seem to want to know: How do I securely store a key? Ideally, you don't. You leave that up to the user / client to enter when needed, make the key storage somebody else's problem. Since you're already deriving your keys from a passphrase, which is presumably provided by somebody, have that somebody remember the passphrase, and all you need to remember is the salt and iteration count[1] and you can re-derive the key when the user re-supplies the passphrase.

If you don't have the option of getting the passphrase from a user/client whenever the key is needed, or if you aren't willing to accept the weaknesses of using passphrases[2] and would rather generate and store a secure random key yourself, you can do that too. First, ditch the passphrase in that case - just use a secure random number generator to generate the key (the same as you're already doing the for the salt) - unless it's serving some critical purpose (such as key recovery).

Next, pick somewhere as secure as possible to store the key. The database is an option, since presumably you already care if your DB is breached and thus have security in place against that, but you can do better. A file on the file system is slightly less likely to be exposed by something like SQL injection (though more likely to be exposed through local file inclusion) and is not generally a good idea. Storing the key in the DB but encrypting it with another key that is stored on the file system is a decent option, especially if the software that uses the key is running on a different machine than the DB, since then a SQLi can't read the keyfile and a LFI can't read from the DB, so then an attacker has to compromise both to get your key(s) in a usable form. Even better than a DB or file, though, is a hardware security module (HSM), which is a hardened computer chip that allows controlled access to the secrets it contains, and can even be made write-only (that is, you can add secrets - along with ways to use them, such as "HMAC this data" or "decrypt data X using AES256-CBC with IV Y" - in such a way that the HSM will never divulge the actual key). HSMs cost money, of course, and need to be protected themselves (can't let just anybody use the HSM, or worse walk off with it). There are also software security modules or "vaults", which are hardened processes that run on a machine (possibly, though not always, the same machine as where their secrets are used) but with unique access permissions that prevent anybody else (except the admin/superuser) from reading their data. The processes have a defined interface, and act basically like an HSM, except of course the data must be stored on disk or similar in some form because there's no dedicated hardware for it. Windows and MacOS have these built in, and there are various third-party options. Some cloud providers also offer a key storage / management system, which is usually backed by an HSM but sort of shares out its functionality using software.

[1]: Please use a better algorithm than PBKDF2 if you're actually hashing/deriving keys from passphrases, it's not the 00s anymore and there are plenty of better choices.
[2]: Human-memorable passphrases tend to have low entropy, and even securely random ones are at best as good as MAX(entropy_of_passphrase, entropy_of_key_derivation_function_output) and in practice usually a bit less because KDFs, like all hash functions, are not fully reversible and lose a little entropy in the process... though in practice this loss is irrelevant for any decent secure hash.

1
  • Great! I really appreciate that.
    – Kim Mỹ
    Jun 29, 2021 at 14:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .