简体   繁体   English

如何在JAVA或SCALA中使用AES 256 CBC提取enc加密数据?

[英]How to extract the enc encrypted data using AES 256 CBC in JAVA or SCALA?

I need help on AES 256 Decryption using JAVA or SCALA. 我需要使用JAVA或SCALA进行AES 256解密的帮助。 I am able to extract using openssl . 我可以使用openssl提取。

Base 64 encoded Key: 5UX8IBWruBk1QmMZlZ1ESYmZRiC9w1DsrPpLIP9QF+Q= Base 64编码的密钥: 5UX8IBWruBk1QmMZlZ1ESYmZRiC9w1DsrPpLIP9QF+Q=

Base 64 encoded payload: U2FsdGVkX19XO99r3f7LgNbPTW8tKexv26mCPUYTMTTiwSSayFvB/QraYJkfzKjEB+tisqzzrU9aZu/tQ5CIVrHHwkUxpyjKEjx3N5q+Ba3weNK/NthpcCsNw5GQxl3NWGoDPe2IFXHMpvpy9xb2mbMnPtwr3m4nF3JzRD6Ft34Q7bHmmTCDkh5kEF9Hx+nbeiLURqLJ1S5YeGq7xhZqalimuQPwT7cr3MPkWPGyZVtNtrKJfIRStoMqP9F2qvm6 . Base 64编码的有效载荷: U2FsdGVkX19XO99r3f7LgNbPTW8tKexv26mCPUYTMTTiwSSayFvB/QraYJkfzKjEB+tisqzzrU9aZu/tQ5CIVrHHwkUxpyjKEjx3N5q+Ba3weNK/NthpcCsNw5GQxl3NWGoDPe2IFXHMpvpy9xb2mbMnPtwr3m4nF3JzRD6Ft34Q7bHmmTCDkh5kEF9Hx+nbeiLURqLJ1S5YeGq7xhZqalimuQPwT7cr3MPkWPGyZVtNtrKJfIRStoMqP9F2qvm6

OpenSSL decryption command: OpenSSL解密命令:

# 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. key.otkey提到的输入key.otkeydata.payload文件包含上面提到的base64解码的字符串。 I am able to decode using openssl and output : 我能够使用openssl和输出进行解码:

{"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: 但是我无法使用Scala代码提取:

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. 上面提到的json除外。 Thanks in advance.! 提前致谢。!

I think you're using your initialization vector (IV) wrong. 我认为您使用的初始化向量(IV)错误。

In your code you derive your ivParameterSpec (IV) from encData (in turn derived from payload ie encrypted data) 在您的代码中,您从encData派生了ivParameterSpec (IV)(又从有效载荷即加密数据派生了)

You don't specify it explicitly during encryption and based on openssl docs : 您不会在加密过程中基于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 得到IV,你需要从你使用的加密密钥文件使用openssl
  2. specify IV explicitly during encryption ( openssl -iv <IV here> ) and reuse it during decryption 在加密期间显式指定IV( openssl -iv <IV here> ),并在解密期间重用它

UPDATE: Also, check out this answer for code example (includes using proper IV). 更新:另外,请查看此答案以获取代码示例(包括使用正确的IV的示例)。

Finally i am able to decrypt the data for give encrypted file and -pass key using AES 256 bit CBC decoder. 最后,我能够使用AES 256位CBC解码器解密数据,以提供加密文件和-pass密钥。

$ 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: Scala代码:

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. 使用此函数调用aesDecryption(secret, encryptedData) ,我们就能解密数据。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM