Blowfish在Java / Scala中加密并在bash中解密

时间:2016-05-20 19:09:44

标签: java bash scala encryption blowfish

我正在尝试构建一个工具来解密scala应用程序中加密的bash中的内容:

但首先,我要在两种语言中成功编码相同的消息并使它们相等:

给出密码“0123456789abcdef”
(十六进制:“30313233343536373839616263646566”和字节[]:[48,49,50,51,52,53,54,55,56,57,97,98,99 ,100,101,102])

scala> import javax.crypto.Cipher
scala> import javax.crypto.spec.SecretKeySpec
scala> val cipher = Cipher.getInstance("Blowfish")
scala> cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec("0123456789abcdef".getBytes("utf-8"), "Blowfish"))
scala> javax.xml.bind.DatatypeConverter.printBase64Binary(cipher.doFinal("message".getBytes("utf-8")))
res7: String = K679Jz06jmc=

但我无法在bash中使用openssl重现相同内容。

$ echo "message" | openssl enc -a -e -blowfish -nosalt -nopad -k "0123456789abcdef"
LJ3iFJ2/mYk=
$ echo "message" | openssl enc -a -e -blowfish -nosalt -nopad -k "30313233343536373839616263646566"
JkkJgYv3fQg=

任何提示? 谢谢!

2 个答案:

答案 0 :(得分:2)

标记OpenSSL更准确,OpenSSL从任何shell运行相同或根本没有shell。

默认情况下,OpenSSL enc执行基于密码的加密,其密钥(加IV)派生类似于(但不完全相同)PBKDF1。要使用密钥加密而非密码,您需要使用带有十六进制的大写-K,并且您需要指定-iv的至少一部分;另一方面-nosalt没用。

此外,echo命令会将换行符添加到它回显的数据中,并且“对一个NL”的加密与“一个人”的加密完全不同。一些操作系统和shell,取决于你使用的echo是内置的还是外部的,有办法省略换行符,但它们并不完全相同。 OTOH所有POSIX系统都支持printf,所以:

$ printf %s message | openssl enc -blowfish -K 30313233343536373839616263646566 -iv 00 -a
K679Jz06jmc=
编辑:Artjom是正确的; Java / Scala(可能)默认为ECB,这是一个坏主意;您应指定/CBC/CTR和填充。与aventurin不同,我认为你没有理由强迫自己进入/NoPadding的紧身衣; Java /PKCS5Padding与OpenSSL的默认兼容。对于CBC或CTR,您需要显式设置IV(第三个参数为Cipher.init)以获得确定性结果 - 您必须设置IV,或检索默认随机一,产生人们通常想要的 decryptable 结果。 OpenSSL enc -blowfish默认为CBC,但明确说明-bf-cbc-bf-ctr更为明确。或者-bf-ecb如果您真的想要ECB,如上所述是不推荐的。

答案 1 :(得分:2)

首先,如果你想拥有相同的密文,你必须确保Scala和OpenSSL加密使用相同的确定性加密算法和相同的输入参数。

由于OpenSSL使用CBC作为默认模式,因此我们在Scala中也这样做。

import javax.crypto.Cipher
import javax.crypto.spec._
import javax.xml.bind.DatatypeConverter

val cipher = Cipher.getInstance("Blowfish/CBC/NoPadding")

val key = new SecretKeySpec(DatatypeConverter.parseHexBinary("0123456789ABCDEF0123456789ABCDEF"), "Blowfish")

val specIv = new IvParameterSpec(DatatypeConverter.parseHexBinary("0000000000000000"))

cipher.init(Cipher.ENCRYPT_MODE, key, specIv)

val enc = cipher.doFinal("messages".getBytes("UTF-8"))

println(DatatypeConverter.printBase64Binary(enc))

请注意,如果没有填充,则输入长度必须是Blowfish块长度为64位的倍数。

使用OpenSSL,您必须明确指定相同的密钥和初始化向量(IV)

printf %s "messages" | openssl enc -e -blowfish -nopad -K "0123456789ABCDEF0123456789ABCDEF" -iv "0000000000000000" -base64

通过上面的例子,在两种情况下都会得到JSj0k4FwtG8=作为密文。