1

I need help on AES 256 Decryption using JAVA or SCALA. I am able to extract using openssl.

Base 64 encoded Key: 5UX8IBWruBk1QmMZlZ1ESYmZRiC9w1DsrPpLIP9QF+Q=

Base 64 encoded payload: U2FsdGVkX19XO99r3f7LgNbPTW8tKexv26mCPUYTMTTiwSSayFvB/QraYJkfzKjEB+tisqzzrU9aZu/tQ5CIVrHHwkUxpyjKEjx3N5q+Ba3weNK/NthpcCsNw5GQxl3NWGoDPe2IFXHMpvpy9xb2mbMnPtwr3m4nF3JzRD6Ft34Q7bHmmTCDkh5kEF9Hx+nbeiLURqLJ1S5YeGq7xhZqalimuQPwT7cr3MPkWPGyZVtNtrKJfIRStoMqP9F2qvm6.

OpenSSL decryption command:

# extract the json from payload
$ openssl enc -d -aes-256-cbc -salt -in data.payload -out output.json -pass file:./key.otkey

input key.otkey mentioned above and data.payload file contain base64 decoded string mentioned above. I am able to decode using openssl and output :

{"fields":["NSN","store_busn_dt","all_net_sales_amt","all_net_sales_qty","dt_net_sale_qty","brfst_net_sale_qty"],"data":[[38099,"2018-04-01",7675.900000000001,998,752,262]]}

But i can't able to extract using Scala code:

import java.nio.charset.StandardCharsets
import java.util.Base64

import javax.crypto.Cipher
import javax.crypto.spec.SecretKeySpec
import javax.crypto.spec.IvParameterSpec
import javax.xml.bind.DatatypeConverter

object AesDecryption extends App {

  val key: String = "5UX8IBWruBk1QmMZlZ1ESYmZRiC9w1DsrPpLIP9QF+Q="
  val keyOut = Base64.getDecoder.decode(key)

  val otKey: SecretKeySpec = new SecretKeySpec(keyOut, "AES")

  val payload: String = "U2FsdGVkX19XO99r3f7LgNbPTW8tKexv26mCPUYTMTTiwSSayFvB/QraYJkfzKjEB+tisqzzrU9aZu/tQ5CIVrHHwkUxpyjKEjx3N5q+Ba3weNK/NthpcCsNw5GQxl3NWGoDPe2IFXHMpvpy9xb2mbMnPtwr3m4nF3JzRD6Ft34Q7bHmmTCDkh5kEF9Hx+nbeiLURqLJ1S5YeGq7xhZqalimuQPwT7cr3MPkWPGyZVtNtrKJfIRStoMqP9F2qvm6"

  val encryptedData: Array[Char] = payload.toCharArray
  //Base64.getDecoder.decode(payload)
  val encData: Array[Byte] = DatatypeConverter.parseBase64Binary(new String(encryptedData))
  println(new String(encData, StandardCharsets.ISO_8859_1))

  val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")

  // Generating IV.// Generating IV.
  val ivSize = 16
  val iv = new Array[Byte](ivSize)
  // Extract IV.// Extract IV.
  System.arraycopy(encData, 0, iv, 0, iv.length)
  val ivParameterSpec = new IvParameterSpec(iv)

  // extract data
  cipher.init(Cipher.DECRYPT_MODE, otKey, ivParameterSpec)
  val output: Array[Byte] = cipher.doFinal(encData)

  // print result
  println(new String(output, StandardCharsets.ISO_8859_1))

}

Output :

Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:989)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:845)
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
    at javax.crypto.Cipher.doFinal(Cipher.java:2165)

Excepted output above mentioned json. Thanks in advance.!

Rumesh Krishnan
  • 443
  • 4
  • 16

2 Answers2

2

I think you're using your initialization vector (IV) wrong.

In your code you derive your ivParameterSpec (IV) from encData (in turn derived from payload i.e. encrypted data)

You don't specify it explicitly during encryption and based on openssl docs:

