در این نوع الگوریتم ها دو کلید ایجاد میشه و کلیدهای رمزنگاری و رمزگشایی متفاوت هستن. مثل الگوریتم های متقارن ما بازم سعی میکنیم که امنیت کلید رو به بیشترین حد ممکن ایجاد کنیم(لینک گیت هاب پروژه و لینک مقاله اصلی).
بریم سراغ پیاده سازی ..
۱. الگوریتم نامتقارن انتخابی ما EC هست که این مورد هم جزو الگوریتم های معروف و شناخته شده هست. ما این کلید رو هم با استفاده از AndroidKeyStore میسازیم:
KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore")
۲. یک اسم برای این کلید انتخاب میکنیم. بعلاوه اینکه هدف مون از ایجاد کلید که ساین و وریفای هست رو بهش ست میکنیم:
KeyGenParameterSpec.Builder( "sample_asymmetric_key_alias", KeyProperties.PURPOSE_SIGN or KeyProperties.PURPOSE_VERIFY )
۳. طول کلید و همچنین نوع دایجست رو ست میکنیم:
setKeySize(256) setDigests(KeyProperties.DIGEST_SHA256)
۴. پارامتری ست میکنیم که این کلید فقط از طریق بایومتریک قابل دسترس باشه ولذا وقتی بخواییم ساین و وریفای کنیم کاربر باید فینگرپرینت فعال داشته باشه و از طریق دیالوگ prompt فینگرپرینت سیستم عامل مطمن بشیم که یوزر صاحب دیوایس هست:
setUserAuthenticationRequired(true)
۵. در هربار تولید سیگنیچر یک متن رمزشده رندوم تولید بشه تا از حملات ممکنه جلوگیری کنه:
setRandomizedEncryptionRequired(true)
۶. نوع دقیق مشخصه استاندارد الگوریتم تولید کلید EC رو ست میکنیم:
setAlgorithmParameterSpec(ECGenParameterSpec("secp256r1"))
۷. مدت زمان اعتبار کلید بعد از انجام بایومتریک صحیح:
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) }
توی مرحله بعد برای ساین یا sign از کد زیر استفاده میکنیم:
val plainMessage = ... // user input text val signature = Signature.getInstance("SHA256withECDSA").run { initSign(getPrivateKey()) update(plainMessage.toByteArray()) sign() }
و همچنین برای وریفای یا verify هم از کد زیر استفاده میکنیم:
val plainMessage = ... // user input text val signature = ... // signed message of user input val isVerified = Signature.getInstance("SHA256withECDSA").run { initVerify(getPublicKey()) update(plainMessage.toByteArray()) verify(signature.toByteArray()) }
در پایان ما یاد گرفتیم که چطور یک کلید نامتقارن و امن با کلی ویژگی های امنیتی در اندروید تولید کنیم و بعد از اون نحوه ساین و وریفای با استفاده از ترکیب اون کلیدها رو هم فرا گرفتیم.