Slide 1

Slide 1 text

͋Μ͍͟Ώ͖ (@yanzm) &ODSZQUFE4IBSFE1SFGFSFODFT͕ EFQSFDBUFEʹͳͬͪΌͬͨʂ Ͳ͏͠Α͏ʂ 1 2025.9.12 DroidKaigi 2025

Slide 2

Slide 2 text

:VLJ"O[BJ w "OESPJE&OHJOFFS w (PPHMF%FWFMPQFS&YQFSUGPS"OESPJE w 9 UXJUUFS !ZBO[N w CMPHZBO[NCMPHTQPUDPN w גࣜձࣾ΢ϑΟΧ୅දऔక໾ w ࡳຈɾؔ౦ڌ఺ੜ׆ 2

Slide 3

Slide 3 text

"HFOEB w +FUQBDL4FDVSJUZ w ͳͥඇਪ঑ EFQSFDBUFE ʹͳͬͨͷ͔ w Ҡߦઌͷબ୒ࢶ w ϚΠάϨʔγϣϯ w க໋తΫϥογϡ΁ͷରԠ 3

Slide 4

Slide 4 text

+FUQBDL4FDVSJUZ 4

Slide 5

Slide 5 text

+FUQBDL4FDVSJUZ +FU4FD w "OESPJE9ϥΠϒϥϦ܈ͷҰͭ w BOESPJEYTFDVSJUZάϧʔϓ w TFDVSJUZDSZQUPEFQSFDBUFE w TFDVSJUZBQQBVUIFOUJDBUPS w TFDVSJUZBQQBVUIFOUJDBUPSUFTUJOH w TFDVSJUZJEFOUJUZDSFEFOUJBM 5 https://developer.android.com/jetpack/androidx/releases/security https://developer.android.com/privacy-and-security/cryptography#security-crypto-jetpack-deprecated

Slide 6

Slide 6 text

TFDVSJUZDSZQUP w (PPHMF*0Ͱൃද w TUBCMF͸೥݄ w ηΩϡϦςΟͷϕετϓϥΫςΟεΛ؆ૉԽ͢ΔͨΊʹઃܭ͞ΕͨϥΠϒϥϦ w +$"ͷΑ͏ͳ௿Ϩϕϧ"1*͸ඇৗʹڧྗ͕ͩෳࡶͰޡ༻͠΍͍͢ w ઐ໳ՈʹΑͬͯݕূ͞Εͨ҆શͳσϑΥϧτઃఆΛఏڙ w NJO4EL7FSTJPOʢ"OESPJE.BSTINBMMPXʣ w ,FZ(FO1BSBNFUFS4QFDΛར༻͢ΔͨΊ 6 https://android-developers.googleblog.com/2019/05/whats-new-with-android-jetpack.html

Slide 7

Slide 7 text

ओཁͳػೳ w &ODSZQUFE4IBSFE1SFGFSFODFT w &ODSZQUFE'JMF 7 https://developer.android.com/reference/kotlin/androidx/security/crypto/package-summary

Slide 8

Slide 8 text

&ODSZQUFE4IBSFE1SFGFSFODFT w 4IBSFE1SFGFSFODFTΠϯλʔϑΣʔεΛ࣮૷͠ɺΩʔͱ஋ͷ྆ํΛࣗಈతʹ ҉߸Խ͢ΔΫϥε 8 val masterKey = MasterKey.Builder(context) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build() val pref: SharedPreferences = EncryptedSharedPreferences.create( context, "secret_shared_prefs", masterKey, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) pref.edit { … }

Slide 9

Slide 9 text

&ODSZQUFE'JMF w ϑΝΠϧͷಡΈॻ͖Λ҉߸Խ͢ΔϢʔςΟϦςΟ 9 val masterKey = MasterKey.Builder(context) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build() val encryptedFile = EncryptedFile.Builder( context, File(context.filesDir, "secret_data"), masterKey, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build() val encryptedOutputStream = encryptedFile.openFileOutput() val encryptedInputStream = encryptedFile.openFileInput()

Slide 10

Slide 10 text

಺෦ͷґଘؔ܎ w TFDVSJUZDSZQUPˠ5JOLˠ"OESPJE,FZTUPSFˠ0&. fi SNXBSF IBSEXBSF w 5JOL(PPHMF੡ͷϚϧνϓϥοτϑΥʔϜରԠͷΦʔϓϯιʔε҉߸ԽϥΠ ϒϥϦ w IUUQTHJUIVCDPNUJOLDSZQUPUJOLKBWB 10

Slide 11

Slide 11 text

಺෦ߏ଄૚ߏ଄γεςϜ w ϚελʔΩʔ"OESPJE,FZTUPSF಺ʹੜ੒ɾอ؅͞ΕɺΞϓϦͷϓϩηε ۭؒʹ͸ܾͯ͠࿐ग़͠ͳ͍ڧྗͳ伴 w Ωʔηοτ࣮ࡍͷσʔλΛ҉߸Խ͢ΔͨΊͷαϒΩʔͷू߹ମ 11 ϚελʔΩʔ Android Keystore ҉߸Խ σʔλ SharedPreferences ͷ XML Ωʔηοτ ҉߸Խ

Slide 12

Slide 12 text

&ODSZQUFE4IBSFE1SFGFSFODFTͷ҉߸ԽεΩʔϜ w ஋ͷ҉߸Խ w ඇܾఆతͳ"&4@($.Λ࢖༻ w ಉ͡ฏจΛෳ਺ճ҉߸Խͯ͠΋ɺຖճҟͳΔ҉߸จ͕ੜ੒͞ΕΔ w Ωʔͷ҉߸Խ w ܾఆతͳ"&4@4*7Λ࢖༻ w ಉ͡Ωʔ͸ৗʹಉ͡҉߸จʹม׵͞ΕΔ 12

Slide 13

Slide 13 text

&ODSZQUFE4IBSFE1SFGFSFODFTͷத਎ 13 12a90104ce… AYMKS+BZSF6B6Mmxan… 1288015e… 12a90104ce… AYMKS+C1JGpFULdDV… 1288015e… ಉ͡ฏจΛ҉߸Խͯ͠΋ ҟͳΔ҉߸จʹͳΔ ৗʹಉ͡҉߸จʹͳΔ

Slide 14

Slide 14 text

ͳͥඇਪ঑ EFQSFDBUFE ʹ ͳͬͨͷ͔ 14

Slide 15

Slide 15 text

ୈҰͷཁҼɿ҆ఆੑͷةػʢٕज़తཧ༝ʣ w ಛఆͷ0&.σόΠεͰൃੜͨ͠ɺճ෮ෆೳͳக໋తΫϥογϡ w ىಈ࣌ʹൃੜ͢Δ͜ͱ͕ଟ͘Ϣʔβʔ͕ΞϓϦΛશ͘࢖༻Ͱ͖ͳ͘ͳΔ w "OESPJEΤίγεςϜͷʮஅยԽʯ 15 https://issuetracker.google.com/issues/176215143 https://issuetracker.google.com/issues/370009394 https://issuetracker.google.com/issues/367562662 https://issuetracker.google.com/issues/147480931

Slide 16

Slide 16 text

ୈೋͷཁҼɿࢥ૝తస׵ʢηΩϡϦςΟ্ͷཧ༝ʣ w ʮͦͷσʔλ͸ɺຊ౰ʹσόΠε্ʹอଘ͢Δඞཁ͕͋Δͷ͔ʁʯ w ࠷΋҆શͳσʔλ͸ɺͦ΋ͦ΋อଘ͠ͳ͍σʔλ w 04ϨϕϧͷϑΝΠϧϕʔε҉߸Խ αϯυϘοΫεϞσϧʹΑΔอޢ w 04ͷอޢΛ৴ͯ͡ɺ༨ܭͳ҉߸Խ͸͠ͳ͍ w 04ͷอޢΛ௒͑Δ҉߸Խ͕ຊ౰ʹඞཁͳ΄Ͳػີੑ͕ߴ͍σʔλ w ։ൃऀ͸ந৅ԽʹཔΔͷͰ͸ͳ͘ɺͦͷϓϩηεΛ׬શʹཧղ͠ɺ੍ޚ͢ Δ੹೚Λෛ͏΂͖ 16

Slide 17

Slide 17 text

Ҡߦઌͷબ୒ࢶ 17

Slide 18

Slide 18 text

&ODSZQUFE4IBSFE1SFGFSFODFTͷҠߦઌ w TFDVSJUZDSZQUPΛ࢖͍ଓ͚Δ w 5JOLʢ಺෦Ͱ"OESPJE,FZTUPSF࢖༻ʣ 4IBSFE1SFGFSFODFT w 5JOLʢ಺෦Ͱ"OESPJE,FZTUPSF࢖༻ʣ %BUB4UPSF w "OESPJE,FZTUPSF $JQIFS 4IBSFE1SFGFSFODFT w "OESPJE,FZTUPSF $JQIFS %BUB4UPSF 18

Slide 19

Slide 19 text

"OESPJE,FZTUPSF $JQIFS 19

Slide 20

Slide 20 text

"OESPJE,FZTUPSF w ҉߸伴Λίϯςφ಺ʹ֨ೲ͠ɺσόΠε͔Βͷநग़Λࠔ೉ʹ͢Δ͜ͱΛ໨తͱ ͨ͠γεςϜϨϕϧͷαʔϏε w 伴ϚςϦΞϧͷඇΤΫεϙʔτੑ w ϋʔυ΢ΣΞϨϕϧͷอޢ w 5&& 5SVTUFE&YFDVUJPO&OWJSPONFOU 04ຊମ͔Β΋ִ཭͞Εͨɺϓϩ ηοα಺ͷ҆શͳ࣮ߦ؀ڥ w 4USPOH#PYઐ༻ͷ଱λϯύʔੑΛ࣋ͭϋʔυ΢ΣΞνοϓ 20

Slide 21

Slide 21 text

伴ͷΞΫηε੍ޚ w Ϣʔβʔೝূͷཁٻ w 伴ͷ࢖༻લʹࢦ໲ೝূ΍إೝূͳͲͷੜମೝূΛϢʔβʔʹཁٻ w ༗ޮظؒͷઃఆ w 伴͕༗ޮͳظؒʢ։࢝೔࣌ͱऴྃ೔࣌ʣΛࢦఆ w ҉߸Խύϥϝʔλͷ੍ݶ w ಛఆͷΞϧΰϦζϜɺϒϩοΫϞʔυɺύσΟϯάํࣜͰͷΈ伴ͷ࢖༻ΛڐՄ w ʜ 21

Slide 22

Slide 22 text

+BWB$SZQUPHSBQIZ"SDIJUFDUVSF +$" w +$"ͷΫϥεੜ੒࣌ʹϓϩόΠμͱͯ͠l"OESPJE,FZ4UPSFzΛࢦఆ͢Δ 22 val keyStore = KeyStore.getInstance("AndroidKeyStore") val keyPairGenerator = KeyPairGenerator.getInstance( KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore" ) val keyGenerator = KeyGenerator.getInstance( KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore" ) https://developer.android.com/privacy-and-security/keystore#UsingAndroidKeyStore

Slide 23

Slide 23 text

4FDSFU,FZͷੜ੒ 23 private const val ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore" private const val KEY_STORE_ALIAS = "my_data_key_store_alias" private fun getOrCreateSecretKey(): SecretKey { val keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_PROVIDER).apply { load(null) } if (keyStore.containsAlias(KEY_STORE_ALIAS)) { val entry = keyStore.getEntry(KEY_STORE_ALIAS, null) return (entry as KeyStore.SecretKeyEntry).secretKey } // 伴Λੜ੒ …

Slide 24

Slide 24 text

4FDSFU,FZͷੜ੒ 24 https://developer.android.com/privacy-and-security/cryptography#choose-algorithm

Slide 25

Slide 25 text

25 private const val ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore" private const val KEY_STORE_ALIAS = "my_data_key_store_alias" private fun getOrCreateSecretKey(): SecretKey { … // 伴Λੜ੒ val params = KeyGenParameterSpec.Builder( KEY_STORE_ALIAS, KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT ) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .setKeySize(256) .build() val keyGenerator = KeyGenerator.getInstance( KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE_PROVIDER ) keyGenerator.init(params) return keyGenerator.generateKey() }

Slide 26

Slide 26 text

"&4($./P1BEEJOH w "&"%ʢ"VUIFOUJDBUFE&ODSZQUJPOXJUI"TTPDJBUFE%BUBʣ҉߸ w σʔλͷػີੑʢ҉߸Խʣ͚ͩͰͳ͘ɺσʔλͷ׬શੑͱೝূੑʢվ͟ΜΛ ݕ஌͢Δೝূλάʣ΋ಉ࣌ʹఏڙ w ॳظԽϕΫτϧʢ*7*OJUJBMJ[BUJPO7FDUPSʣ 26

Slide 27

Slide 27 text

ॳظԽϕΫτϧʢ*7*OJUJBMJ[BUJPO7FDUPSʣ w ಉ͡伴Ͱಉ͡σʔλΛ҉߸Խͯ͠΋ɺຖճҟͳΔ҉߸จ͕Ͱ͖ΔΑ͏ʹ͢Δ ͨΊͷɺϥϯμϜͳσʔλ w "&4($.Ͱಉ͡伴ʹରͯ͠*7Λ࢖͍ճ͢ͷ͸ઈରʹμϝ 27

Slide 28

Slide 28 text

*7ͷ؅ཧํ๏  ҉߸Խૢ࡞ͷͨͼʹɺ҉߸࿦తʹ҆શͳ৽͍͠ϥϯμϜ*7Λੜ੒ʢ/*45ʹ ΑΔ($.Ͱͷ*7௕ͷਪ঑͸όΠτʣ w $JQIFS಺Ͱߦͬͯ͘ΕΔ  *7Λ҉߸จͱҰॹʹอଘʢҰൠతʹ͸*7Λ҉߸จͷઌ಄ʹ݁߹ʣ  ෮߸࣌ʹ͸ɺอଘ͓͍ͯͨ͠*7Λ࢖ͬͯ$JQIFSΛॳظԽ 28 http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf

Slide 29

Slide 29 text

29 private const val TRANSFORMATION = "AES/GCM/NoPadding" private const val IV_SIZE_BYTES = 12 private const val TAG_SIZE_BITS = 128 fun encrypt(plaintext: String): String { val cipher = Cipher.getInstance(TRANSFORMATION) cipher.init(Cipher.ENCRYPT_MODE, getOrCreateSecretKey()) val ciphertext = cipher.doFinal(plaintext.toByteArray(Charsets.UTF_8)) val ivAndCiphertext = cipher.iv + ciphertext // IV ͱ҉߸จΛ݁߹ return Base64.getEncoder().encodeToString(ivAndCiphertext) }

Slide 30

Slide 30 text

30 private const val TRANSFORMATION = "AES/GCM/NoPadding" private const val IV_SIZE_BYTES = 12 private const val TAG_SIZE_BITS = 128 fun decrypt(encryptedString: String): String { val cipher = Cipher.getInstance(TRANSFORMATION) val ivAndCiphertext = Base64.getDecoder().decode(encryptedString) // อଘ͓͍ͯͨ͠ IV Λ࢖༻ val spec = GCMParameterSpec(TAG_SIZE_BITS, ivAndCiphertext, 0, IV_SIZE_BYTES) cipher.init(Cipher.DECRYPT_MODE, getOrCreateSecretKey(), spec) val plaintextBytes = cipher.doFinal( /* input = */ ivAndCiphertext, /* inputOffset = */ IV_SIZE_BYTES, /* inputLen = */ ivAndCiphertext.size - IV_SIZE_BYTES ) return String(plaintextBytes, Charsets.UTF_8) }

Slide 31

Slide 31 text

5JOL 31

Slide 32

Slide 32 text

5JOL w IUUQTHJUIVCDPNUJOLDSZQUPUJOLKBWB w TFDVSJUZDSZQUPˠ5JOL+BWB w MBUFTU5JOL+BWB 32 implementation("com.google.crypto.tink:tink-android:1.18.0")

Slide 33

Slide 33 text

&ODSZQUFE4IBSFE1SFGFSFODFTͰͷ5JOL࢖༻ 33

Slide 34

Slide 34 text

&ODSZQUFE4IBSFE1SFGFSFODFTͰͷ5JOL࢖༻ 34 1.16.0 Ͱ௥Ճ

Slide 35

Slide 35 text

35

Slide 36

Slide 36 text

ΩʔηοτػೳΛ࢖Θͳ͍৔߹ 36 class TinkHelper { private val aead: Aead init { AeadConfig.register() if(!AndroidKeystore.hasKey(KEY_STORE_ALIAS)) { AndroidKeystore.generateNewAes256GcmKey(KEY_STORE_ALIAS) } aead = AndroidKeystore.getAead(KEY_STORE_ALIAS) } … }

Slide 37

Slide 37 text

37 class TinkHelper { private val aead: Aead … fun encrypt(plaintext: String): String { val plaintextBytes = plaintext.toByteArray(Charsets.UTF_8) val encrypted = aead.encrypt(plaintextBytes, ByteArray(0)) return Base64.getEncoder().encodeToString(encrypted) } fun decrypt(encryptedString: String): String { val encrypted = Base64.getDecoder().decode(encryptedString) val plaintextBytes = aead.decrypt(encrypted, ByteArray(0)) return String(plaintextBytes, Charsets.UTF_8) } }

Slide 38

Slide 38 text

ΩʔηοτػೳΛ࢖͍͍ͨ৔߹ 38

Slide 39

Slide 39 text

ΩʔηοτػೳΛ࢖͍͍ͨ৔߹ w Ωʔηοτػೳ͕ຊ౰ʹඞཁ͔ߟ͑Δ w ଎͕͞ඞཁʁʢ"OESPJE,FZTUPSFΛ࢖ͬͨ৔߹ΑΓ଎͍ʣ w ૚ߏ଄ͷηΩϡϦςΟ͕ඞཁʁ w 伴Λϩʔςʔγϣϯ͍ͨ͠ʁ w ΩʔόϦϡʔͷΩʔ໊΋҉߸Խ͢Δඞཁ͋Δʁ 39

Slide 40

Slide 40 text

ΩʔηοτػೳΛ࢖͍͍ͨ৔߹ w Ωʔηοτػೳ͕ຊ౰ʹඞཁ͔ߟ͑Δ w ଎͕͞ඞཁʁʢ"OESPJE,FZTUPSFΛ࢖ͬͨ৔߹ΑΓ଎͍ʣ w ૚ߏ଄ͷηΩϡϦςΟ͕ඞཁʁ w 伴Λϩʔςʔγϣϯ͍ͨ͠ʁ w ΩʔόϦϡʔͷΩʔ໊΋҉߸Խ͢Δඞཁ͋Δʁ w 5JOLͷΩʔηοτػೳΛΑ͘ཧղ͔ͯ͠Β࢖͏ 40

Slide 41

Slide 41 text

41 class TinkHelperWithKeyset(context: Context) { private val aead: Aead private val keysetPref: SharedPreferences by lazy { … } init { … val masterKeyAead = AndroidKeystore.getAead(KEY_STORE_MASTER_KEY_ALIAS) val keysetHex = keysetPref.getString("keyset_name", null) val handle = if (keysetHex == null) { KeysetHandle.generateNew(KeyTemplates.get("AES256_GCM").toParameters()).also { val encryptedKeyset = TinkProtoKeysetFormat.serializeEncryptedKeyset(it, masterKeyAead, ByteArray(0)) keysetPref.edit { putString("keyset_name", Hex.encode(encryptedKeyset)) } } } else { LegacyKeysetSerialization.parseEncryptedKeyset( BinaryKeysetReader.withBytes(Hex.decode(keysetHex)), masterKeyAead, ByteArray(0) ) } aead = handle.getPrimitive(RegistryConfiguration.get(), Aead::class.java) }

Slide 42

Slide 42 text

ϚΠάϨʔγϣϯ 42

Slide 43

Slide 43 text

ϚΠάϨʔγϣϯͷεςοϓ  ϚΠάϨʔγϣϯࡁΈ͔Ͳ͏͔νΣοΫ͢Δ w ྫʣϚΠάϨʔγϣϯࡁΈ͔Ͳ͏͔ͷϑϥάΛӬଓԽ͢Δ w ྫʣTFDVSJUZDSZQUPͷϚελʔΩʔ͕ଘࡏ͍ͯ͠Δ͔Ͳ͏͔Ͱ൑அ 43

Slide 44

Slide 44 text

ϚΠάϨʔγϣϯͷεςοϓ  ϚΠάϨʔγϣϯࡁΈ͔Ͳ͏͔νΣοΫ͢Δ  &ODSZQUFE4IBSFE1SFGFSFODFʹอଘ͍ͯ͠ΔσʔλΛϝϞϦ্ʹऔΓग़͢  ৽͘͠࡞੒ͨ͠"OESPJE,FZTUPSF $JQIFS ΋͘͠͸5JOL Ͱ҉߸Խ͢Δ  ৽͘͠࡞੒ͨ͠%BUB4UPSF4IBSFE1SFGFSFODFTʹอଘ͢Δ  TFDVSJUZDSZQUPͷΩʔηοτ͕อଘ͞Ε͍ͯͨ4IBSFE1SFGFSFODFTϑΝ ΠϧΛ࡟আ͢Δ  "OESPJE,FZTUPSF಺ͷTFDVSJUZDSZQUPͷϚελʔΩʔΛ࡟আ͢Δ 44

Slide 45

Slide 45 text

ϚελʔΩʔͱΩʔηοτͷ࡟আ 45 // delete SharedPreferences files deleteSharedPreferences("secret_shared_prefs") // delete MasterKey val keyStore = KeyStore.getInstance("AndroidKeyStore").apply { load(null) } if (keyStore.containsAlias(MasterKey.DEFAULT_MASTER_KEY_ALIAS)) { keyStore.deleteEntry(MasterKey.DEFAULT_MASTER_KEY_ALIAS) } EncryptedSharedPreferences.create( applicationContext, "secret_shared_prefs", … )

Slide 46

Slide 46 text

க໋తΫϥογϡ΁ͷରԠ 46

Slide 47

Slide 47 text

ใࠂ͞Ε͍ͯΔΫϥογϡͷཁҼ w όοΫΞοϓઃఆͷෆ଍ w 0&.σόΠεͷ"OESPJE,FZTUPSFͷόά 47

Slide 48

Slide 48 text

όοΫΞοϓઃఆͷෆ଍ 48 όοΫΞοϓ Android Keystore SharedPreferences ͷ XML σόΠε A σόΠε B Android Keystore ❌

Slide 49

Slide 49 text

όοΫΞοϓઃఆͷෆ଍ 49 όοΫΞοϓ Android Keystore SharedPreferences ͷ XML σόΠε A σόΠε B Android Keystore ❌

Slide 50

Slide 50 text

όοΫΞοϓઃఆͷෆ଍ 50 όοΫΞοϓ Android Keystore SharedPreferences ͷ XML σόΠε A σόΠε B Android Keystore ❌ SharedPreferences ͷ XML ෳ߹ԽͰ͖ͳ͍

Slide 51

Slide 51 text

όοΫΞοϓઃఆͷෆ଍ 51 όοΫΞοϓ Android Keystore SharedPreferences ͷ XML σόΠε A σόΠε B Android Keystore ❌ SharedPreferences ͷ XML ෳ߹ԽͰ͖ͳ͍ ❌

Slide 52

Slide 52 text

όοΫΞοϓઃఆ 52

Slide 53

Slide 53 text

53 … ಺ͱಉ͡ … https://developer.android.com/identity/data/autobackup?utm_source=chatgpt.com#IncludingFiles data_extraction_rules.xml EncryptedSharedPreferences.create() Ͱࢦఆ໊ͨ͠લ EncryptedFile.Builder Ͱ࢖ΘΕ͍ͯΔσϑΥϧτ໊ withSharedPref()Ͱࢦఆͨ͠ ໊લʢΩʔηοτͷอଘઌʣ ҉߸Խͨ͠σʔλͷอଘઌ

Slide 54

Slide 54 text

0&.σόΠεͷ"OESPJE,FZTUPSFͷόά 54 https://github.com/tink-crypto/tink/issues/535#issuecomment-912170221

Slide 55

Slide 55 text

"OESPJE,FZTUPSFͷόάʹରॲ͢Δ  ྫ֎ΛัଊͰ͖ΔΑ͏ʹ͢Δ  "OESPJE,FZTUPSF಺ͷ伴ɺ҉߸Խͨ͠σʔλ͕อଘ͞Ε͍ͯΔϑΝΠϧɺ ʢ5JOLΛ࢖͍ͬͯΔ৔߹͸ΩʔηοτʣΛ࡟আ͢Δ  σʔλΛ࠶औಘ͢ΔʢྫϢʔβʔʹϩάΠϯ͠௚ͯ͠΋Β͏ʣ  伴Λ࡞Γ௚͢  ৽͍͠伴Ͱ࠶औಘͨ͠σʔλΛ҉߸Խͯ͠อଘ͢Δ 55 ӬٱʹࣦΘΕͯࠔΔ΋ͷ͸อଘ͠ͳ͍ʢ࠶औಘͰ͖Δ΋ͷͷΈʹ͢Δʣ

Slide 56

Slide 56 text

·ͱΊ w ຊ౰ʹ҉߸Խ͢Δඞཁ͕͋Δͷ͔Α͘ߟ͑Δ w ӬٱʹࣦΘΕͯࠔΔ΋ͷ͸อଘ͠ͳ͍ w "OESPJE,FZTUPSF $JQIFS΋͘͠͸5JOLͰͷ҉߸ԽʹҠߦ͢Δ w ҉߸Խ͞Εͨσʔλ͕อଘ͞Ε͍ͯΔϑΝΠϧΛόοΫΞοϓର৅͔Βআ͘ w "OESPJE,FZTUPSFͷόάʹૺ۰͢ΔલఏͰରԠࡦΛ࣮૷͓ͯ͘͠ 56