Is it safe to use the SHA256 of a hard-to-bruteforce string as the key to encrypt data with AES256?
The definition of
hard-to-bruteforce string is vague since it is not clear under which conditions, when, and against who. Therefore, while assuming that you have a
hard-to-bruteforce string as a password we need to turn the usual advice.
We assume that the attacker knows the key generation method, too. Therefore, firstly, the attacker will try to brute-force for possible strings and simple or complex combinations.
The users should choose passwords from entropy sources for this kind of method. The usual advice is using diceware generated passphrases that will provide high entropy passwords.
If the user has a high entropy password to enter any Cryptographically secure hash function, i.e. it has pre-image, secondary pre-image, and collision resistance, then the user can be safe., note that there is no iteration, no prevention against parallelization, though this is not necessary if you have a password with high entropy. For passwords, collision resistance is not important, pre-image, secondary pre-image resistance are important.
For multiple key derivations, you can use Hashed Message Authentication Code (HMAC)-based key derivation function (HKDF). HKDF with the expand can increase the entropy of the Input Key Material (IKM). If the entropy is good, then you can use the extract mechanism.
For key generation from passwords, you can also prefer, passwords based key generation algorithms. Bcrypt (1999), PBKDF2 (2000) and Scrypt (2009) are well-known examples. There is also new Argon2 which has the winner of the Password Hashing Competition in July 2015. Argond2id is recommendable. One of the aims of Password-Based Key Derivation functions is reducing the timing of the Brute-force password searching - like hashcat. This is achieved by iterating the hashing many times, like 10K, using large memory to reduce parallelization as done in GPU's.
Keep in mind that, in general, humans cannot remember
hard-to-bruteforce string. It is advised to use a password manager to keep passwords. Now, it turns into the chicken-egg problem. How to remember the
hard-to-bruteforce string for the password manager.
The Password-Based Key Derivation Functions are the solution for general users. With some restrictions on the passwords ( forcing some level of password space, 10-char, 1 upper, 1 decimal, 1 punctuation, etc...) the attack time can be adjusted according to current known attack levels. So, in practice, the minimal security is set. It is better to teach them the diceware.
Yes, it is safe. The answer of @kelalaka (the first part, before update) it not correct.
The OP is saying that the password is a strong string which is hard to bruteforce. That's why the answer of @kelalaka the attacker, firstly, will try to brute-force is not relevant to the question. Everything @kelalaka is saying about password stretching is correct, but it is not relevant to this particular question.
I am curious why would you want to use SHA256 instead of password, if your password is complex and is hard to bruteforce. But this is another story.
I would suppose that some readers who didn't read the question attentively will vote my answer down. Some people don't think much and just apply patterns that they have in their minds, like Password? --> hashing is bad --> use stretching instead But guys, read the question once again.
If you have a string with enough strength to be considered a secret then the action that you want to perform is to extract that entropy into a 256 bit key. For this we generally have to assume that the strength is 256 bits, or the actual strength of the resulting 256 bit key will be smaller than 2^256. Generally passwords have a strength of max 40-80 bits or so, so a normal password would definitely not suffice. For normal passwords you'd use a PBKDF.
To implement such a strategy we use a KDF, a key derivation function. If you have a sufficiently strong input then a Key Based KDF or KBKDF will do. We have one extra requirement for this KDF and that is that it is able to accept any sized input for the keying material, and not just a key. This is basically the extraction requirement mentioned before. The KDF should not only operate on actual keys as input key material.
There is one KDF that explicitly decouples the extraction from deriving the keys called HKDF, which consists of HKDF-Extract and HKDF-Expand. As the name implies, HKDF relies on HMAC, which in turn relies on a hash. It doesn't require any other primitives, so you can implement it using just a hash function such as SHA-256 (not for the uninitiated, mind you). If you just need one reasonably sized key, you can use just HKDF-Expand.
That said, just using SHA-256 as poor-mans-KDF is probably fine. It should nicely perform the extraction for you and give you relatively well distributed output after all.
One important factor is that all these KDF's operate on binary data. However, you start off with a string. So you first need to convert this string to bytes. That means choosing a character encoding such as US-ASCII or it's compatible Unicode version UTF-8. Of course, it is then of vital importance that:
- you specify this character encoding and
- that you enforce that input doesn't fall outside the range.
If you don't you may get keys that don't match and that's never nice (if not outright fatal for a project).
As kelalaka suggested, a single SHA256 hash of the password is not sufficiently secure, although it works. PBKDF2 uses many chained iterations of a hash like SHA256 to derive an AES key from a password. bcrypt, scrypt, and argon2 are newer key derivation functions that increase the difficulty of deriving the key by implementing an iterative hash that also requires a lot of memory (which GPUs typically do not have).