[英]Java unreliable RSA encryption/decryption of strings
I have a very annoying problem with the unreliable encryption and decryption of string with the RSA algorithm in Java. 我用Java中的RSA算法对字符串进行不可靠的加密和解密有一个非常烦人的问题。 It seams to only work about 35% of the times, and I can't figure out why it sometimes does work and sometimes don't.
它接缝只能在35%的时间内工作,我无法弄清楚为什么它有时会起作用,有时却不起作用。 Here's some test-code I wrote to try to verify the randomness in the encryption/decryption.
这是我写的一些测试代码,试图验证加密/解密中的随机性。 It runs 100 laps and it encrypts and decrypts the same string every time and prints the number of times it was successful:
它运行100圈,每次加密和解密相同的字符串并打印成功的次数:
public static void main(String[] args) throws Exception {
byte[] dataToEncrypt = "Hello World!".getBytes("UTF-16LE");
byte[] cipherData = null;
byte[] decryptedData;
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(512);
KeyPair kp = kpg.genKeyPair();
Key publicKey = kp.getPublic();
Key privateKey = kp.getPrivate();
KeyFactory fact = KeyFactory.getInstance("RSA");
RSAPublicKeySpec pub = (RSAPublicKeySpec) fact.getKeySpec(publicKey,
RSAPublicKeySpec.class);
RSAPublicKeySpec spec = new RSAPublicKeySpec(pub.getModulus(), pub
.getPublicExponent());
KeyFactory factory = KeyFactory.getInstance("RSA");
PublicKey publicKeyRSA = factory.generatePublic(spec);
Cipher cipher = Cipher.getInstance("RSA");
int k = 0;
for (int i = 0; i < 100; i++) {
try {
cipher.init(Cipher.ENCRYPT_MODE, publicKeyRSA);
cipherData = cipher.doFinal(dataToEncrypt);
} catch (Exception e1) {
System.out.println("Encrypt error");
}
String s = new String(cipherData, "UTF-16LE");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
try {
decryptedData = cipher.doFinal(s.getBytes("UTF-16LE"));
System.out.println("Decrypted: "
+ new String(decryptedData, "UTF-16LE"));
k += 1;
} catch (Exception e1) {
System.out.println("Decrypt error");
}
}
System.out.println("Number of correct decryptions is: " + k);
}
I've tried to initialize the KeyPairGenerator with various values without any success. 我试图用各种值初始化KeyPairGenerator但没有成功。
Edit: Now it works like a charm, thanks to Base64 : 编辑:现在它就像魅力一样,感谢Base64 :
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PublicKey;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
public class Test {
public static void main(String[] args) throws Exception {
byte[] dataToEncrypt = "Hello World!".getBytes("UTF-16LE");
byte[] cipherData = null;
byte[] decryptedData;
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(512);
KeyPair kp = kpg.genKeyPair();
Key publicKey = kp.getPublic();
Key privateKey = kp.getPrivate();
KeyFactory fact = KeyFactory.getInstance("RSA");
RSAPublicKeySpec pub = (RSAPublicKeySpec) fact.getKeySpec(publicKey,
RSAPublicKeySpec.class);
RSAPublicKeySpec spec = new RSAPublicKeySpec(pub.getModulus(), pub
.getPublicExponent());
KeyFactory factory = KeyFactory.getInstance("RSA");
PublicKey publicKeyRSA = factory.generatePublic(spec);
Cipher cipher = Cipher.getInstance("RSA");
int k = 0;
for (int i = 0; i < 100; i++) {
try {
cipher.init(Cipher.ENCRYPT_MODE, publicKeyRSA);
cipherData = cipher.doFinal(dataToEncrypt);
} catch (Exception e1) {
System.out.println("Encrypt error");
}
String s = Base64.encodeBytes(cipherData);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
try {
decryptedData = cipher.doFinal(Base64.decode(s));
System.out.println("Decrypted: "
+ new String(decryptedData, "UTF-16LE"));
k += 1;
} catch (Exception e1) {
System.out.println("Decrypt error");
}
}
System.out.println("Number of correct decryptions is: " + k);
}
} }
This is the problem, or at least a problem: 这是问题,或者至少是一个问题:
String s = new String(cipherData, "UTF-16LE");
You're taking arbitrary binary data and trying to create a string from it, treating it as if it's UTF-16-encoded text. 你正在使用任意二进制数据并尝试从中创建一个字符串,将其视为UTF-16编码的文本。 It's not.
不是。 It's arbitrary binary data.
这是任意的二进制数据。
Either keep it in binary form (as byte[]
) or use base64 to convert it to text in a safe, reversible manner. 要么保持二进制形式(如
byte[]
),要么使用base64以安全,可逆的方式将其转换为文本。 ( This public domain base64 encoder has a reasonable API, for example.) (例如, 此公共域base64编码器具有合理的API。)
可能是因为您将加密的字节流转换为UTF16-LE,这是您不应该做的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.