If not explicitly given it will be derived from the password. See key derivation for details.

So, my advice here is to either:

  1. get IV you need to use from key file you use for encryption with openssl
  2. specify IV explicitly during encryption (openssl -iv <IV here>) and reuse it during decryption

UPDATE: Also, check out this answer for code example (includes using proper IV).

Eugene Loy
  • 12,224
  • 8
  • 53
  • 79
  • Is it possible to decrypt without `ivParameterSpec` ? Because `openssl` working without `iv`. – Rumesh Krishnan Jul 13 '18 at 13:13
  • @RumeshKrishnan you have to use some IV with CBC ciphers one way or another. It is just how CBC ciphers work. It plays role somewhat similar to SEED in random number generators. Now, it is true that you don't specify IV when you use `openssl`. But it is only because `openssl` internally derives IV for you from password (i.e. file you use in `openssl -pass ` ). – Eugene Loy Jul 13 '18 at 13:43
  • Thanks for you information. So, any pointer, how we can derive the `IV` from the password file? Kindly help me on this, i am new to this crypto world. – Rumesh Krishnan Jul 13 '18 at 13:49
  • @RumeshKrishnan If I am not mistaken you should add `-P` to your `openssl` encryption command to get all relevant data. – Eugene Loy Jul 13 '18 at 13:56
  • Thanks for all your guidelines. Now, i am able to decrpt using below code. :) – Rumesh Krishnan Jul 13 '18 at 16:52
0

Finally i am able to decrypt the data for give encrypted file and -pass key using AES 256 bit CBC decoder.

$ echo -n "U2FsdGVkX19XO99r3f7LgNbPTW8tKexv26mCPUYTMTTiwSSayFvB/QraYJkfzKjE
B+tisqzzrU9aZu/tQ5CIVrHHwkUxpyjKEjx3N5q+Ba3weNK/NthpcCsNw5GQxl3N
WGoDPe2IFXHMpvpy9xb2mbMnPtwr3m4nF3JzRD6Ft34Q7bHmmTCDkh5kEF9Hx+nb
eiLURqLJ1S5YeGq7xhZqalimuQPwT7cr3MPkWPGyZVtNtrKJfIRStoMqP9F2qvm6

"  | openssl enc -aes-256-cbc -salt -base64 -pass pass:5UX8IBWruBk1QmMZlZ1ESYmZRiC9w1DsrPpLIP9QF+Q= -d

Scala Code:

def aesDecryption(secret: String, data: String): String = {
    val decoded: Array[Byte] = Base64.getDecoder.decode(data)
    val salt = decoded.slice(8,16)
    val encryptedData = decoded.slice(16, decoded.length)
    val (key, iv) = getKeyIv(secret.getBytes(), salt)
    val sKeySpec = new SecretKeySpec(key, "AES")
    val ivSpec = new IvParameterSpec(iv)

    val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
    cipher.init(Cipher.DECRYPT_MODE, sKeySpec, ivSpec)
    new String(cipher.doFinal(encryptedData))   }

private def getKeyIv(password: Array[Byte], salt: Array[Byte]): (Array[Byte], Array[Byte]) = {
    val md5: MessageDigest = MessageDigest.getInstance("MD5")
    // first digest
    md5.update(password)
    md5.update(salt)
    val hash1 = md5.digest()
    // second digest
    md5.reset()
    md5.update(hash1)
    md5.update(password)
    md5.update(salt)
    val hash2 = md5.digest()
    // third digest
    md5.reset()
    md5.update(hash2)
    md5.update(password)
    md5.update(salt)
    val hash3 = md5.digest()
    val key = hash1.take(16) ++ hash2.take(16)
    val iv = hash3.take(16)
    (key, iv)   
}

aesDecryption(secret, encryptedData) using this functional call, we can able to decrypt the data.

Reference: https://github.com/chmduquesne/minibackup/blob/master/samples/OpensslAES.java

Rumesh Krishnan
  • 443
  • 4
  • 16