由于输入字符串,RSA 解密失败
RSA Decryption fails due to input string
我有以下问题。
我的代码中有 2 个函数,用于加密/解密简单字符串。
所以:
我必须将字符串“someString”传递给函数:
public static String doEncryption(String input) {
try {
if (!RSAService.areKeysPresent()) {
RSAService.generateKey();
}
ObjectInputStream inputStream;
// Encrypt the string using the public key
inputStream = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));
PublicKey publicKey = (PublicKey) inputStream.readObject();
byte[] cipherText = RSAService.encrypt(input, publicKey);
return cipherText.toString();
} catch (Exception e) {
e.printStackTrace();
}
return "ERROR: Public key file is probably missing";
}
函数doEncryption("someString")
returns[B@61decc8c]
现在我必须将这个字符串嵌入到 url 中,服务器端代码应该从那里获取它。
到目前为止一切都很好,但是当我调用函数时
public static String doDecryption(String input) {
try {
if (!RSAService.areKeysPresent()) {
RSAService.generateKey();
}
ObjectInputStream inputStream;
// Decrypt the cipher text using the private key.
inputStream = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
PrivateKey privateKey = (PrivateKey) inputStream.readObject();
String out = decrypt(input.getBytes(), privateKey);
return out;
} catch (Exception e) {
e.printStackTrace();
}
return "ERROR: Private key file is probably missing or doesn't match the public key";
}
doDecryption("[B@61decc8c")
尖叫,但有以下例外:
javax.crypto.BadPaddingException: Data must start with zero
at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:325)
at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:272)
at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:356)
at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:382)
at javax.crypto.Cipher.doFinal(Cipher.java:2087)
at rsaendecryptor.RSAService.decrypt(RSAService.java:132)
at rsaendecryptor.RSAService.doDecryption(RSAService.java:180)
at rsaendecryptor.RSAEnDecrypt.main(RSAEnDecrypt.java:20)
java.lang.NullPointerException
at java.lang.String.<init>(String.java:556)
at rsaendecryptor.RSAService.decrypt(RSAService.java:138)
at rsaendecryptor.RSAService.doDecryption(RSAService.java:180)
at rsaendecryptor.RSAEnDecrypt.main(RSAEnDecrypt.java:20)
有什么办法可以解决这个问题吗?我必须在客户端和服务器端之间传递字符串,因为它们甚至可以在不同的域中。更不用说字符串实际上会从 .Net 逻辑生成并发送到 Java 服务器端。字符串加密工作正常...我应该怎么做才能修复解密。
这是完整的 class 代码:
public class RSAService {
/**
* String to hold name of the encryption algorithm.
*/
public static final String ALGORITHM = "RSA";
/**
* String to hold the name of the private key file.
*/
public static final String PRIVATE_KEY_FILE = "private.key";
/**
* String to hold name of the public key file.
*/
public static final String PUBLIC_KEY_FILE = "public.key";
/**
* Generate key which contains a pair of private and public key using 1024
* bytes. Store the set of keys in Prvate.key and Public.key files.
*
*/
public static void generateKey() {
try {
final KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);
keyGen.initialize(1024);
final KeyPair key = keyGen.generateKeyPair();
File privateKeyFile = new File(PRIVATE_KEY_FILE);
File publicKeyFile = new File(PUBLIC_KEY_FILE);
// Create files to store public and private key
privateKeyFile.createNewFile();
if (publicKeyFile.getParentFile() != null) {
publicKeyFile.getParentFile().mkdirs();
}
publicKeyFile.createNewFile();
// Saving the Public key in a file
ObjectOutputStream publicKeyOS = new ObjectOutputStream(
new FileOutputStream(publicKeyFile));
publicKeyOS.writeObject(key.getPublic());
publicKeyOS.close();
// Saving the Private key in a file
ObjectOutputStream privateKeyOS = new ObjectOutputStream(
new FileOutputStream(privateKeyFile));
privateKeyOS.writeObject(key.getPrivate());
privateKeyOS.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* The method checks if the pair of public and private key has been
* generated.
*
* @return flag indicating if the pair of keys were generated.
*/
public static boolean areKeysPresent() {
File privateKey = new File(PRIVATE_KEY_FILE);
File publicKey = new File(PUBLIC_KEY_FILE);
if (privateKey.exists() && publicKey.exists()) {
return true;
}
return false;
}
/**
* Encrypt the plain text using public key.
*
* @param text : original plain text
* @param key :The public key
* @return Encrypted text
* @throws java.lang.Exception
*/
public static byte[] encrypt(String text, PublicKey key) {
byte[] cipherText = null;
try {
// get an RSA cipher object and print the provider
final Cipher cipher = Cipher.getInstance(ALGORITHM);
// encrypt the plain text using the public key
cipher.init(Cipher.ENCRYPT_MODE, key);
cipherText = cipher.doFinal(text.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
return cipherText;
}
/**
* Decrypt text using private key.
*
* @param text :encrypted text
* @param key :The private key
* @return plain text
* @throws java.lang.Exception
*/
public static String decrypt(byte[] text, PrivateKey key) {
byte[] dectyptedText = null;
try {
// get an RSA cipher object and print the provider
final Cipher cipher = Cipher.getInstance(ALGORITHM);
// decrypt the text using the private key
cipher.init(Cipher.DECRYPT_MODE, key);
dectyptedText = cipher.doFinal(text);
} catch (Exception ex) {
ex.printStackTrace();
}
return new String(dectyptedText);
}
public static String doEncryption(String input) {
try {
if (!RSAService.areKeysPresent()) {
RSAService.generateKey();
}
ObjectInputStream inputStream;
// Encrypt the string using the public key
inputStream = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));
PublicKey publicKey = (PublicKey) inputStream.readObject();
byte[] cipherText = RSAService.encrypt(input, publicKey);
return cipherText.toString();
} catch (Exception e) {
e.printStackTrace();
}
return "ERROR: Public key file is probably missing";
}
public static String doDecryption(String input) {
try {
if (!RSAService.areKeysPresent()) {
RSAService.generateKey();
}
ObjectInputStream inputStream;
// Decrypt the cipher text using the private key.
inputStream = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
PrivateKey privateKey = (PrivateKey) inputStream.readObject();
String out = decrypt(input.getBytes(), privateKey);
return out;
} catch (Exception e) {
e.printStackTrace();
}
return "ERROR: Private key file is probably missing or doesn't match the public key";
}
}
感谢 shikjohari 和这篇文章 here 我能够修复我的代码!
在doEncryption()
方法中我修改了return如下:
return (Base64.encode(cipherText)).toString();
并且在 doDecryption()
方法中我修改了 return 如下:
String out = decrypt(Base64.decode(input), privateKey);
return out;
您可以从我的第一个 post 中获取完整代码,只需按照此 post 编辑两个方法的 returns。希望这有帮助。
public static String doEncryption(String input)
到此为止。字符串不是二进制数据的容器,因此一开始就不应该用来包含密文。它应该作为 byte[]
.
传递
注意,当您遇到异常时,不要猜测条件是什么,return 一个说明它 'probably' 是什么的字符串。它使调试成为一种猜测。使用异常附带的消息。
我有以下问题。 我的代码中有 2 个函数,用于加密/解密简单字符串。
所以:
我必须将字符串“someString”传递给函数:
public static String doEncryption(String input) {
try {
if (!RSAService.areKeysPresent()) {
RSAService.generateKey();
}
ObjectInputStream inputStream;
// Encrypt the string using the public key
inputStream = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));
PublicKey publicKey = (PublicKey) inputStream.readObject();
byte[] cipherText = RSAService.encrypt(input, publicKey);
return cipherText.toString();
} catch (Exception e) {
e.printStackTrace();
}
return "ERROR: Public key file is probably missing";
}
函数doEncryption("someString")
returns[B@61decc8c]
现在我必须将这个字符串嵌入到 url 中,服务器端代码应该从那里获取它。
到目前为止一切都很好,但是当我调用函数时
public static String doDecryption(String input) {
try {
if (!RSAService.areKeysPresent()) {
RSAService.generateKey();
}
ObjectInputStream inputStream;
// Decrypt the cipher text using the private key.
inputStream = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
PrivateKey privateKey = (PrivateKey) inputStream.readObject();
String out = decrypt(input.getBytes(), privateKey);
return out;
} catch (Exception e) {
e.printStackTrace();
}
return "ERROR: Private key file is probably missing or doesn't match the public key";
}
doDecryption("[B@61decc8c")
尖叫,但有以下例外:
javax.crypto.BadPaddingException: Data must start with zero
at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:325)
at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:272)
at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:356)
at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:382)
at javax.crypto.Cipher.doFinal(Cipher.java:2087)
at rsaendecryptor.RSAService.decrypt(RSAService.java:132)
at rsaendecryptor.RSAService.doDecryption(RSAService.java:180)
at rsaendecryptor.RSAEnDecrypt.main(RSAEnDecrypt.java:20)
java.lang.NullPointerException
at java.lang.String.<init>(String.java:556)
at rsaendecryptor.RSAService.decrypt(RSAService.java:138)
at rsaendecryptor.RSAService.doDecryption(RSAService.java:180)
at rsaendecryptor.RSAEnDecrypt.main(RSAEnDecrypt.java:20)
有什么办法可以解决这个问题吗?我必须在客户端和服务器端之间传递字符串,因为它们甚至可以在不同的域中。更不用说字符串实际上会从 .Net 逻辑生成并发送到 Java 服务器端。字符串加密工作正常...我应该怎么做才能修复解密。
这是完整的 class 代码:
public class RSAService {
/**
* String to hold name of the encryption algorithm.
*/
public static final String ALGORITHM = "RSA";
/**
* String to hold the name of the private key file.
*/
public static final String PRIVATE_KEY_FILE = "private.key";
/**
* String to hold name of the public key file.
*/
public static final String PUBLIC_KEY_FILE = "public.key";
/**
* Generate key which contains a pair of private and public key using 1024
* bytes. Store the set of keys in Prvate.key and Public.key files.
*
*/
public static void generateKey() {
try {
final KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);
keyGen.initialize(1024);
final KeyPair key = keyGen.generateKeyPair();
File privateKeyFile = new File(PRIVATE_KEY_FILE);
File publicKeyFile = new File(PUBLIC_KEY_FILE);
// Create files to store public and private key
privateKeyFile.createNewFile();
if (publicKeyFile.getParentFile() != null) {
publicKeyFile.getParentFile().mkdirs();
}
publicKeyFile.createNewFile();
// Saving the Public key in a file
ObjectOutputStream publicKeyOS = new ObjectOutputStream(
new FileOutputStream(publicKeyFile));
publicKeyOS.writeObject(key.getPublic());
publicKeyOS.close();
// Saving the Private key in a file
ObjectOutputStream privateKeyOS = new ObjectOutputStream(
new FileOutputStream(privateKeyFile));
privateKeyOS.writeObject(key.getPrivate());
privateKeyOS.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* The method checks if the pair of public and private key has been
* generated.
*
* @return flag indicating if the pair of keys were generated.
*/
public static boolean areKeysPresent() {
File privateKey = new File(PRIVATE_KEY_FILE);
File publicKey = new File(PUBLIC_KEY_FILE);
if (privateKey.exists() && publicKey.exists()) {
return true;
}
return false;
}
/**
* Encrypt the plain text using public key.
*
* @param text : original plain text
* @param key :The public key
* @return Encrypted text
* @throws java.lang.Exception
*/
public static byte[] encrypt(String text, PublicKey key) {
byte[] cipherText = null;
try {
// get an RSA cipher object and print the provider
final Cipher cipher = Cipher.getInstance(ALGORITHM);
// encrypt the plain text using the public key
cipher.init(Cipher.ENCRYPT_MODE, key);
cipherText = cipher.doFinal(text.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
return cipherText;
}
/**
* Decrypt text using private key.
*
* @param text :encrypted text
* @param key :The private key
* @return plain text
* @throws java.lang.Exception
*/
public static String decrypt(byte[] text, PrivateKey key) {
byte[] dectyptedText = null;
try {
// get an RSA cipher object and print the provider
final Cipher cipher = Cipher.getInstance(ALGORITHM);
// decrypt the text using the private key
cipher.init(Cipher.DECRYPT_MODE, key);
dectyptedText = cipher.doFinal(text);
} catch (Exception ex) {
ex.printStackTrace();
}
return new String(dectyptedText);
}
public static String doEncryption(String input) {
try {
if (!RSAService.areKeysPresent()) {
RSAService.generateKey();
}
ObjectInputStream inputStream;
// Encrypt the string using the public key
inputStream = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));
PublicKey publicKey = (PublicKey) inputStream.readObject();
byte[] cipherText = RSAService.encrypt(input, publicKey);
return cipherText.toString();
} catch (Exception e) {
e.printStackTrace();
}
return "ERROR: Public key file is probably missing";
}
public static String doDecryption(String input) {
try {
if (!RSAService.areKeysPresent()) {
RSAService.generateKey();
}
ObjectInputStream inputStream;
// Decrypt the cipher text using the private key.
inputStream = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
PrivateKey privateKey = (PrivateKey) inputStream.readObject();
String out = decrypt(input.getBytes(), privateKey);
return out;
} catch (Exception e) {
e.printStackTrace();
}
return "ERROR: Private key file is probably missing or doesn't match the public key";
}
}
感谢 shikjohari 和这篇文章 here 我能够修复我的代码!
在doEncryption()
方法中我修改了return如下:
return (Base64.encode(cipherText)).toString();
并且在 doDecryption()
方法中我修改了 return 如下:
String out = decrypt(Base64.decode(input), privateKey);
return out;
您可以从我的第一个 post 中获取完整代码,只需按照此 post 编辑两个方法的 returns。希望这有帮助。
public static String doEncryption(String input)
到此为止。字符串不是二进制数据的容器,因此一开始就不应该用来包含密文。它应该作为 byte[]
.
注意,当您遇到异常时,不要猜测条件是什么,return 一个说明它 'probably' 是什么的字符串。它使调试成为一种猜测。使用异常附带的消息。