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

Android Security(Security library, Biometric Auth)

TaeHwan
December 21, 2019

Android Security(Security library, Biometric Auth)

TaeHwan

December 21, 2019
Tweet

More Decks by TaeHwan

Other Decks in Programming

Transcript

  1. Android Dev Summit 2019 extended Seoul AndroidX Security library Android

    Security kakaopay GDG Seoul Organizer Taehwan
  2. ੉ ੗ܐٜਸ ଵҊೞࣁਃ • ࠶۽Ӓ • https://thdev.tech/android/2019/12/21/Android-Security-Library • ਬౚ࠳ •

    https://www.youtube.com/watch?v=0uG_RKiDmQY • https://youtu.be/W3mwSnF1n50 • ѐߊ ޙࢲ • https://developer.android.com/guide/topics/security/cryptography • https://developer.android.com/training/articles/keystore • https://github.com/google/tink • https://developer.android.com/topic/security/data • https://developer.android.com/training/sign-in/biometric-auth
  3. Security Library • MinSdk • API 23 - Android 6.0

    (Marshmallow) • Last version • alpha2 (May 23, 2019) • ઁҕೞח Ѫٜ • ঐഐച ҙ۲ : EncryptedFile, EncryptedSharedPreferences • KeyAlias ࢤࢿ : Android KeyStore ੉ਊೠ MasterKeys generator https://developer.android.com/guide/topics/security/cryptography
  4. ঐഐച ҙ۲(Google Tink ࢎਊ) • Open source project • Multi-language(Java,

    C++, Obj-c ١) • cross-platform ജ҃ ૑ਗ https://github.com/google/tink
  5. ߡ੹੉ ݏ૑ ঋਵݶ Manifest merger failed : uses-sdk:minSdkVersion 21 cannot

    be smaller than version 23 declared in library … Suggestion: use a compatible library with a minSdk of at most 21, or increase this project's minSdk version to at least 23, or use tools:overrideLibrary="androidx.security" to force usage (may lead to runtime failures)
  6. EncryptedSharedPreferences private val sharedPreferences: SharedPreferences by lazy { val keyGenParameterSpec

    = MasterKeys.AES256_GCM_SPEC val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec) EncryptedSharedPreferences.create( "security_test", masterKeyAlias, requireContext(), EncryptedSharedPreferences .PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences .PrefValueEncryptionScheme.AES256_GCM) }
  7. private val sharedPreferences: SharedPreferences by lazy { val keyGenParameterSpec =

    MasterKeys.AES256_GCM_SPEC val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec) EncryptedSharedPreferences.create( "security_test", masterKeyAlias, requireContext(), EncryptedSharedPreferences .PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences .PrefValueEncryptionScheme.AES256_GCM) } EncryptedSharedPreferences 1. Alias ࢤࢿ ః spec ੿੄ 2. Alias ࢤࢿ 3. ୡӝച 4. Preferences ౵ੌ ݺ 5. ࢤࢿೠ Alias 6. Keyী ؀ೠ ঐഐച ߑध ૑੿ 7. Valueী ؀ೠ ঐഐച ߑध ૑੿
  8. ؘ੉ఠ ਤ஖ ഛੋ • Device File Explorerܳ ੉ਊೠ ഛੋ •

    data/data/packageName/shared_prefs/fileName.xml
  9. ੿݈ ੜ ঐഐചغ঻ա? <?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <string

    name=“__androidx_security_crypto_encrypted_prefs_key_keyset__”>12a9012625bdf450e290a64e2d986fef7dfc1eeb 2bbd155284109e023154109143a090d5cdcd013d7baa0e5a8a711bc2be890…001</string> <string name=“__androidx_security_crypto_encrypted_prefs_value_keyset__”>128801a126068a44b9c8d90f866c9ad39506d 7c878dcd1933afb0555993979cee6078d131cb2b197439c7054….e9b90072001</string> <string name="ATL2UNefXJWYrZ1WL6QlgOVHj0zdG6R7Uw==">AXIG/ 0eBMc6MsQjaAbOQUY8QijYBYnl4TKWnH+dcNIjKBfZqlyJtgbcMEcorjP71Vcc=</string> </map> Key editী ؀ೠ key/value
  10. EncryptedFile val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec) val

    fileToRead = "my_sensitive_data.txt" val encryptedFile = EncryptedFile.Builder( File(requireContext().cacheDir, fileToRead), requireContext(), masterKeyAlias, EncryptedFile .FileEncryptionScheme .AES256_GCM_HKDF_4KB ).build()
  11. EncryptedFile val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec) val

    fileToRead = "my_sensitive_data.txt" val encryptedFile = EncryptedFile.Builder( File(requireContext().cacheDir, fileToRead), requireContext(), masterKeyAlias, EncryptedFile .FileEncryptionScheme .AES256_GCM_HKDF_4KB ).build() 1. Alias ࢤࢿ ః spec ੿੄ 2. Alias ࢤࢿ 3. ࢎਊೡ file name 4. EncryptedFile ୡӝച 5. ࢎਊೡ ౵ੌ ୡӝച 6. Key Alias 7. ࢎਊೡ ঐഐച ؘ੉ఠ
  12. ؘ੉ఠ ਤ஖ ഛੋ • Device File Explorerܳ ੉ਊೠ ഛੋ •

    ੷੢ೠ ҃۽۽ ੉ز • ৈӝࢲח data/data/packageName/cache/fileName.txt
  13. KeyAlias ߸҃? @NonNull public static String getOrCreate( @NonNull KeyGenParameterSpec spec)

    throws GeneralSecurityException, IOException { validate(spec); if (!MasterKeys.keyExists(spec.getKeystoreAlias())) { generateKey(spec); } return spec.getKeystoreAlias(); } • masterKeyAliasח String ߸ࣻ੉׮ • ߸҃ оמೞҊ, ز੘ী ޙઁহ׮. • ೞ૑݅ MasterKeys ࢎਊਸ ӂ੢ validate(spec); if (!MasterKeys.keyExists(spec.getKeystoreAlias())) { generateKey(spec); }
  14. EncryptedFile • File openFileOutput ࢎਊ द ઱੄೧ঠ ೠ׮. • ੉޷

    ࢤࢿػ زੌ ౵ੌ੉ ੓ਵݶ Exception ߊࢤ
  15. EncryptedFile @NonNull public FileOutputStream openFileOutput() throws GeneralSecurityException, IOException { if

    (mFile.exists()) { throw new IOException("output file already exists, please use a new file: " + mFile.getName()); } FileOutputStream fileOutputStream = new FileOutputStream(mFile); OutputStream encryptingStream = mStreamingAead.newEncryptingStream( fileOutputStream, mFile.getName().getBytes(UTF_8)); return new EncryptedFileOutputStream(fileOutputStream.getFD(), encryptingStream); }
  16. EncryptedFile @NonNull public FileOutputStream openFileOutput() throws GeneralSecurityException, IOException { if

    (mFile.exists()) { throw new IOException("output file already exists, please use a new file: " + mFile.getName()); } FileOutputStream fileOutputStream = new FileOutputStream(mFile); OutputStream encryptingStream = mStreamingAead.newEncryptingStream( fileOutputStream, mFile.getName().getBytes(UTF_8)); return new EncryptedFileOutputStream(fileOutputStream.getFD(), encryptingStream); } if (mFile.exists()) { throw new IOException("output file already exists, please use a new file: " + mFile.getName()); } زੌ ౵ੌ ݺਵ۽ Output ೡ ҃਋ Exception ߊࢤ
  17. ౵ੌ ॳӝ ೧Ѿ ߑߨ val file = File(requireContext() .cacheDir, fileToRead)

    if (file.exists()) { file.delete() } • ӝઓ ౵ੌਸ ઁѢ • ৮੹ೠ ؘ੉ఠ ࣚप ઱੄ ೙ਃ • ӝઓ ౵ੌਸ ੍য ׮द ੷੢ • ࢜۽਍ ؘ੉ఠ append റ ੷੢
  18. Biometric Authentication • MinSdk • API 23 - Android 6.0

    (Marshmallow) • Last version • 1.0.1 (December 18, 2019) https://developer.android.com/training/sign-in/biometric-auth
  19. Biometric Authentication val biometricPrompt = BiometricPrompt.PromptInfo.Builder() .setTitle("Biometric login for my

    app") .setSubtitle("Log in using your biometric credential") .setNegativeButtonText("Use account password") .setConfirmationRequired(true) .build() val biometric = BiometricPrompt( requireActivity(), ContextCompat.getMainExecutor(requireContext()), listener ) biometric.authenticate(biometricPrompt)
  20. Biometric Authentication val biometricPrompt = BiometricPrompt.PromptInfo.Builder() .setTitle("Biometric login for my

    app") .setSubtitle("Log in using your biometric credential") .setNegativeButtonText("Use account password") .build() val biometric = BiometricPrompt( requireActivity(), ContextCompat.getMainExecutor(requireContext()), listener ) biometric.authenticate(biometricPrompt) .setConfirmationRequired(true) ঴ҷ ੋध੄ ҃਋ ୶о ߡౡ ഝࢿച ২࣌ ࢎਊ
  21. Biometric Authentication val listener = object : BiometricPrompt.AuthenticationCallback() { override

    fun onAuthenticationError(errorCode: Int, errString: CharSequence) { super.onAuthenticationError(errorCode, errString) android.util.Log.i("TEMP", "Unlock error errorCode $errorCode errString $errString") } override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { super.onAuthenticationSucceeded(result) // Unlocked android.util.Log.i("TEMP", "Unlock success") } override fun onAuthenticationFailed() { super.onAuthenticationFailed() android.util.Log.i("TEMP", "Unlock failed") } }
  22. Biometric Authentication • onAuthenticationError • ஂࣗ, ࠺޻ߣഐ ࢎਊ, ײӝ ١

    ݽٚ ী۞ח ৈӝ۽ • onAuthenticationSucceeded • Biometric ੋૐ ࢿҕ द ৈӝ۽ • onAuthenticationFailed • ੋૐ җ੿ীࢲ पಁೠ ҃਋ ৈӝ۽