4
$\begingroup$

I built an app that used AES encryption with 16 characters Key and IV. It seems it could easily be hacked, as someone did it in a day.

I feel that I made a few mistakes

  1. Used key & IV which was only plain text length of 16
  2. Key not hashed with SHA-256
  3. It was an Android app ( Xamarin Forms) and I did not obfuscate the app

Can anyone guide me on what went wrong?

[Updates]

  • The app needs to operate in offline mode. That's why I hardcode keys in the application.
  • This app is reading information from QR Code encrypted content. An attacker able to create a QR Code with fake information that becomes a valid QR code
$\endgroup$
4
  • $\begingroup$ What is the character space for you? A to Z, and a to z? Was the key size of the AES. How you stored the password, etc. You need to provide all information. $\endgroup$
    – kelalaka
    Dec 7, 2020 at 13:17
  • $\begingroup$ A-Z, 0-9, and symbols. Key size 16 bytes $\endgroup$ Dec 7, 2020 at 13:18
  • 10
    $\begingroup$ What does cracked mean? was the key recovered? plain text revealed? access to something granted? Message spoofed? What was the encryption mode? It seems more likely a bypass than an encryption attack. $\endgroup$
    – Meir Maor
    Dec 7, 2020 at 13:53
  • 9
    $\begingroup$ Please next time write the full details of your problem with a clear indication of the aim so that you can get a proper answer for your cause. $\endgroup$
    – kelalaka
    Dec 7, 2020 at 16:09

4 Answers 4

12
$\begingroup$

If the characters are from $[A..Z]$ and $[0..9]$ then that makes 39 possibilities per character (byte). Then the keyspace will be $39^{16}$ and that is approximately 83-bit. This is space is achievable with supercomputers but not for ordinary people. Therefore, there must be something else around that cracks your system.

Used key & IV which was only plain text length of 16

That is not a good way.

  • The IV must random, though, your mode of operation is not clear therefore we cannot recommend the exact usage. In short, we can say that a (key,IV) pair must be used only once. You can use Android's secure random to generate the random IV.

  • For the key, one should go for the diceware or Bip39 to have good strength on the password. The user can still have a longer character than 16 so that at least 128-bit strength is achieved. With the password, the memory-hard password hashing algorithms like Argon2 to reduce the attack capability of the attackers.

Key not hashed with SHA-256

SHA-256 is not a password hashing algorithm we have Scrypt, PBKDF2, and Argon2 for those kinds of problems.

It was an Android app ( Xamarin Forms) and I did not obfuscate the app

This sentence indicates that probably you hardcoded the key into your application. And the attacker resolved the key by getting the package and analyzed the reversed byte code. This is not the correct way to store a cryptographic key.

If you want to communicate with your server use DHKE with your server to create the session key and possibly the IV by using the full exchanged key with HKDF. Then apply AES-GCM or ChaCha20-Poly1305 to achieve the authenticated encryption. In this way, you don't need to store secret keys. You only need the public key of your server. With this, you can achieve, forward secrecy, confidentiality, integrity, and authentication.

If you want to use app-in encryption, then get the password with a good strength from the user and derive the encryption key by using Argon2id.

You may also have the benefit of using the Android-KeyStore if that fits your needs.


updates

[Update] This app is reading information from QR Code encrypted content. An attacker able to create a QR Code with fake information that becomes a valid QR code

As Fgrieu mentioned that you can use a signed QR. To check the signature one only needs a public key.

  • If the content doesn't need to be encrypted, then there is no need for an encryption key.

  • If encryption is required, one can either install the key later and store it in the key-store or use a server-client approach so that the device doesn't use the key at all. The client either gets the key temporality from the server, or it can use the server as a decryption oracle while using a secure channel as told above.

[Update] The app needs to operate in offline mode. That's why I hardcode keys in the application

Installing the key later is the solution. You can install the key either manually in Android activity or use a specially designed QR code to read in then store it in the Android Key-Store.

$\endgroup$
2
  • 1
    $\begingroup$ Obligatory XKCD $\endgroup$
    – Cort Ammon
    Dec 8, 2020 at 5:35
  • $\begingroup$ Side note: that's probably what happened (reverse engineering to find the key), given that the code is 1) a Java class (much easier to "decompile") 2) not encrypted by default (have to use 3rd party progs). OTOH, iOS does encrypt the code, and it's (basically) C compiled into machine code ; you would have to dump the memory of an iOS device (to get it in clear), then look for the key (stored within the code)... way more difficult than with Android. $\endgroup$
    – Déjà vu
    Dec 8, 2020 at 7:31
