Как извлечь зашифрованные данные с помощью AES 256 CBC в JAVA или SCALA? - PullRequest
0 голосов
/ 30 апреля 2018

Мне нужна помощь по расшифровке AES 256 с использованием JAVA или SCALA. Я могу извлечь, используя openssl.

Ключ кодированный Base 64: 5UX8IBWruBk1QmMZlZ1ESYmZRiC9w1DsrPpLIP9QF+Q=

Полезная нагрузка в кодировке Base 64: U2FsdGVkX19XO99r3f7LgNbPTW8tKexv26mCPUYTMTTiwSSayFvB/QraYJkfzKjEB+tisqzzrU9aZu/tQ5CIVrHHwkUxpyjKEjx3N5q+Ba3weNK/NthpcCsNw5GQxl3NWGoDPe2IFXHMpvpy9xb2mbMnPtwr3m4nF3JzRD6Ft34Q7bHmmTCDkh5kEF9Hx+nbeiLURqLJ1S5YeGq7xhZqalimuQPwT7cr3MPkWPGyZVtNtrKJfIRStoMqP9F2qvm6.

Команда расшифровки 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, упомянутый выше, и файл data.payload содержат расшифрованную строку base64, упомянутую выше. Я могу декодировать, используя 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]]}

Но я не могу извлечь, используя код 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))

}

Вывод:

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)

Исключен выход вышеупомянутого json. Заранее спасибо.!

Ответы [ 2 ]

0 голосов
/ 13 июля 2018

Наконец, я могу расшифровать данные для получения зашифрованного файла и ключа -pass, используя 256-битный CBC-декодер AES.

$ 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:

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) используя этот функциональный вызов, мы можем расшифровать данные.

Ссылка: https://github.com/chmduquesne/minibackup/blob/master/samples/OpensslAES.java

0 голосов
/ 13 июля 2018

Я думаю, что вы используете ваш вектор инициализации (IV) неправильно.

В вашем коде вы получаете ivParameterSpec (IV) из encData (в свою очередь, из полезной нагрузки, то есть зашифрованных данных)

Вы не указываете это явно во время шифрования и на основе openssl документов :

Если явно не указано, он будет получен из пароля. Подробнее смотрите в разделе «Вывод ключа».

Итак, мой совет здесь:

  1. получите IV, который вам нужно использовать из файла ключа, который вы используете для шифрования с openssl
  2. явно указать IV во время шифрования (openssl -iv <IV here>) и повторно использовать его во время расшифровки

ОБНОВЛЕНИЕ: Кроме того, проверьте этот ответ для примера кода (включая использование правильного IV).

...