class CipherHelper(val algorithm: String, val transformation: String, val iv: String? = null) { companion object { private const val ALGO_BLOWFISH = "Blowfish" private const val ALGO_AES = "AES" private const val ALGO_DES = "DES" // iv length of 8 fun getBlowfishInstance(iv: String) = CipherHelper(ALGO_BLOWFISH, "Blowfish/CBC/PKCS5Padding", iv) // iv length of 16 fun getAESInstance(iv: String) = CipherHelper(ALGO_AES, "AES/CBC/PKCS5Padding", iv) // iv length is 8 fun getDESInstance(iv: String) = CipherHelper(ALGO_DES, "DES/CBC/PKCS5Padding", iv) } private val cipher by lazy { Cipher.getInstance(transformation) } fun getSecretKey(secret: String): SecretKeySpec { val hash = when (algorithm) { ALGO_DES -> { val spec = DESKeySpec(secret.toByteArray()) val f = SecretKeyFactory.getInstance("DES") f.generateSecret(spec).encoded } ALGO_AES -> { val random = SecureRandom() val salt = ByteArray(16) random.nextBytes(salt) val spec = PBEKeySpec(secret.toCharArray(), salt, 65536, 128) val f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1") f.generateSecret(spec).encoded } else -> { // BLOWFISH secret.toByteArray() } } return SecretKeySpec(hash, algorithm) } fun encrypt(secret: SecretKey, value: String): String { val iv = IvParameterSpec(iv?.toByteArray()) cipher.init(Cipher.ENCRYPT_MODE, secret, iv) val data = cipher.doFinal(value.toByteArray()) return Base64.encodeToString(data, Base64.DEFAULT) } fun decrypt(secret: SecretKey, value: String): String { val iv = IvParameterSpec(iv?.toByteArray()) cipher.init(Cipher.DECRYPT_MODE, secret, iv) val data = Base64.decode( value, Base64.DEFAULT) return String(cipher.doFinal(data)) }}
Usage
val iv = "c16(}Hhx"val cipher = CipherHelper.getBlowfishInstance(iv)val secretKey = cipher.getSecretKey("3hb1L0x7moZA7OWtmi_mHPtxwl2GNxIDkk7A7bPM-Xo")val value = "I am Desmond"val encryptedValue = cipher.encrypt(secretKey, value)val decryptedValue = cipher.decrypt(secretKey, encryptedValue)
This weakness with this method is a static secret key which could be easily exposed. For a dynamic/secure secret key which is stored security within the application (unique for each application) usually used for password and app data encryption, do explore Android Keystore or Tink.
References: