Slide 1

Slide 1 text

Android Dev Summit 2019 extended Seoul AndroidX Security library Android Security kakaopay GDG Seoul Organizer Taehwan

Slide 2

Slide 2 text

য়ט ঌইࠅ ղਊ • AndroidX Security Library ࣗѐ • Library ࢎਊߨ • ࢎਊೞݶࢲ ઱੄ೡ ੼

Slide 3

Slide 3 text

੉ ߊ಴ীࢲ ঌ ࣻ হח Ѫٜ • Security Libraryਸ ઁ৻ ೠ ࠁউ਷ ঌ ࣽ হ׮.

Slide 4

Slide 4 text

੉ ੗ܐٜਸ ଵҊೞࣁਃ • ࠶۽Ӓ • 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

Slide 5

Slide 5 text

Android Dev Summit 2019 extended Seoul Security Library

Slide 6

Slide 6 text

Android Security

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

ঐഐച ҙ۲(Google Tink ࢎਊ) • Open source project • Multi-language(Java, C++, Obj-c ١) • cross-platform ജ҃ ૑ਗ https://github.com/google/tink

Slide 9

Slide 9 text

Android Dev Summit 2019 extended Seoul Use Security library

Slide 10

Slide 10 text

Use Security library dependencies { implementation "androidx.security:security-crypto:1.0.0-alpha02" }

Slide 11

Slide 11 text

ߡ੹੉ ݏ૑ ঋਵݶ 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)

Slide 12

Slide 12 text

Encrypted Shared Preferences

Slide 13

Slide 13 text

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) }

Slide 14

Slide 14 text

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ী ؀ೠ ঐഐച ߑध ૑੿

Slide 15

Slide 15 text

௏٘ ੸ਊ sharedPreferences .edit() .putString("edit", binding.editQuery.text.toString()) .apply() sharedPreferences.getString("edit", "") binding.tvShowQuery.text =

Slide 16

Slide 16 text

ز੘ ഛੋ • Input • Encryption • SharedPreferences • Decryption • TextView.text update

Slide 17

Slide 17 text

ؘ੉ఠ ਤ஖ ഛੋ • Device File Explorerܳ ੉ਊೠ ഛੋ • data/data/packageName/shared_prefs/fileName.xml

Slide 18

Slide 18 text

੿݈ ੜ ঐഐചغ঻ա? 12a9012625bdf450e290a64e2d986fef7dfc1eeb 2bbd155284109e023154109143a090d5cdcd013d7baa0e5a8a711bc2be890…001 128801a126068a44b9c8d90f866c9ad39506d 7c878dcd1933afb0555993979cee6078d131cb2b197439c7054….e9b90072001 AXIG/ 0eBMc6MsQjaAbOQUY8QijYBYnl4TKWnH+dcNIjKBfZqlyJtgbcMEcorjP71Vcc= Key editী ؀ೠ key/value

Slide 19

Slide 19 text

EncryptedFile

Slide 20

Slide 20 text

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()

Slide 21

Slide 21 text

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. ࢎਊೡ ঐഐച ؘ੉ఠ

Slide 22

Slide 22 text

Read/Write encryptedFile.openFileOutput().bufferedWriter().use { it.write(binding.editQuery.text.toString()) } val content = encryptedFile.openFileInput() .bufferedReader().useLines { lines -> lines.fold(" ") { working, line -> "$working $line" } } // Use content

Slide 23

Slide 23 text

ز੘ ഛੋ • Input • Encryption • SharedPreferences • Decryption • TextView.text update

Slide 24

Slide 24 text

ؘ੉ఠ ਤ஖ ഛੋ • Device File Explorerܳ ੉ਊೠ ഛੋ • ੷੢ೠ ҃۽۽ ੉ز • ৈӝࢲח data/data/packageName/cache/fileName.txt

Slide 25

Slide 25 text

੿݈ ੜ ঐഐചغ঻ա?

Slide 26

Slide 26 text

Warning

Slide 27

Slide 27 text

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); }

Slide 28

Slide 28 text

EncryptedFile • File openFileOutput ࢎਊ द ઱੄೧ঠ ೠ׮. • ੉޷ ࢤࢿػ زੌ ౵ੌ੉ ੓ਵݶ Exception ߊࢤ

Slide 29

Slide 29 text

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); }

Slide 30

Slide 30 text

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 ߊࢤ

Slide 31

Slide 31 text

౵ੌ ॳӝ ೧Ѿ ߑߨ val file = File(requireContext() .cacheDir, fileToRead) if (file.exists()) { file.delete() } • ӝઓ ౵ੌਸ ઁѢ • ৮੹ೠ ؘ੉ఠ ࣚप ઱੄ ೙ਃ • ӝઓ ౵ੌਸ ੍য ׮द ੷੢ • ࢜۽਍ ؘ੉ఠ append റ ੷੢

Slide 32

Slide 32 text

Biometric Authentication

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

Use Security library dependencies { implementation "androidx.biometric:biometric:1.0.1" }

Slide 35

Slide 35 text

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)

Slide 36

Slide 36 text

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) ঴ҷ ੋध੄ ҃਋ ୶о ߡౡ ഝࢿച ২࣌ ࢎਊ

Slide 37

Slide 37 text

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") } }

Slide 38

Slide 38 text

Biometric Authentication • onAuthenticationError • ஂࣗ, ࠺޻ߣഐ ࢎਊ, ײӝ ١ ݽٚ ী۞ח ৈӝ۽ • onAuthenticationSucceeded • Biometric ੋૐ ࢿҕ द ৈӝ۽ • onAuthenticationFailed • ੋૐ җ੿ীࢲ पಁೠ ҃਋ ৈӝ۽

Slide 39

Slide 39 text

Android Dev Summit 2019 extended Seoul End Taehwan [email protected]