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

Secure Derivation of Passwords on Android

XiaoyiLI
September 10, 2019

Secure Derivation of Passwords on Android

As Android developers, security matters in Android development. With the rapid growth of Android devices in the world, Security has never been as important as it is today, and it will never be an outdated subject.
Passwords or passphrases created by humans are often short or predictable enough to allow password cracking. Taking some examples of several common attacks we will explain why using the password directly for encryption and authentification is risky. We will understand how Secure Derivation of Passwords can prevent password cracking. And most important, we will talk about what are the solutions on Android.

In this talk you will learn password security on Android:
- Cryptographic knowledge about password cracking
- What is the key derivation
- Solutions for key derivation
- How to improve password security on Android using Password-based key derivation functions?
- What are the existing Android framework API solutions, the limitations, the improvements?
- On Android, how to use modern password-based key derivation functions such as PBKDF2 and Argon2

Android engineers interested in improving password security and understanding cryptographic in Android development are definitely recommended to come to this talk.

XiaoyiLI

September 10, 2019
Tweet

Other Decks in Technology

Transcript

  1. Encryption System Plaintext Something very secret Encryption AES 256 316B9FB70EAA0364D62

    A202370AC8ED4AF79F4 649EE27E30CFB5A69898 A50EB6 Password Encrypted Content
  2. Security • Insecure usages of Password • What is password

    hashing • How hashes are cracked • How to survive from password cracking • Implementation on Android
  3. Security • Insecure usages of Password • What is password

    hashing • How hashes are cracked • How to survive from password cracking • Implementation on Android
  4. Passwords created by humans • Short • Reused • Predictable

    • Example of passwords 123456 111111 qwerty abc123 password …
  5. Insecure usage of Passwords • Using the password directly •

    Brute-force attack or dictionary attack Plaintext Something very secret Encryption 316B9FB70EAA0364D62 A202370AC8ED4AF79F4 649EE27E30CFB5A69898 A50EB6 Password Encrypted Content
  6. Security • Insecure usages of Password • What is password

    hashing • How hashes are cracked • How to survive from password cracking • Implementation on Android
  7. Password Hashing • One-way functions • Fixed size generation •

    Identical output • Known algorithms • MD5, SHA-1, SHA-2 Password Password Cracking
  8. Security • Insecure usages of Password • What is password

    hashing • How hashes are cracked • How to survive from password cracking • Implementation on Android
  9. Brute Force and Dictionary Attacks Dictionary attacts Testing pass :

    failed Testing pig : failed Testing today : failed ... Testing dog : failed Testing secre1 : success Brute Force Attacks Testing a : failed Testing aa : failed Testing aaa : failed ... Testing abcdef : failed Testing abcdeg : success Large computation time
  10. Lookup Tables Attacks Pre-compute table that stores the hashes of

    the passwords # Hash MD5(’helloworld’) Hash Password 6ADFB18… helloworld E4BBE5B… android … … Pre-compute table
  11. Lookup Tables Attacks Searching 6ADFB183A4A2C94A2F92DAB5ADE762A47889A5A1 : helloworld Searching E4BBE5B7A4C1EB55652965AEE885DD59BD2EE7F4 :

    android Searching B3170BDFE0AC276B25861A17E34AD1F445B7C1D1 : pasSworD Searching CCF6837F82E177E414C83D2B4B932262A09DD557 : secreT Searching C4E4330172C276B362657264D996B8D26C46F1C7 : Not found Hash Password 6ADFB18… helloworld E4BBE5B… android … … Pre-compute table Require large space
  12. Rainbow Tables Attacks • Time-memory trade-off technique • Use Precomputed

    hash chains • Compare to brute-force attack • Less computer processing time • More storage • Compare to Lookup table attack • More computer processing time • Less storage
  13. Security • Insecure usages of Password • What is password

    hashing • How hashes are cracked • How to survive from password cracking • Implementation on Android
  14. How to survive from password cracking • Space • Time

    All defenses are about increasing the cost of attackers
  15. Increase the space by salt • Defense Lookup tables and

    rainbow tables attacks • Randomize the hashes - Salt • Salt is a non-secret value SHA256(‘’bv53fsdfce11C0 + password’’) = de7c8a55a24d5c38a09b36f5cff29f09c304691f383368133f587b4d1b4de801 SHA256(‘’ae5Pdiu49d0Lj + myword’’) = 4aa5e705cf736ff4802e7eb7e30431278f091674ce9864c0f6b33519bda955d0 SHA256(‘’Add948jfen3osP + helloworld’’) = ef65738f2f0c359b765ac9cb6535a83ec512b3a2d9372df1a2f77fef2e775769
  16. Common mistakes of using Salt • Salt reuse • Like

    no salt • Create a new rainbow table • Attack multiple users • One salt per user • Short salt • Create rainbow tables consisting of every possible salt User name Password Salt Hash Alice Hello bv5PewefV11Cd B9EFA700BAC9965458C170F72A46AD8A4B128860 Bob World bv5PewefV11Cd 357D5F4239F19A479D9D3055DEB21ECF8A5F3929 Alex @pwd123 bv5PewefV11Cd CD0EBF38006521834DD893FF8319AD05B5C372F4 Jon @pwd123 bv5PewefV11Cd CD0EBF38006521834DD893FF8319AD05B5C372F4
  17. Increase the time by Key derivation • Salt doesn’t prevent

    brute-force attacks • Make the hash funcion very slow • Fast enough for the users
  18. Increase the time by Key derivation - System Architecture Key

    Derivation Password Derived Key Plaintext Something very secret Encryption 316B9FB70EAA0364D62 A202370AC8ED4AF79F4 649EE27E30CFB5A69898 A50EB6 Encrypted Content
  19. Security • Insecure usages of Password • What is password

    hashing • How hashes are cracked • How to survive from password cracking • Implementation on Android
  20. Key derivation on Android – PBKDF2 • PBKDF2 – Password

    based key derivation function • API javax.crypto.SecretKeyFactory algorithms • PBKDF2WithHmacSHA1 since API level 1 • PBKDF2WithHmacSHA256 since API level 26 • Code example
  21. Key derivation on Android – PBKDF2 @Throws(NoSuchAlgorithmException::class, InvalidKeySpecException::class) fun generateKey(password:

    CharArray, salt: ByteArray): SecretKey { // Number of PBKDF2 hardening rounds to use val iterations = 1000 // Generate a 256-bit key val outputKeyLength = 256 val secretKeyFactory = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1") } else { SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256") } val keySpec = PBEKeySpec(password, salt, iterations, outputKeyLength) return secretKeyFactory.generateSecret(keySpec) }
  22. Key derivation on Android – PBKDF2 @Throws(NoSuchAlgorithmException::class, InvalidKeySpecException::class) fun generateKey(password:

    CharArray, salt: ByteArray): SecretKey { // Number of PBKDF2 hardening rounds to use val iterations = 1000 // Generate a 256-bit key val outputKeyLength = 256 val secretKeyFactory = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1") } else { SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256") } val keySpec = PBEKeySpec(password, salt, iterations, outputKeyLength) return secretKeyFactory.generateSecret(keySpec) }
  23. Key derivation on Android – PBKDF2 @Throws(NoSuchAlgorithmException::class, InvalidKeySpecException::class) fun generateKey(password:

    CharArray, salt: ByteArray): SecretKey { // Number of PBKDF2 hardening rounds to use val iterations = 1000 // Generate a 256-bit key val outputKeyLength = 256 val secretKeyFactory = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1") } else { SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256") } val keySpec = PBEKeySpec(password, salt, iterations, outputKeyLength) return secretKeyFactory.generateSecret(keySpec) }
  24. Key derivation on Android – PBKDF2 @Throws(NoSuchAlgorithmException::class, InvalidKeySpecException::class) fun generateKey(password:

    CharArray, salt: ByteArray): SecretKey { // Number of PBKDF2 hardening rounds to use val iterations = 1000 // Generate a 256-bit key val outputKeyLength = 256 val secretKeyFactory = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1") } else { SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256") } val keySpec = PBEKeySpec(password, salt, iterations, outputKeyLength) return secretKeyFactory.generateSecret(keySpec) } Migration
  25. More Secure Key derivation on Android – Argon2 • Computation

    cost on CPUs • Advantages of modern massively-parallel platforms like GPUs • Bcrypt, scrypt and, more recently, Argon2 The winner of the Password Hashing Competition • Argon2 compatibility • Android NDK with Argon2 source code • https://github.com/P-H-C/phc-winner-argon2 • Libsodium binding library
  26. NDK system architecture Java/Kotlin JNI Native C/C++ Native interfaces JNI

    export functions CPU based library armeabi-v7a, arm64_v8a, x86, x86_64
  27. Key derivation on Android – Argon2 Step 1: Compile Argon2

    or Libsodium source code based on the targetted Android architectures (arm64-v8a, x86_64 etc) Step 2: Define the native interface Step 3: Define the JNI export function Step 4: Call the argon2 API provided by the library
  28. Define the native interface # Android Kotlin object JniCrypto {

    external fun deriveKeyArgon2d( key: ByteArray, salt: ByteArray, t_cost: Int, m_cost: Int, parallelism: Int, derivedKeySize: Int ): ByteArray }
  29. Define the native interface # Android Kotlin object JniCrypto {

    external fun deriveKeyArgon2d( key: ByteArray, salt: ByteArray, t_cost: Int, m_cost: Int, parallelism: Int, derivedKeySize: Int ): ByteArray }
  30. Define the JNI export function in c++ files # Android

    JNI JNIEXPORT jbyteArray JNICALL Java_package_name_class_name_deriveKeyArgon2d(JNIEnv *env, jobject thiz, jbyteArray key, jbyteArray salt, jint t_cost, jint m_cost, jint parallelism, jint derivedKeySize) { // Convert JNI Data type to native type char *native_key = as_char_array(env, key); char *native_salt = as_char_array(env, salt); int native_keyLength = env->GetArrayLength(key); int native_saltLength = env->GetArrayLength(salt); // Call the argon2 API }
  31. Call the argon2 API provided by the library # Argon2

    Source Code int argon2d_hash_raw( const uint32_t t_cost, const uint32_t m_cost, const uint32_t parallelism, const void *pwd, const size_t pwdlen, const void *salt, const size_t saltlen, void *hash, const size_t hashlen);
  32. Take away • DO NOT WRITE YOUR OWN CRYPTO •

    Don't use passwords directly, use derived keys
  33. Insecure usage of Passwords Plaintext Something very secret Encryption 316B9FB70EAA0364D62

    A202370AC8ED4AF79F4 649EE27E30CFB5A69898 A50EB6 Password Encrypted Content
  34. Take away Key Derivation Password Derived Key Plaintext Something very

    secret Encryption 316B9FB70EAA0364D62 A202370AC8ED4AF79F4 649EE27E30CFB5A69898 A50EB6 Encrypted Content
  35. Take away • DO NOT WRITE YOUR OWN CRYPTO •

    Don't use passwords directly, use derived keys • Hash with Salt, long salt, non-reused salt • Keep away from insecure algorithms like MD5, SHA1, etc