Blowfish在Java/Scala中加密,在bash中解密
我正在尝试构建一个工具来解密在scala应用程序中加密的bash中的内容: 但首先,我必须成功地用两种语言编码相同的信息,并使它们相等: 给定密码短语“0123456789abcdef”Blowfish在Java/Scala中加密,在bash中解密,java,bash,scala,encryption,blowfish,Java,Bash,Scala,Encryption,Blowfish,我正在尝试构建一个工具来解密在scala应用程序中加密的bash中的内容: 但首先,我必须成功地用两种语言编码相同的信息,并使它们相等: 给定密码短语“0123456789abcdef”(十六进制:“303132333435363373839616263646566”和字节[]:[48,49,50,51,52,53,54,55,56,57,97,98,99,100,101,102]) 但是我不能在bash中用openssl复制同样的内容 $ echo "message" | openssl en
(十六进制:“303132333435363373839616263646566”和字节[]:[48,49,50,51,52,53,54,55,56,57,97,98,99,100,101,102]) 但是我不能在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会更准确,它可以从任何shell或根本没有shell运行相同的操作 OpenSSL
enc
默认情况下进行基于密码的加密,密钥(加上IV)派生类似于(但不完全是)PBKDF1。要使用密钥而不是密码进行加密,需要将大写字母-K
与十六进制一起使用,并且需要至少指定-iv
的一部分;另一方面,-nosalt
是无用的
另外,echo
命令向其回显的数据添加一条换行符,并且“ME s a g e NL”的加密与“ME s a g 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,或检索默认的随机值,以生成人们通常想要的可解密结果。OpenSSLenc-blowfish
默认为CBC,但更清楚的是显式地声明-bf CBC
或-bf ctr
。或者-bf ecb
,如果您真的想要ecb,如上所述是不推荐的。标记OpenSSL会更准确,它可以从任何shell或根本没有shell运行相同的内容
OpenSSLenc
默认情况下进行基于密码的加密,密钥(加上IV)派生类似于(但不完全是)PBKDF1。要使用密钥而不是密码进行加密,需要将大写字母-K
与十六进制一起使用,并且需要至少指定-iv
的一部分;另一方面,-nosalt
是无用的
另外,echo
命令向其回显的数据添加一条换行符,并且“ME s a g e NL”的加密与“ME s a g 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,或检索默认的随机值,以生成人们通常想要的可解密结果。OpenSSLenc-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))
请注意,在没有填充的情况下,输入长度必须是64位Blowfish块长度的倍数
使用OpenSSL,您必须明确指定相同的密钥和初始化向量(IV)
在上述示例中,您将在这两种情况下获得作为密文的
JSj0k4FwtG8=
。首先,如果您想要拥有相同的密文,您必须确保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))
请注意,在没有填充的情况下,输入长度必须是64位Blowfish块长度的倍数
使用OpenSSL,您必须明确指定相同的密钥和初始化向量(IV)
在上面的例子中,在这两种情况下,您都会得到作为密文的
JSj0k4FwtG8=
。密码短语或密码不是密钥。您应该使用PBKDF(基于密码的密钥派生函数)从密码中创建密钥。否则,如果必须,请以十六进制或64进制指定二进制密钥。请注意,Java8JRE在Java.util
中有一个Base64
类。一般建议:始终使用完全限定的密码字符串Cipher.getInstance(“河豚”)根据默认的安全提供程序,code>可能会产生不同的密码。它很可能导致“河豚/ECB/PKCS5P添加”
,但不一定非得如此。如果它发生更改,您将失去不同JVM之间的兼容性。请不要使用。它是确定性的,因此在语义上不安全。您至少应该使用随机模式,如或。最好是对密文进行身份验证,这样就不可能进行类似的攻击。这可以通过诸如GCM或EAX之类的经过身份验证的模式或SCH来完成