喂,
我用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解码。
答案 0 :(得分:10)
将字节转换为十六进制和返回是很棘手的。这应该可以解决您的问题。 (您需要修复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();
}
}
}
答案 1 :(得分:3)
您的myKey变量长度必须是8的倍数
答案 2 :(得分:1)
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类来解决此问题。
答案 3 :(得分:1)
现在我有了解决方案!
首先,Unicode存在一些问题,所以我把ISO-8859-1放在了各处。 Including in the Base64 encoding and decoding.
然后,我和变种一起玩了。
这是我的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");
而Charset
是java.nio.charset.Charset
。
最后但并非最不重要的是,我相应地更改了加密Java代码。
答案 4 :(得分:0)
通过声明模式和填充,您应该更明确地使用Cipher
。这段代码是如何加密的? String
encryptedString
中的实际内容是什么?是十六进制编码还是base64编码?如果它没有编码,肯定会成为麻烦的来源。
答案 5 :(得分:0)
试试这个
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
的全班答案 6 :(得分:0)
试试{ /** * 初始化密码以进行解密 / cipher.init(Cipher.DECRYPT_MODE,secretKey); /* * 初始化输入输出流 */ inStream = new FileInputStream(encryptedFile); outStream = new FileOutputStream(decryptedFile); 字节[]缓冲区=新字节[1024]; 内里; 而 ((len = inStream.read(buffer)) > 0) { outStream.write(cipher.update(buffer, 0, len)); outStream.flush(); } outStream.write(cipher.doFinal()); inStream.close(); outStream.close(); }
答案 7 :(得分:0)
try {
/**
* Initialize the cipher for decryption
*/
cipher.init(Cipher.DECRYPT_MODE, secretKey);
/**
* Initialize input and output streams
*/
inStream = new FileInputStream(encryptedFile);
outStream = new FileOutputStream(decryptedFile);
byte[] buffer = new byte[1024];
int len;
while ((len = inStream.read(buffer)) > 0) {
outStream.write(cipher.update(buffer, 0, len));
outStream.flush();
}
outStream.write(cipher.doFinal());
inStream.close();
outStream.close();
}
...