Several months ago, I was required to research on 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 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 purpose so it can be changed) provided to me has actually used SHA-256 which made both system 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 UUID and send it to 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 is 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$ – user7761803 Jul 4 '19 at 11:30
  • $\begingroup$ @user7761803 I see. Thank you! $\endgroup$ – Sunny Leung Jul 5 '19 at 2:20
  • 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$ – user7761803 Jul 5 '19 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$ – user7761803 Jul 5 '19 at 9:23

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.

| improve this answer | |
  • $\begingroup$ I added the codes and the main objective of the license system in the question. You can look at that. $\endgroup$ – Sunny Leung Jul 4 '19 at 8:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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