· 7 years ago · May 23, 2018, 11:46 PM
1import java.security.SecureRandom
2import java.util.Base64
3
4import javax.crypto.spec.{GCMParameterSpec, SecretKeySpec}
5import javax.crypto.{Cipher, KeyGenerator, SecretKey}
6
7object Cryptor {
8
9 def main(args: Array[String]): Unit = {
10 val cryptor = new Cryptor("84AmEdqF7YTruR2o4^2BfwkSA0weHtEVgHz$7Rqy".getBytes)
11
12 val messageToEncrypt = "🤠Secret message ðŸ¤"
13
14 val encryptedText = cryptor.encrypt(messageToEncrypt)
15 System.out.println("Encrypted Text1: " + encryptedText)
16 val decryptedText = cryptor.decrypt(encryptedText)
17 System.out.println("Decrypted text: " + decryptedText)
18 }
19}
20
21class Cryptor(private val secret: Array[Byte]) {
22
23 private val AES_KEY_SIZE = 256
24 private val AES_KEY_SIZE_IN_BYTE = AES_KEY_SIZE / 8
25 private val IV_SIZE = 128
26 private val TAG_BIT_LENGTH = 128
27 private val ALGO_TRANSFORMATION_STRING = "AES/GCM/PKCS5Padding"
28 private val ALGO = "AES"
29
30 private val secureRandom = new SecureRandom()
31
32 def encrypt(message: String): String = {
33 val aesKey: SecretKey = generateAesKey()
34 val gcmParameterSpec = generateGcmParameterSpec()
35
36 val cipher = Cipher.getInstance(ALGO_TRANSFORMATION_STRING)
37 cipher.init(Cipher.ENCRYPT_MODE, aesKey, gcmParameterSpec, new SecureRandom())
38 cipher.updateAAD(secret)
39
40 val encryptedMessage = cipher.doFinal(message.getBytes)
41 encodeData(aesKey, gcmParameterSpec, encryptedMessage)
42 }
43
44 def decrypt(encryptedDataString: String): String = {
45 val (aesKey, gcmParameterSpec, encryptedMessage) = decodeData(encryptedDataString)
46
47 val cipher = Cipher.getInstance(ALGO_TRANSFORMATION_STRING)
48 cipher.init(Cipher.DECRYPT_MODE, aesKey, gcmParameterSpec, new SecureRandom())
49 cipher.updateAAD(secret)
50
51 val message = cipher.doFinal(encryptedMessage)
52 new String(message)
53 }
54
55 private def generateAesKey(): SecretKey = {
56 val keygen = KeyGenerator.getInstance(ALGO)
57 keygen.init(AES_KEY_SIZE)
58 keygen.generateKey
59 }
60
61 private def generateGcmParameterSpec(): GCMParameterSpec = {
62 val iv = new Array[Byte](IV_SIZE)
63 secureRandom.nextBytes(iv)
64 new GCMParameterSpec(TAG_BIT_LENGTH, iv)
65 }
66
67 private def encodeData(aesKey: SecretKey, gcmParameterSpec: GCMParameterSpec, encryptedMessage: Array[Byte]): String = {
68 val data = aesKey.getEncoded ++ gcmParameterSpec.getIV ++ encryptedMessage
69 Base64.getEncoder.encodeToString(data)
70 }
71
72 private def decodeData(encodedData: String): (SecretKeySpec, GCMParameterSpec, Array[Byte]) = {
73 val data = Base64.getDecoder.decode(encodedData)
74 val aesKey = new SecretKeySpec(data.take(AES_KEY_SIZE_IN_BYTE), ALGO)
75 val iv = data.slice(AES_KEY_SIZE_IN_BYTE, AES_KEY_SIZE_IN_BYTE + IV_SIZE)
76 val gcmParameterSpec = new GCMParameterSpec(TAG_BIT_LENGTH, iv)
77 val encryptedMessage = data.drop(AES_KEY_SIZE_IN_BYTE + IV_SIZE)
78 (aesKey, gcmParameterSpec, encryptedMessage)
79 }
80}