Kotlin - RSA Encryption and Decryption example
The RSA algorithm (Rivest-Shamir-Adleman) is a cryptographic algorithm that is used for specific security services or purposes, which enables public-key encryption and is widely used to secure sensitive data, particularly when it is being sent over an insecure network such as the HTTP. A public key is shared publicly, while a private key is secret and must not be shared with anyone.
The following illustration highlights how asymmetric cryptography works:
Example 1: The Cipher Type: RSA/ECB/PKCS1Padding
import java.security.spec.PKCS8EncodedKeySpec
import javax.crypto.Cipher
import java.security.spec.X509EncodedKeySpec
import java.io.IOException
import java.security.*
import java.util.*
/*
* RSA Key Size: 1024
* Cipher Type: RSA/ECB/PKCS1Padding
*/
class RSAKotlinDemo1 {
var privateKey: PrivateKey
var publicKey: PublicKey
companion object {
// convert String publickey to Key object
@Throws(GeneralSecurityException::class, IOException::class)
fun loadPublicKey(stored: String): Key {
val data: ByteArray = Base64.getDecoder().
decode(stored.toByteArray())
val spec = X509EncodedKeySpec(data)
val fact = KeyFactory.getInstance("RSA")
return fact.generatePublic(spec)
}
// Encrypt using publickey
@Throws(Exception::class)
fun encryptMessage(plainText: String, publickey: String): String {
val cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding")
cipher.init(Cipher.ENCRYPT_MODE, loadPublicKey(publickey))
return Base64.getEncoder().encodeToString(cipher.doFinal
(plainText.toByteArray()))
}
// Decrypt using privatekey
@Throws(Exception::class)
fun decryptMessage(encryptedText: String?, privatekey: String):
String {
val cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding")
cipher.init(Cipher.DECRYPT_MODE, loadPrivateKey(privatekey))
return String(cipher.
doFinal(Base64.getDecoder().decode(encryptedText)))
}
// Convert String private key to privateKey object
@Throws(GeneralSecurityException::class)
fun loadPrivateKey(key64: String): PrivateKey {
val clear: ByteArray = Base64.getDecoder().
decode(key64.toByteArray())
val keySpec = PKCS8EncodedKeySpec(clear)
val fact = KeyFactory.getInstance("RSA")
val priv = fact.generatePrivate(keySpec)
Arrays.fill(clear, 0.toByte())
return priv
}
@Throws(Exception::class)
@JvmStatic
fun main(args: Array<String>) {
val secretText = "www.knowledgefactory.net"
val keyPairGenerator = RSAKotlinDemo1()
// Generate private and public key
val privateKey: String = Base64.getEncoder().
encodeToString(keyPairGenerator.privateKey.encoded)
val publicKey: String = Base64.getEncoder().
encodeToString(keyPairGenerator.publicKey.encoded)
println("Private Key: $privateKey")
println("Public Key: $publicKey")
// Encrypt secret text using public key
val encryptedValue = encryptMessage(secretText, publicKey)
println("Encrypted Value: $encryptedValue")
// Decrypt
val decryptedText = decryptMessage(encryptedValue, privateKey)
println("Decrypted output: $decryptedText")
}
}
init {
val keyGen = KeyPairGenerator.getInstance("RSA")
keyGen.initialize(1024)
val pair = keyGen.generateKeyPair()
privateKey = pair.private
publicKey = pair.public
}
}
Output:
Private Key:
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANHdZHjuChS2Icoc+eUtPNLlhjZXgqPiy0o744sG/lBWdYyFamVcEBt28ExMxMtsznVrLQ9vz6V1eTNcwsuwjIfHePp4Vnedinc7U4CjqmhCY+tZab94iugJDLfh6Jbf7aDRcwuzbUK41VQwDWQcw5zcgIE0njfT3ULH/hqcSra9AgMBAAECgYBzu2CF49eBVnNJzzLr9Ed/kf2yiA3OLOqotGAmMiQaz6MhbA2heeSUEMIxgYBhIk60p/cAdUuQVjkRXw05YNINqwRuc4+/3pyNXXJ3EfyVLvjLePmdB2UFHvi+31WoXpbX1NNb8lf25G+5f58cgHsapjgWpGO9Bq2afPne1sZR4QJBAOpis/7Ytpbu68IiyukU8rNk4u+LtQXjyf3hX6NuccixSYurDTkmcPLOIJnXY9qmU2RFJjgP8bPHNo2QQyYRgVkCQQDlN8/MxNqSrZ8qSGLLJ37tCtECUnLn/tr6demUfJkLMxZI96cOi9v99DuTCISQdZDq1BS1hWNwwQ9ycuomdrAFAkApqyB6xwY28QTCv7K5GztGf0IE+h5VjLiFRQLeqCzcVABSLzermFTuJY0QLIWZAobCxbRUtSjwIBNnuWTmqKgJAkEAuvfAb0WvB+/JIYMz2oQX2yB0hhFcmvHeCmg9pBnR+DmulswzHwFj64zZP0C2aOMM1w8w6TOpfiJsCC3F4qPzRQJBAOQ6kJX8rEYAte9UI27IJ1o/JPGlatajCnHsJmzgHvkGhwqFVi9ip2DLBTAr2yRhWXnVp99tPlHTm3DY/yM/a7E=
Public Key:
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDR3WR47goUtiHKHPnlLTzS5YY2V4Kj4stKO+OLBv5QVnWMhWplXBAbdvBMTMTLbM51ay0Pb8+ldXkzXMLLsIyHx3j6eFZ3nYp3O1OAo6poQmPrWWm/eIroCQy34eiW3+2g0XMLs21CuNVUMA1kHMOc3ICBNJ43091Cx/4anEq2vQIDAQAB
Encrypted Value:
uJ0oo4f3XbaiBUpiO49vVHKyelbdk8CIT1kOgEaiJ8XcwqM4OPZt7sHMKMWPjFE/84KQnphPdbog8uPe5DF33xNE8D5UgN+RfsUai0PQEVX07DdkiW8GnlKN0UOR8iNQoP9Dp2ir3V9pc4bKggDk7V7IxmoyP/dkbU/Jgi9OPRg=
Decrypted output: www.knowledgefactory.net
Example 2: The Cipher Type: RSA/ECB/OAEPWithSHA-1AndMGF1Padding
import java.security.spec.PKCS8EncodedKeySpec
import javax.crypto.Cipher
import java.security.spec.X509EncodedKeySpec
import java.io.IOException
import java.security.*
import java.util.*
/*
* RSA Key Size: 2048
* Cipher Type: RSA/ECB/OAEPWithSHA-1AndMGF1Padding
*/
class RSAKotlinDemo2 {
var privateKey: PrivateKey
var publicKey: PublicKey
companion object {
// convert String publickey to Key object
@Throws(GeneralSecurityException::class, IOException::class)
fun loadPublicKey(stored: String): Key {
val data: ByteArray = Base64.getDecoder().
decode(stored.toByteArray())
val spec = X509EncodedKeySpec(data)
val fact = KeyFactory.getInstance("RSA")
return fact.generatePublic(spec)
}
// Encrypt using publickey
@Throws(Exception::class)
fun encryptMessage(plainText: String, publickey: String): String {
val cipher = Cipher.
getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding")
cipher.init(Cipher.ENCRYPT_MODE, loadPublicKey(publickey))
return Base64.getEncoder().encodeToString(cipher.doFinal
(plainText.toByteArray()))
}
// Decrypt using privatekey
@Throws(Exception::class)
fun decryptMessage(encryptedText: String?, privatekey: String):
String {
val cipher = Cipher.
getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding")
cipher.init(Cipher.DECRYPT_MODE, loadPrivateKey(privatekey))
return String(cipher.
doFinal(Base64.getDecoder().decode(encryptedText)))
}
// Convert String private key to privateKey object
@Throws(GeneralSecurityException::class)
fun loadPrivateKey(key64: String): PrivateKey {
val clear: ByteArray = Base64.getDecoder().
decode(key64.toByteArray())
val keySpec = PKCS8EncodedKeySpec(clear)
val fact = KeyFactory.getInstance("RSA")
val priv = fact.generatePrivate(keySpec)
Arrays.fill(clear, 0.toByte())
return priv
}
@Throws(Exception::class)
@JvmStatic
fun main(args: Array<String>) {
val secretText = "www.knowledgefactory.net"
val keyPairGenerator = RSAKotlinDemo2()
// Generate private and public key
val privateKey: String = Base64.getEncoder().
encodeToString(keyPairGenerator.privateKey.encoded)
val publicKey: String = Base64.getEncoder().
encodeToString(keyPairGenerator.publicKey.encoded)
println("Private Key: $privateKey")
println("Public Key: $publicKey")
// Encrypt secret text using public key
val encryptedValue = encryptMessage(secretText, publicKey)
println("Encrypted Value: $encryptedValue")
// Decrypt
val decryptedText = decryptMessage(encryptedValue, privateKey)
println("Decrypted output: $decryptedText")
}
}
init {
val keyGen = KeyPairGenerator.getInstance("RSA")
keyGen.initialize(2048)
val pair = keyGen.generateKeyPair()
privateKey = pair.private
publicKey = pair.public
}
}
Example 3: The Cipher Type: RSA/ECB/OAEPWithSHA-256AndMGF1Padding
import java.security.spec.PKCS8EncodedKeySpec
import javax.crypto.Cipher
import java.security.spec.X509EncodedKeySpec
import java.io.IOException
import java.security.*
import java.util.*
/*
* RSA Key Size: 4096
* Cipher Type: RSA/ECB/OAEPWithSHA-256AndMGF1Padding
*/
class RSAKotlinDemo3 {
var privateKey: PrivateKey
var publicKey: PublicKey
companion object {
// convert String publickey to Key object
@Throws(GeneralSecurityException::class, IOException::class)
fun loadPublicKey(stored: String): Key {
val data: ByteArray = Base64.getDecoder().
decode(stored.toByteArray())
val spec = X509EncodedKeySpec(data)
val fact = KeyFactory.getInstance("RSA")
return fact.generatePublic(spec)
}
// Encrypt using publickey
@Throws(Exception::class)
fun encryptMessage(plainText: String, publickey: String): String {
val cipher = Cipher.
getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding")
cipher.init(Cipher.ENCRYPT_MODE, loadPublicKey(publickey))
return Base64.getEncoder().encodeToString(cipher.doFinal
(plainText.toByteArray()))
}
// Decrypt using privatekey
@Throws(Exception::class)
fun decryptMessage(encryptedText: String?, privatekey: String):
String {
val cipher = Cipher.
getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding")
cipher.init(Cipher.DECRYPT_MODE, loadPrivateKey(privatekey))
return String(cipher.
doFinal(Base64.getDecoder().decode(encryptedText)))
}
// Convert String private key to privateKey object
@Throws(GeneralSecurityException::class)
fun loadPrivateKey(key64: String): PrivateKey {
val clear: ByteArray = Base64.getDecoder().
decode(key64.toByteArray())
val keySpec = PKCS8EncodedKeySpec(clear)
val fact = KeyFactory.getInstance("RSA")
val priv = fact.generatePrivate(keySpec)
Arrays.fill(clear, 0.toByte())
return priv
}
@Throws(Exception::class)
@JvmStatic
fun main(args: Array<String>) {
val secretText = "www.knowledgefactory.net"
val keyPairGenerator = RSAKotlinDemo3()
// Generate private and public key
val privateKey: String = Base64.getEncoder().
encodeToString(keyPairGenerator.privateKey.encoded)
val publicKey: String = Base64.getEncoder().
encodeToString(keyPairGenerator.publicKey.encoded)
println("Private Key: $privateKey")
println("Public Key: $publicKey")
// Encrypt secret text using public key
val encryptedValue = encryptMessage(secretText, publicKey)
println("Encrypted Value: $encryptedValue")
// Decrypt
val decryptedText = decryptMessage(encryptedValue, privateKey)
println("Decrypted output: $decryptedText")
}
}
init {
val keyGen = KeyPairGenerator.getInstance("RSA")
keyGen.initialize(4096)
val pair = keyGen.generateKeyPair()
privateKey = pair.private
publicKey = pair.public
}
}
More Kotlin related topics,
- WebSocket - Kotlin - Spring boot web application example
- Kotlin: RSA + AES a double layer security system
- Kotlin hashing - Using MD5, SHA-1, SHA-256, SHA-384, SHA-512, and PBKDF2
- Kotlin- AES, RSA, 3DES Encryption and Decryption with example
- Iterate over the Map, List, and Set in Kotlin! How?
- Kotlin Programming in Visual Studio Code IDE [Ubuntu]