Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Encryption 101 on Android

Encryption 101 on Android

Avatar for Aung Kyaw Paing

Aung Kyaw Paing

November 22, 2025
Tweet

More Decks by Aung Kyaw Paing

Other Decks in Technology

Transcript

  1. Types of encryption • Symmetric Encryption ◦ Uses single key

    to encrypt/decrypt data at rest • Asymmetric Encryption ◦ Uses a public/private key pair to encrypt/decrypt a message transfer • Hybrid Encryption ◦ Uses both symmetric and asymmetric encryption to optimize message transfer
  2. JetSec Crypto 2019 2021 2023 May 2025 Today Retired in

    1.1.0 First stable version Deprecated in alpha07 First Alpha version Version 1.1.0 alpha06
  3. val KEY_ALIAS = "My Key Name" fun generateKeyInAndroidMasterKeyStore() { val

    keyGenParameterSpec = KeyGenParameterSpec.Builder( KEY_ALIAS, KeyProperties.PURPOSE_DECRYPT or KeyProperties.PURPOSE_ENCRYPT ) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .setKeySize(256) .build() val keyGenerator = KeyGenerator.getInstance("AES", "AndroidKeyStore") keyGenerator.init(keyGenParameterSpec) keyGenerator.generateKey() }
  4. val KEY_ALIAS = "My Key Name" fun generateKeyInAndroidMasterKeyStore() { val

    keyGenParameterSpec = KeyGenParameterSpec.Builder( KEY_ALIAS, KeyProperties.PURPOSE_DECRYPT or KeyProperties.PURPOSE_ENCRYPT ) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .setKeySize(256) .build() val keyGenerator = KeyGenerator.getInstance("AES", "AndroidKeyStore") keyGenerator.init(keyGenParameterSpec) keyGenerator.generateKey() }
  5. val KEY_ALIAS = "My Key Name" fun generateKeyInAndroidMasterKeyStore() { val

    keyGenParameterSpec = KeyGenParameterSpec.Builder( KEY_ALIAS, KeyProperties.PURPOSE_DECRYPT or KeyProperties.PURPOSE_ENCRYPT ) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .setKeySize(256) .build() val keyGenerator = KeyGenerator.getInstance("AES", "AndroidKeyStore") keyGenerator.init(keyGenParameterSpec) keyGenerator.generateKey() }
  6. val KEY_ALIAS = "My Key Name" fun generateKeyInAndroidMasterKeyStore() { val

    keyGenParameterSpec = KeyGenParameterSpec.Builder( KEY_ALIAS, KeyProperties.PURPOSE_DECRYPT or KeyProperties.PURPOSE_ENCRYPT ) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .setKeySize(256) .build() val keyGenerator = KeyGenerator.getInstance("AES", "AndroidKeyStore") keyGenerator.init(keyGenParameterSpec) keyGenerator.generateKey() }
  7. // Encrypt and Decrypt Non-Determinstically aead.encrypt(plaintext, aad) aead.decrypt(ciphertext, aad) //

    Encrypt and Decrypt Determinstically deterministicAead.encryptDeterministically(plaintext, aad) deterministicAead.decryptDeterministically(ciphertext, aad)
  8. // Encrypt and Decrypt Non-Determinstically aead.encrypt(plaintext, aad) aead.decrypt(ciphertext, aad) //

    Encrypt and Decrypt Determinstically deterministicAead.encryptDeterministically(plaintext, aad) deterministicAead.decryptDeterministically(ciphertext, aad)
  9. “Warning: because Android Keystore is unreliable, we strongly recommend disabling

    it by not setting any master key URI.” https://javadoc.io/static/com.google.crypto.tink/tink-android/1.16.0/com/google/ crypto/tink/integration/android/AndroidKeysetManager.html
  10. “When Android Keystore is disabled or otherwise unavailable, keysets will

    be stored in cleartext. This is not as bad as it sounds because keysets remain inaccessible to any other apps running on the same device. Moreover, as of July 2020, most active Android devices support either full-disk encryption or file-based encryption, which provide strong security protection against key theft even from attackers with physical access to the device. Android Keystore is only useful when you want to require user authentication for key use, which should be done if and only if you're absolutely sure that Android Keystore is working properly on your target devices. “ https://javadoc.io/static/com.google.crypto.tink/tink-android/1.16.0/com/google/ crypto/tink/integration/android/AndroidKeysetManager.html
  11. Android OS Encryption 4.4 7.0 10.0 Enforce FBE File-based encryption

    (FBE) Full-disk encryption (FDE) FDE encrypt the entire storage with single key. FBE encrypt individual files with multiple keys
  12. If you’re targeting minimum SDK 29 (Android 10), then you

    probably don’t need any encryption as the OS automatically encrypt your app’s internal directory with a unique keys.
  13. Application Sandbox In addition, Android application are executed in individual

    sandboxs so they cannot access the contents of other apps.
  14. val KEY_ALIAS = "My Key Name" fun generateKeyInAndroidMasterKeyStore() { val

    keyGenParameterSpec = KeyGenParameterSpec.Builder( KEY_ALIAS, KeyProperties.PURPOSE_DECRYPT or KeyProperties.PURPOSE_ENCRYPT ) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .setKeySize(256) .build() val keyGenerator = KeyGenerator.getInstance("AES", "AndroidKeyStore") keyGenerator.init(keyGenParameterSpec) keyGenerator.generateKey() }
  15. But if it’s stored in plain text, what if the

    hacker gain root access, that expose the data stored, can they not use this plain text key to decrypt?
  16. • To gain root access, you’d have to unlock bootloader,

    which would delete your internal data! ◦ An outlier is that some OS forks, like LineageOS, require unlocked bootloader to function. • Root detections are not reliable and hackers can still bypass these checks
  17. But what about attack that requires physical access? For example,

    root access is an elevation of privilege attack. If a hacker gain physical access (and root access), encryption is not going to protect your data at rest anyways. There is no way to really prevent this!
  18. The short is we don’t need encryption for data at

    rest. • Existence of JetSec Crypto implies that the default shared preferences has security flaw which is not true • False sense of security bring more harm because devs thought that user’s data are protected and started storing more and more sensitive datas. • However, some sector still requires this due to legal reasons. In that case, use this custom implementation.
  19. Do not store sensitive data Architecture your system so that

    sensitive data would only be stored on the backend and not on the frontend.
  20. Have short lifespan for sensitive data • Clear the data

    on the device as soon as possible ◦ Example: User logout, data no longer relevant after a certain operation • Use Worker to periodically clean data
  21. Remote wipe Allow user to force logout and wipe their

    data in the app through other means.