Several months ago, I was required to research AES and SHA-256 to make a secured license system for my app. However, I was dumb enough that couldn't distinguish between the 256 bits from AES and the actual SHA-256, which resulted in me making a system that generates a 256-bit long key (44 characters long base64 key) for AES-GCM encryption and decryption without the actual SHA-256. Now, it's time for me to update the system that cooperates with an AES system in PHP. But then I found the PHP resources (it's used for research purposes so it can be changed) provided to me has actually used SHA-256 which made both systems totally different. Then my question is, is the 256-bit long key secure enough that I don't actually need the SHA-256 in the PHP system?

P.S.: If I misunderstood anything in the question, I would like to apologize since I am still new to the area of cryptography...

PHP code:

echo '<pre>';

$hash_string = 'qIANSOwtdfF4y5Yk33ZLE5s6KwKBAeu6qzJRG84Sjjo=';
echo "password : ";
echo '<hr>';
$decode_string = base64_decode($hash_string);
$hash = hash('SHA256', $decode_string, true);
echo "hash : ";
echo '<hr>';
$app_cc_aes_key = substr($hash, 0, 32);
$cipher = 'aes-256-gcm';
$iv_len = openssl_cipher_iv_length($cipher);
echo "app_cc_aes_key : ";
echo '<br>';
echo "cipher :";
echo '<hr>';

$data = '7bc9d6ae-982f-11e9-bc42-526af7764f64';
echo "data : {$data}";
echo '<hr>';

$tag_length = 16;
$iv = openssl_random_pseudo_bytes($iv_len);
$tag = "";
$encrypt = openssl_encrypt($data, $cipher, $app_cc_aes_key, OPENSSL_RAW_DATA, $iv, $tag, "", $tag_length);
$encrypt_text = base64_encode($iv.$tag.$encrypt);
echo "encrypt :";
echo '<br>';
echo "encrypt_text :";
echo '<hr>';

$decoded_text = base64_decode($encrypt_text);
$iv = substr($decoded_text, 0, $iv_len);
$tag = substr($decoded_text, $iv_len, $tag_length);
$ciphertext = substr($decoded_text, $iv_len + $tag_length);
$decrypt_text = openssl_decrypt($ciphertext, $cipher, $app_cc_aes_key, OPENSSL_RAW_DATA, $iv, $tag);
echo "decrypt_text : {$decrypt_text}";
echo '<hr>';

The method to generate AES key in C#:

public string NewKey()
    var key = new byte[KEY_BIT_SIZE / 8];
    return Convert.ToBase64String(key);

About the license system: It's on Android. When the app first opens, the app will generate a UUID and send it to the server for authorization. Then our staff will authorize manually and send an authorization code back. If there is the code, the app can then automatically license for using our courses which are arranged by our staff.

  • 1
    $\begingroup$ You should not use Random.NextBytes to generate keys - even the documentation says to use RNGCryptoServiceProvider.GetBytes. See this question on stack overflow. $\endgroup$ Commented Jul 4, 2019 at 11:30
  • 1
    $\begingroup$ Something to note about your licence system: as I understand it, it is challenge-response, but presumably a yes/no decision is made in the app based on decrypting the authorisation code. Someone wishing to bypass this could simply find the test in the app executable and make it always take the “success” branch. (This is surprisingly easy to do, unless you are protecting the app with obfuscation and other technologies such as ProGuard.). An alternative would be to have the challenge-response use Diffie-Hellman key exchange. $\endgroup$ Commented Jul 5, 2019 at 9:23
  • $\begingroup$ To use DH: instead of the UUID sent to the server, the app sends a public value. When it’s authorised, the staff generate and send the server-side public value instead of an authorisation code. Both sides can then compute a shared key (which you would need to run through a proper KDF). This shared key can be used to encrypt data for the app. (You’d probably actually encrypt each course with its own key, and use the shared key as a master key to encrypt the course’s key for the licensed app.). I’d use X25519 as the public keys are only 32 bytes. But this is a topic for another question… $\endgroup$ Commented Jul 5, 2019 at 9:23

2 Answers 2


You don't say how SHA-256 is used in the PHP system, so there's really no way to know how "secure" it is. At a guess, SHA-256 is being used as a key derivation function (KDF) on the input key material, so whether it provides any additional security will depend on the source of the input key material. Of course, SHA-256 isn't great as a KDF - one would normally use something like HKDF (e.g. as documented in RFC 5869).

a system that generates 256-bit long key

How this is generated is going to materially impact how secure your scheme is.

If it is generated by a cryptographically-strong random number generator (CSPRNG), then using a KDF on it is generally considered to be unnecessary.

If it is generated by a Diffie-Hellman key exchange, then it's important to use a KDF on the raw DH output.

If it's generated any other way, your whole scheme is likely to be insecure, whether or not SHA-256 is used.

But this is all based on a guess of how the various algorithms are used.

To get a better answer, you really need to tell us what the requirements are for your licensing system, what the thread model is (note that if this is a mobile app, they are considered to be run in an untrusted environment that an attacker has full control over, and various obfuscation and white-box crypto techniques are normally used too) and the details of the scheme.

I am still new to the area of cryptography

Cryptography is one of the areas where it's always better to "buy" rather than "build" - don't roll your own.

  • $\begingroup$ I added the codes and the main objective of the license system in the question. You can look at that. $\endgroup$ Commented Jul 4, 2019 at 8:45

I know this is an older post but I would just like to chime in with comments since developers who are new to crypto may find this and propagate a common but critical mistake. In the OP, there is the following line

$app_cc_aes_key = substr($hash, 0, 32);

This is an incredibly dangerous line of code unless you absolutely know what is occurring behind the scenes but basically, it could reduce a 256-bit key to 128 bits. I have written a blog on this topic cautioning developers to avoid this mistake.

NOTE: In this actual implementation the OP is actually benign since the hash function is returning binary data (3rd parameter in hash call set to true) but if the third parameter was missing or false, the hash would return a hex string not binary and the following substr call would significantly weaken the encryption key.

$hash = hash('SHA256', $decode_string, true);


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.