تو این الگوریتم ها یک کلید واحد ساخته میشه که به وسیله اون ما سمت کلاینت اندروید رمزنگاری رو انجام میدیم و بعدا هم باید با همون کلید رمزگشایی رو هم انجام بدیم. ما سعی میکنیم که امنیت کلیدمون رو با بیشترین حد ممکن ایجاد کنیم(لینک گیت هاب پروژه و لینک مقاله اصلی).
بریم سراغ پیاده سازی ..
۱. الگوریتم انتخابی ما AES هست که جزو الگوریتم های پیچیده و امن توی دنیای آی تی شناخته میشه. بعلاوه اینکه این کلید رو با استفاده از AndroidKeyStore میسازیم. همونطور که میدونید KeyStore یه بخش محافظت شده ای هست که دسترسی به کلید تولید شده رو خیلی سخت میکنه:
KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore")
۲. برای این کلید یه اسم انتخاب میکنیم. بعلاوه اینکه هدف مون از ایجاد کلید که رمزنگاری و رمزگشایی هست رو بهش ست میکنیم:
KeyGenParameterSpec.Builder( "sample_symmetric_key_alias", KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT )
۳. سایز این کلید بعلاوه بلاک مود و همچنین نوع پدینگ رمزنگاری رو ست میکنیم:
setKeySize(256) setBlockModes(KeyProperties.BLOCK_MODE_GCM) setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
۴. این کلید فقط از طریق بایومتریک قابل دسترس باشه ولذا وقتی بخواییم رمزنگاری یا رمزگشایی کنیم کاربر باید فینگرپرینت فعال داشته باشه و از طریق دیالوگ prompt فینگرپرینت سیستم عامل مطمن بشیم که یوزر صاحب دیوایس هست:
setUserAuthenticationRequired(true)
۵. در هربار تولید متن رمزشده یک متن رمزشده رندوم تولید بشه تا از حملات ممکنه جلوگیری کنه:
setRandomizedEncryptionRequired(true)
۶. مدت زمان اعتبار کلید بعد از انجام بایومتریک صحیح:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { setUserAuthenticationParameters(10, KeyProperties.AUTH_BIOMETRIC_STRONG) } else { setUserAuthenticationValidityDurationSeconds(10) }
۷. اگر فینگرپرینت جدیدی توی دیوایس اضافه شد این کلید ما نامعتبر بشه:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { setInvalidatedByBiometricEnrollment(true) }
۸. موقع رمزگشایی حتما قفل صفحه باز باشه و اگر دیوایس از StrongBox پشتیبانی میکنه حتما فرآیند تولید کلید داخل اون انجام بشه(دو فضای ایجاد کلید TEE, StrongBox داریم)
val hasStrongBox = context.packageManager.hasSystemFeature(PackageManager.FEATURE_STRONGBOX_KEYSTORE) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { setUnlockedDeviceRequired(true) if(hasStrongBox) setIsStrongBoxBacked(true) }
توی مرحله بعد برای رمزنگاری یا encrypt از کد زیر استفاده میکنیم:
val plainText = ... // user input text val plainBytes = plainText.toByteArray(StandardCharsets.UTF_8) val key = keyStoreManager.getKeyWithAlias(KEY_ALIAS_SYMMETRIC) val cipher = Cipher.getInstance(AES_GCM_NOPADDING) cipher.init(Cipher.ENCRYPT_MODE, key) val initailVector = cipher.iv val encryptedBytes = cipher.doFinal(plainBytes)
و همچنین برای رمزگشایی یا decrypt هم از کد زیر استفاده میکنیم:
val encryptedBytes = ... // encrypted byte array val key = keyStoreManager.getKeyWithAlias(KEY_ALIAS_SYMMETRIC) val spec = GCMParameterSpec(AUTHENTICATION_TAG_SIZE, iv) val cipher = Cipher.getInstance(AES_GCM_NOPADDING) cipher.init(Cipher.DECRYPT_MODE, key, spec) val decryptedBytes = cipher.doFinal(encryptedBytes) val plainText = String(decryptedBytes, StandardCharsets.UTF_8)
در پایان ما یاد گرفتیم که چطور یک کلید متقارن و امن با کلی ویژگی های امنیتی در اندروید تولید کنیم و بعد از اون نحوه رمزنگاری و رمزگشایی با استفاده از اون کلید رو هم فرا گرفتیم.