4
$\begingroup$

We have little detail on the security goals or the hack (to the point that the question feels detached from reality), thus this answer is not specific.

  1. Used key & IV which was only plain text length of 16

The key length of 16 chars (AES-256) is unlikely to be a real practical issue for a short-term attack. Even if we restrict to 32 = 25 possible values per char, that's 80-bit, which is at least hard to break. An exception is if the key was in the code (see 3), where directly using a text key (especially if it on the tune of "MyZup3rZ3cr3tK3y") helps attack.

The IV of 16 bytes is standard, and OK in practice if it does not repeat. Constant or otherwise repeating IV can be a disaster, especially with the common AES-CTR, just like a reused pad in the OTP.

  1. Key not hashed with SHA-256

That's not an issue, if the key is random. If it's not (e.g. derived from a password or passphrase), SHA-256 is inadequate and it's needed a purposely-slow "password-based" hash, e.g. scrypt or Argon2.

  1. It was an Android app (Xamarin Forms) and I did not obfuscate the app

If the key was in the app's code, it's quite possible it was extracted from there. While obfuscation helps to a degree, embedding secret or private keys in code is fragile, and bad practice. Yet it's common because the alternatives are more complex, and either hardly safer or not portable.

It's also entirely possible that a hack worked around the crypto without breaking it, e.g. that code which execution is conditioned by a cryptogram was executed without cryptogram, by bypassing the test.

When a standard API is used for the crypto, that API can be where a competent hacker watches, and that can be a disaster if confidential data transits here (this is the point of encryption). Or if the key transits here, which sometimes is unavoidable (when AES is used to communicate with another device or server, and the API does not have provision for encrypted loading/export of keys).

This app is reading information from QR Code encrypted content. An attacker is able to create a QR Code with fake information that becomes a valid QR code.

What about signing the QR code? The public key can be embedded in the app, and it becomes impossible to forge a QR code that the real app will tell genuine, no matter the reverse-engineering. For small QR codes, and if something standard is thought, ECDSA or EdDSA would be fine.

$\endgroup$
3
  • $\begingroup$ @kelalaka too. I realise it isn't likely the case here, but is it really that hard to brute force 80bits when we are dealing with human passwords? The attacker is surely getting to the key far quicker if they search likely word(s) rather than naively brute forcing. $\endgroup$
    – Modal Nest
    Dec 7, 2020 at 14:19
  • 1
    $\begingroup$ @ModalNest the question is how fast one can iterate the [A..Z0..1] compared to the standard iterator. It can be very effective and hashcat has a special syntax for this kind of problem. The bottleneck of this iteration cannot be more than $2^{48}$ for AES-128. $\endgroup$
    – kelalaka
    Dec 7, 2020 at 16:01
  • $\begingroup$ I've edited the Q. but not heavily. You can check if you want. $\endgroup$
    – kelalaka
    Dec 7, 2020 at 16:19
1
$\begingroup$

Let's start with a couple bad assumptions you made

 The app needs to operate in offline mode. 
 That's why I hardcode keys in the application.
    

Anytime you hardcode keys into an application, you have NO security. ALWAYS assume that an attacker can get your source code or reverse engineer it and can get what they want.

You should only consider an application secure when an attacker has your source code and knows all of your algorithms. Consider all of the standard encryption and hash algorithms. These are all public yet, given an attacker has all the source code for AES, it is still considered strong, even if the attacker knows the ciphertext and IV, but not the KEY. Similarly, SHA256 is considered unbroken even if the attacker knows the output and the algorithm, they cannot derive the original input.

 It was an Android app ( Xamarin Forms) and I did not obfuscate the app

Any time you are considering security using obfuscation, you are not spending your efforts wisely. If you think your application would have been secure if you obfuscated it, you are wrong. The application still needs to run in the Android environment and there are a ton of apps that will reverse engineer the code. If they reward is big enough, someone will spend the time. You may slow down an attacker a little, but only a little.

$\endgroup$
0
$\begingroup$

You should not give the key to anyone not authorized to encrypt and decrypt data with the key. The key should be providing the security, not your app.

The reason AES didn't provide you any security was that you were not using AES as your security mechanism. You were using your app as the security mechanism.

Are users supposed to be able to decode QR codes but not encode them? Then don't give them the key that encodes them. Use an asymmetric scheme like RSA or ECDSA and only give the user the key used to verify the QR codes.

You don't explain your requirements well, but it sounds like you simply aren't using the encryption scheme as the security scheme.

$\endgroup$

Your Answer

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

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