What is RSA?
RSA operates on the principle of asymmetric cryptography, employing a public key for encryption and a private key for decryption. This means that anyone can use the public key to lock a message securely, but only the individual holding the private key can unlock and read it.
Android KeyStore
The Android KeyStore is a feature in Android devices that provides a secure way to store and manage cryptographic keys and sensitive information. Here’s a more detailed and understandable explanation.
Purpose: Securely stores and manages cryptographic keys and sensitive information.
Security: Keys are protected in a secure, often hardware-backed part of the device.
Operation: Apps perform cryptographic operations through the KeyStore without direct access to keys.
Hardware-backed: Utilizes Trusted Execution Environment (TEE) or Secure Element (SE) for extra security.
Developer Usage: Allows generation and management of keys for encryption, signing, and authentication.
User Benefits: Enhances security for apps handling sensitive data like banking and secure messaging.
Steps to generate public and private key
- Create a class EncryptionUtils and add generateKey function which returns the private and public key pair.
object EncryptionUtils {
private const val ANDROID_KEYSTORE = "AndroidKeyStore"
private const val KEY_ALIAS = "MytestAlias" // As per your requirment
fun generateKey(): KeyPair?{
val keyStore: KeyStore = KeyStore.getInstance(ANDROID_KEYSTORE).apply {
load(null)
}
val aliases: Enumeration<String> = keyStore.aliases()
val keyPair: KeyPair?
if (aliases.toList().firstOrNull { it == KEY_ALIAS } == null){
val keyPairGenerator: KeyPairGenerator = KeyPairGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_RSA,
ANDROID_KEYSTORE
)
val parameterSpec: KeyGenParameterSpec = KeyGenParameterSpec.Builder(
KEY_ALIAS,
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT )
.setBlockModes(KeyProperties.BLOCK_MODE_ECB)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
.build()
keyPairGenerator.initialize(parameterSpec)
keyPair = keyPairGenerator.genKeyPair()
}else{
val entry = keyStore.getEntry(KEY_ALIAS, null) as? KeyStore.PrivateKeyEntry
keyPair = KeyPair(entry?.certificate?.publicKey,entry?.privateKey)
}
return keyPair
}
}
2. Add below functions under EncryptionUtils to use public and private key
/**
* Returns the public key with alias [KEY_ALIAS].
*/
fun getPublicKey(): String? {
val keyPair = generateKey()
val publicKey = keyPair?.public ?: return null
return String(Base64.encode(publicKey.encoded, Base64.DEFAULT))
}
/**
* Returns the private key with alias [KEY_ALIAS].
*/
fun getPrivateKey(): PrivateKey? {
val keyPair = generateKey()
return keyPair?.private
}
3. Add encrypt and decrypt function to secure plain text
fun encrypt(data: String, publicKey: PublicKey): String {
val cipher: Cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding")
cipher.init(Cipher.ENCRYPT_MODE, publicKey)
val bytes = cipher.doFinal(data.toByteArray())
return Base64.encodeToString(bytes, Base64.DEFAULT)
}
fun decrypt(data: String, privateKey: PrivateKey?): String {
val cipher: Cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding")
cipher.init(Cipher.DECRYPT_MODE, privateKey)
val encryptedData = Base64.decode(data, Base64.DEFAULT)
val decodedData = cipher.doFinal(encryptedData)
return String(decodedData)
}
4. Add function to decode public key for locking data
fun decodePublicKey(publicKey: String?): PublicKey {
val decodedKey = Base64.decode(publicKey, Base64.DEFAULT)
// Convert the byte array back to PublicKey object
val keyFactory = KeyFactory.getInstance(KeyProperties.KEY_ALGORITHM_RSA)
val keySpec = X509EncodedKeySpec(decodedKey)
return keyFactory.generatePublic(keySpec)
}
You are done to write functions to generate private and public key under Android keyStore.
You can test encryption/decryption using below anywhere inside project
Job Offers
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val actualData = "Akash"
// getPublicKey will call generateKey internally and return the public key
val publicKey = EncryptionUtils.getPublicKey()
// base64 encoded publicKey, decodePublicKey will decode the value
val decodedPublicKey = EncryptionUtils.decodePublicKey(publicKey)
//encrypt data with public key
val encryptedData = EncryptionUtils.encrypt(actualData,decodedPublicKey)
// decrypt data with private key
val decryptedData = EncryptionUtils.decrypt(encryptedData,EncryptionUtils.getPrivateKey())
Log.e("CheckKeys","actualData $actualData")
Log.e("CheckKeys","encryptedData $encryptedData")
Log.e("CheckKeys","decryptedData $decryptedData")
}
}
Here, we learn how to create private and public key in android with data encryption — decryption.
You can connect me on