Kotlin- RSA, AES, 3DES Encryption and Decryption with example

Quick Overview - RSA

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 1RSA Encryption and Decryption

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.*

class RSADemo {
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 = RSADemo()
// 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 2RSA Encryption and Decryption

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 3RSA Encryption and Decryption

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
}
}


Quick Overview - AES 

Advanced Encryption Standard which is a symmetric encryption algorithm. AES encryption is used by the U.S. for securing sensitive but unclassified material, so we can say it is enough secure. It allows 128 bit, 192 bit and 256-bit encryption. Symmetric encryption is very fast as compared to asymmetric encryption and are used in systems such as database system.

The following illustration highlights how symmetric cryptography works:



AES Encryption and Decryption example
import javax.crypto.Cipher
import java.io.UnsupportedEncodingException
import java.security.NoSuchAlgorithmException
import javax.crypto.spec.SecretKeySpec
import java.security.MessageDigest
import java.util.*

object AESDemo {
private var secretKey: SecretKeySpec? = null
private lateinit var key: ByteArray

// set Key
fun setKey(myKey: String) {
var sha: MessageDigest? = null
try {
key = myKey.toByteArray(charset("UTF-8"))
sha = MessageDigest.getInstance("SHA-1")
key = sha.digest(key)
key = Arrays.copyOf(key, 16)
secretKey = SecretKeySpec(key, "AES")
} catch (e: NoSuchAlgorithmException) {
e.printStackTrace()
} catch (e: UnsupportedEncodingException) {
e.printStackTrace()
}
}

// method to encrypt the secret text using key
fun encrypt(strToEncrypt: String, secret: String): String? {
try {
setKey(secret)
val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding")
cipher.init(Cipher.ENCRYPT_MODE, secretKey)
return Base64.getEncoder().encodeToString(cipher.doFinal
(strToEncrypt.toByteArray(charset("UTF-8"))))
} catch (e: Exception) {
println("Error while encrypting: $e")
}
return null
}

// method to encrypt the secret text using key
fun decrypt(strToDecrypt: String?, secret: String): String? {
try {
setKey(secret)
val cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING")
cipher.init(Cipher.DECRYPT_MODE, secretKey)
return String(cipher.doFinal(Base64.getDecoder().
decode(strToDecrypt)))
} catch (e: Exception) {
println("Error while decrypting: $e")
}
return null
}

@JvmStatic
fun main(args: Array<String>) {
// key
val secretKey = "secretkey"
// secret text
val originalString = "knowledgefactory.net"
// Encryption
val encryptedString = encrypt(originalString, secretKey)
// Decryption
val decryptedString = decrypt(encryptedString, secretKey)
// Printing originalString,encryptedString,decryptedString
println("Original String:$originalString")
println("Encrypted value:$encryptedString")
println("Decrypted value:$decryptedString")
}
}
Output:

Original String:knowledgefactory.net

Encrypted value:7W9JdoGEuWiV5EFdQxdyE+PYnj7WnkfeMhb3xU5uHgo=

Decrypted value:knowledgefactory.net


Quick Overview - 3DES

DES is a symmetric-key algorithm predicated on a Feistel network. As a symmetric key cipher, it utilizes the same key for both the encryption and decryption processes. The Feistel network makes both of these processes virtually precisely equipollent, which results in an algorithm that is more efficient to implement.

DES Encryption and Decryption example

import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
import javax.crypto.SecretKey
import java.util.Arrays
import java.security.MessageDigest

class DESDemo {
@Throws(Exception::class)
fun encrypt(message: String): ByteArray {
val md = MessageDigest.getInstance("md5")
val digestOfPassword = md.digest(
"HG58YZ3CR9"
.toByteArray(charset("utf-8"))
)
val keyBytes = Arrays.copyOf(digestOfPassword, 24)
var j = 0
var k = 16
while (j < 8) {
keyBytes[k++] = keyBytes[j++]
}
val key: SecretKey = SecretKeySpec(keyBytes, "DESede")
val iv = IvParameterSpec(ByteArray(8))
val cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding")
cipher.init(Cipher.ENCRYPT_MODE, key, iv)
val plainTextBytes = message.toByteArray(charset("utf-8"))
// final String encodedCipherText = new sun.misc.BASE64Encoder()
// .encode(cipherText);
return cipher.doFinal(plainTextBytes)
}

@Throws(Exception::class)
fun decrypt(message: ByteArray?): String {
val md = MessageDigest.getInstance("md5")
val digestOfPassword = md.digest(
"HG58YZ3CR9"
.toByteArray(charset("utf-8"))
)
val keyBytes = Arrays.copyOf(digestOfPassword, 24)
var j = 0
var k = 16
while (j < 8) {
keyBytes[k++] = keyBytes[j++]
}
val key: SecretKey = SecretKeySpec(keyBytes, "DESede")
val iv = IvParameterSpec(ByteArray(8))
val decipher = Cipher.getInstance("DESede/CBC/PKCS5Padding")
decipher.init(Cipher.DECRYPT_MODE, key, iv)

// final byte[] encData = new
// sun.misc.BASE64Decoder().decodeBuffer(message);
val plainText = decipher.doFinal(message)
return String(plainText)
}

companion object {
@Throws(Exception::class)
@JvmStatic
fun main(args: Array<String>) {
val text = "knowledgefactory.net"
val codedtext = DESDemo().encrypt(text)
val decodedtext = DESDemo().decrypt(codedtext)
println(codedtext)
println(decodedtext)
// This correctly shows "knowledgefactory.net"
}
}
}

Popular posts from this blog

Learn Java 8 streams with an example - print odd/even numbers from Array and List

Java Stream API - How to convert List of objects to another List of objects using Java streams?

Registration and Login with Spring Boot + Spring Security + Thymeleaf

Java, Spring Boot Mini Project - Library Management System - Download

ReactJS, Spring Boot JWT Authentication Example

Top 5 Java ORM tools - 2024

Java - Blowfish Encryption and decryption Example

Spring boot video streaming example-HTML5

Google Cloud Storage + Spring Boot - File Upload, Download, and Delete