Blowfish在Java / Scala中加密并在bash中解密
我正在尝试构建一个工具来解密scala应用程序中加密的bash中的内容:
但首先,我要在两种语言中成功编码相同的消息并使它们相等:
鉴于密码“0123456789abcdef”
(hex:“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=
任何提示? 谢谢!
标记OpenSSL会更准确,OpenSSL从任何shell运行相同或根本不运行shell。
默认情况下,OpenSSL enc
执行基于密码的加密,其密钥(加IV)派生类似于(但不完全相同)PBKDF1。 要使用密钥而不是密码进行加密,您需要使用带有hex的UPPERCASE -K
,并且您需要至少指定-iv
一部分; 另一方面 – 无-nosalt
也没用。
此外, echo
命令为它echo
的数据添加换行符 ,“message NL”的加密与’messag e’的加密完全不同。 一些操作系统和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 或检索默认随机值,以产生可解密结果,人们通常都想要。 OpenSSL enc -blowfish
默认为CBC,但明确指出-bf-cbc
或-bf-ctr
更清楚。 或-bf-ecb
如果你真的想要ECB,如上所述是不推荐的。
首先,如果您希望使用相同的密文,则必须确保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=
密文。