使用Blowfish在Java中解密

你好,

我用Blowfish用Java加密和解密。

加密工作正常,但解密失败。

这是我的解密Java代码:

String encryptedString = … ; String decryptedString = null; SecretKeySpec key = new SecretKeySpec(myKey.getBytes(), "Blowfish"); Cipher cipher; try { cipher = Cipher.getInstance("Blowfish"); cipher.init(Cipher.DECRYPT_MODE, key); byte[] decrypted = cipher.doFinal(encryptedString.getBytes()); decryptedString = new String(decrypted, Charset.forName("UTF-8")); } [ catch Exceptions … ] 

我得到一个例外:

Exception. javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher

你能告诉我如何让它干活吗? 谢谢。

我给出的输入来自我的加密Java代码,Base64中的+编码,我在将它解释为解密操作之前从Base64解码。

将字节转换为hex和返回是很棘手的。 这应该可以解决您的问题。 (您需要修复encryptedString的字符串表示)

输出:

 StackOverflow 537461636B4F766572666C6F77 [83, 116, 97, 99, 107, 79, 118, 101, 114, 102, 108, 111, 119] J~3¹ÙÂÖ"¢ª„¨u 194A7E33B9060CD9C2D622A2AA84A875 [25, 74, 126, 51, -71, 6, 12, -39, -62, -42, 34, -94, -86, -124, -88, 117] StackOverflow 537461636B4F766572666C6F77 [83, 116, 97, 99, 107, 79, 118, 101, 114, 102, 108, 111, 119] 

码:

 import java.util.Arrays; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; public class Main { public static void main(String[] args) throws Exception { KeyGenerator keygenerator = KeyGenerator.getInstance("Blowfish"); SecretKey secretkey = keygenerator.generateKey(); String plaintextString = "StackOverflow"; System.out.println(plaintextString + " " + bytesToHex(plaintextString.getBytes()) + " " + Arrays.toString(plaintextString.getBytes())); SecretKeySpec key = new SecretKeySpec(secretkey.getEncoded(), "Blowfish"); Cipher cipher = Cipher.getInstance("Blowfish"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] encrypted = cipher.doFinal(plaintextString.getBytes()); String encryptedString = bytesToHex(encrypted); System.out.println(new String(encrypted) + " " + encryptedString + " " + Arrays.toString(encrypted)); cipher.init(Cipher.DECRYPT_MODE, key); byte[] decrypted = cipher.doFinal(hexToBytes(encryptedString)); String decryptedString = bytesToHex(decrypted); System.out.println(new String(decrypted) + " " + decryptedString + " " + Arrays.toString(decrypted)); } public static byte[] hexToBytes(String str) { if (str == null) { return null; } else if (str.length() < 2) { return null; } else { int len = str.length() / 2; byte[] buffer = new byte[len]; for (int i = 0; i < len; i++) { buffer[i] = (byte) Integer.parseInt(str.substring(i * 2, i * 2 + 2), 16); } return buffer; } } public static String bytesToHex(byte[] data) { if (data == null) { return null; } else { int len = data.length; String str = ""; for (int i = 0; i < len; i++) { if ((data[i] & 0xFF) < 16) str = str + "0" + java.lang.Integer.toHexString(data[i] & 0xFF); else str = str + java.lang.Integer.toHexString(data[i] & 0xFF); } return str.toUpperCase(); } } } 

你的myKey变量长度必须是8的倍数

 String encryptedString = … ; String decryptedString = null; SecretKeySpec key = new SecretKeySpec(myKey.getBytes(), "Blowfish"); private static byte[] linebreak = {}; // Remove Base64 encoder default linebreak private static Base64 coder; Cipher cipher; try { coder = new Base64(32, linebreak, true); cipher = Cipher.getInstance("Blowfish"); cipher.init(Cipher.DECRYPT_MODE, key); byte[] decrypted = cipher.doFinal(encryptedString.getBytes()); decryptedString = new String(coder.encode(decrypted)); } [ catch Exceptions … ] 

您可以使用Base64类来解决此问题。

现在我有了解决方案!

首先,Unicode有一些问题,所以我把ISO-8859-1放到了各处。 包括在Base64编码和解码。

然后,我和变种一起玩弄了。

这是我的Java代码,适用于Blowfish解密:

 String encryptedString = … ; String decryptedString = null; SecretKeySpec key = new SecretKeySpec(myKey.getBytes(CHARSET_ISO_8859_1), "Blowfish"); Cipher cipher; try { cipher = Cipher.getInstance("Blowfish/ECB/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, key); byte[] decrypted = cipher.doFinal(encryptedString.getBytes(CHARSET_ISO_8859_1)); decryptedString = new String(decrypted, CHARSET_ISO_8859_1); } [ catch Exceptions … ] 

请注意,我已将"Blowfish"替换为"Blowfish/ECB/PKCS5Padding"以获取Cipher实例,但是,如果您对密钥执行相同操作,则会失败。

密钥myKey必须是包含8个字符的Latin-1字符串。 这使得128位的密钥成为可能。 Blowfish算法允许更大的密钥,但由于JRE中的美国出口限制,它们在Java中失败 – 美国允许加密但不强于NSA可以破解的密码。

CHARSET_ISO_8859_1是一个常量,如下所示:

 final Charset CHARSET_ISO_8859_1 = Charset.forName("ISO-8859-1"); 

Charsetjava.nio.charset.Charset

最后但并非最不重要的是,我相应地更改了加密Java代码。

通过声明模式和填充,你肯定应该更明确地使用Cipher 。 这段代码是如何加密的? String encryptedString实际上是什么? 是hex编码还是base64编码? 如果没有编码,肯定会成为麻烦的来源。

试试这个

 private byte[] encrypt(String key, String plainText) throws GeneralSecurityException { SecretKey secret_key = new SecretKeySpec(key.getBytes(), ALGORITM); Cipher cipher = Cipher.getInstance(ALGORITM); cipher.init(Cipher.ENCRYPT_MODE, secret_key); return cipher.doFinal(plainText.getBytes()); } 

在这里你可以找到整个类与enc / dec — http://dexxtr.com/post/57145943236/blowfish-encrypt-and-decrypt-in-java-android