I'm trying to decrypt AES on Scala (using javax.crypto.Cipher), the ciphertext was encrypted in Node.js app (using aes-js). and getting an error
Node (encryption)
var aesjs = require("aes-js");
// An example 128-bit key
var key = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ];
var key_128_array = new Uint8Array(key);
var key_128_hex = aesjs.utils.hex.fromBytes(key_128_array);
console.log(key_128_hex);
// 0102030405060708090a0b0c0d0e0f10
// Convert text to bytes
var text = 'TextMustBe16Byte';
var textBytes = aesjs.utils.utf8.toBytes(text);
var aesEcb = new aesjs.ModeOfOperation.ecb(key_128_array);
var encryptedBytes = aesEcb.encrypt(textBytes);
// To print or store the binary data, you may convert it to hex
var encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes);
console.log(encryptedHex);
// "a7d93b35368519fac347498dec18b458"
Scala (decryption)
import org.bouncycastle.jce.provider.BouncyCastleProvider
import javax.crypto.Cipher
val cipher = Cipher.getInstance("AES", new BouncyCastleProvider())
val key = "0102030405060708090a0b0c0d0e0f10";
val aesKeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES")
cipher.init(Cipher.DECRYPT_MODE, aesKeySpec)
val msg = "a7d93b35368519fac347498dec18b458"
val decrypted = cipher.doFinal(msg.getBytes())
log.debug(s"decrypted data ${decrypted}")
And I'm getting the following error:
javax.crypto.BadPaddingException: pad block corrupted
at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher$BufferedGenericBlockCipher.doFinal(Unknown Source)
at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(Unknown Source)
at javax.crypto.Cipher.doFinal(Cipher.java:2164)
...
Any idea what I'm doing wrong? Any help would be greatly appreciated.
The problem is with the key and message formats. Key is represented as hex sting and calling .getBytes
will return bytes of chars in UTF-8
and not actual key bytes. Java 8 has javax.xml.bind.DatatypeConverter
that can convert a hex string into correct Array[Byte]
. Same with msg
, it has to be converted correctly into Array[Byte]
You have to specify cipher AES/ECB/NoPadding
as you do use ecb
in node-js.
import javax.crypto.spec.SecretKeySpec
import javax.xml.bind.DatatypeConverter
object DecryptApp extends App {
import org.bouncycastle.jce.provider.BouncyCastleProvider
import javax.crypto.Cipher
val cipher = Cipher.getInstance("AES/ECB/NoPadding", new BouncyCastleProvider())
val key = "0102030405060708090a0b0c0d0e0f10"
val keyBytes = DatatypeConverter.parseHexBinary(key)
val aesKeySpec = new SecretKeySpec(keyBytes, "AES")
cipher.init(Cipher.DECRYPT_MODE, aesKeySpec)
val msg = "a7d93b35368519fac347498dec18b458"
val decrypted = cipher.doFinal(DatatypeConverter.parseHexBinary(msg))
println(s"decrypted data ${decrypted.map(_.toChar).mkString}")
}