[英]Blowfish encrypt in Java/Scala and decrypt in bash
我正在嘗試構建一種工具來解密在Scala應用程序中加密的bash中的內容:
但是首先,我必須成功地用兩種語言編碼相同的消息並使它們相等:
給定密碼短語“ 0123456789abcdef”
(十六進制:“ 30313233343536373839616263646566”和byte []:[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。 要使用密鑰而不是密碼進行加密,您需要將UPPERCASE -K
與十六進制一起使用,並且需要至少指定-iv
一部分; 另一方面, -nosalt
是沒有用的。
同樣, echo
命令在其echo
的數據上添加換行符 ,“ message NL”的加密與“ messag e”的加密完全不同。 某些操作系統和外殼程序(取決於所使用的echo
是內置的還是外部的)可以省略換行符,但是它們並不完全相同。 OTOH所有POSIX系統都支持printf
,因此:
$ printf %s message | openssl enc -blowfish -K 30313233343536373839616263646566 -iv 00 -a
K679Jz06jmc=
編輯:Artjom是正確的; Java / Scala(可能)默認為ECB,這是一個壞主意; 您應該指定/CBC
或/CTR
和填充。 與東陵/NoPadding
不同,我認為您沒有理由強迫自己/NoPadding
; Java /PKCS5Padding
與OpenSSL的默認兼容。 對於CBC或CTR,您需要顯式設置IV(使用Cipher.init
的第三個參數)以獲得確定性的結果-您必須設置IV 或檢索默認的隨機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=
作為密文。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.