java - 尝试解密 int 时出现 RSA BadPaddingException
java - RSA BadPaddingException when trying to decrypt an int
我知道以前有人问过类似的问题,但我找不到针对我的问题的答案。我正在尝试使用 RSA 加密来拍摄带有加密像素的图像,并使用相同的私钥对其进行解密。尽管当我尝试解密使用 getRGB() 从图像像素中获取的 int 时,我仍然 运行 遇到了一个问题。这是我的代码:
int pixel = img.getRGB(1, 1);
System.out.println(pixel);
byte[] bytes = ByteBuffer.allocate(4).putInt(pixel).array();
System.out.println(fromByteArray(bytes));
bytes = rsa.RSADecryptB(privk, bytes);
int nom = ByteBuffer.wrap(bytes).getInt(); // big-endian by default
System.out.println(nom);
这是我的主程序 class,它从另一个 class 调用方法 RSADecryptB,这是该方法:
public static []byte RSADecryptB(PrivateKey privatekey, byte[] cipherText) {
byte[] ll = null;
try {
/* Create cipher for decryption. */
Cipher decrypt_cipher = Cipher.getInstance("RSA");
decrypt_cipher.init(Cipher.DECRYPT_MODE, privatekey);
ll = decrypt_cipher.doFinal(cipherText);
} catch (IllegalBlockSizeException e) {
System.out.println("1");
e.printStackTrace();
}
catch (InvalidKeyException et) {
System.out.println("2");
et.printStackTrace();
}
catch (NoSuchAlgorithmException ev) {
System.out.println("3");
ev.printStackTrace();
}
catch (BadPaddingException ea) {
System.out.println("4");
ea.printStackTrace();
}
catch (NoSuchPaddingException eo) {
System.out.println("5");
eo.printStackTrace();
}
return ll;
}
当我运行程序输出是这样的:
-1606258341
5
4
javax.crypto.BadPaddingException: Decryption error
at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:380)
at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:291)
at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:363)
at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
at javax.crypto.Cipher.doFinal(Cipher.java:2165)
at Encryption5.RSADecryptB(Encryption5.java:126)
at ImageEncryptor.main(ImageEncryptor.java:405)
Exception in thread "main" java.lang.NullPointerException
at java.nio.ByteBuffer.wrap(ByteBuffer.java:396)
at ImageEncryptor.main(ImageEncryptor.java:406)
我不明白为什么会这样。 -1606258341是像素的值,5和4的输出是因为NoSuchPaddingException和BadPaddingException。如果有人可以帮助解释为什么会发生这种情况以及我做错了什么,那就太好了。谢谢!
编辑:我知道我可能不应该直接使用 RSA,但我自己也在逐个像素地进行加密。我这样做更多是为了练习使用 bufferedimages/byte arrays/rsa 而不是创建最多 efficient/secure 程序。此外,当我在我的加密方法中解密整数时,它工作正常。当我用不同的方法解密它时,我得到了错误。另外,加密后的图像被保存到一个文件中,然后提取出来解密。这也是我的加密方法(它不使用任何填充):
int w = img.getWidth();
int h = img.getHeight();
byte[] bytes = null;
ByteBuffer wrappedo = null;
int nom = 0;
ByteBuffer wrapped = null;
int num = 0;
int pixel = 0;
System.out.println("width, height: " + w + ", " + h);
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
pixel = img.getRGB(j, i);
bytes = ByteBuffer.allocate(4).putInt(pixel).array();
bytes = rsa.RSAEncrypt(bytes);
wrappedo = ByteBuffer.wrap(bytes); // big-endian by default
nom = wrappedo.getInt();
img.setRGB(j, i, nom);
}
}
然后是 RSAEncrypt 方法:
public static byte[] RSAEncrypt(byte[] data) {
byte[] cipherData = null;
try {
PublicKey pubKey = readKeysFromFile();
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
cipherData = cipher.doFinal(data);
}
catch (Exception e) {}
return cipherData;
}
您需要用于加密图像的方法。几乎可以肯定,它无法按照您目前期望的方式进行加密。它可能是普通的/原始的/教科书的/玩具 RSA(只是模幂)但在那种情况下你需要自己创建解密例程。
每个像素都单独加密的可能性很小。正如 JB Nizet 已经提到的,那将是 非常 低效的。 RSA 输出是密钥对的大小(这又与模数的字节大小相同)。 RSA 密钥对的密钥大小至少应为 512 位才能使其 难以 解密,并且大约 2048 位是安全的。通常使用混合方案使用 RSA 加密较大的文本(例如,首先使用 AES 加密,然后使用 RSA 加密 AES 密钥)。
此外,您目前指定 "RSA"
作为算法。对于 SUNRSA 提供者(以及大多数其他提供者),这将转换为 "RSA/ECB/PKCS1Padding"
,因为 "ECB"
和 "PKCS1Padding"
是默认值。 PKCS#1 填充有 11 个字节的开销。因此,如果您的密文小于模数 或 密文小于 11 个字节,那么解密 必须 失败 - 它确实如此。
我知道以前有人问过类似的问题,但我找不到针对我的问题的答案。我正在尝试使用 RSA 加密来拍摄带有加密像素的图像,并使用相同的私钥对其进行解密。尽管当我尝试解密使用 getRGB() 从图像像素中获取的 int 时,我仍然 运行 遇到了一个问题。这是我的代码:
int pixel = img.getRGB(1, 1);
System.out.println(pixel);
byte[] bytes = ByteBuffer.allocate(4).putInt(pixel).array();
System.out.println(fromByteArray(bytes));
bytes = rsa.RSADecryptB(privk, bytes);
int nom = ByteBuffer.wrap(bytes).getInt(); // big-endian by default
System.out.println(nom);
这是我的主程序 class,它从另一个 class 调用方法 RSADecryptB,这是该方法:
public static []byte RSADecryptB(PrivateKey privatekey, byte[] cipherText) {
byte[] ll = null;
try {
/* Create cipher for decryption. */
Cipher decrypt_cipher = Cipher.getInstance("RSA");
decrypt_cipher.init(Cipher.DECRYPT_MODE, privatekey);
ll = decrypt_cipher.doFinal(cipherText);
} catch (IllegalBlockSizeException e) {
System.out.println("1");
e.printStackTrace();
}
catch (InvalidKeyException et) {
System.out.println("2");
et.printStackTrace();
}
catch (NoSuchAlgorithmException ev) {
System.out.println("3");
ev.printStackTrace();
}
catch (BadPaddingException ea) {
System.out.println("4");
ea.printStackTrace();
}
catch (NoSuchPaddingException eo) {
System.out.println("5");
eo.printStackTrace();
}
return ll;
}
当我运行程序输出是这样的:
-1606258341
5
4
javax.crypto.BadPaddingException: Decryption error
at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:380)
at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:291)
at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:363)
at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
at javax.crypto.Cipher.doFinal(Cipher.java:2165)
at Encryption5.RSADecryptB(Encryption5.java:126)
at ImageEncryptor.main(ImageEncryptor.java:405)
Exception in thread "main" java.lang.NullPointerException
at java.nio.ByteBuffer.wrap(ByteBuffer.java:396)
at ImageEncryptor.main(ImageEncryptor.java:406)
我不明白为什么会这样。 -1606258341是像素的值,5和4的输出是因为NoSuchPaddingException和BadPaddingException。如果有人可以帮助解释为什么会发生这种情况以及我做错了什么,那就太好了。谢谢!
编辑:我知道我可能不应该直接使用 RSA,但我自己也在逐个像素地进行加密。我这样做更多是为了练习使用 bufferedimages/byte arrays/rsa 而不是创建最多 efficient/secure 程序。此外,当我在我的加密方法中解密整数时,它工作正常。当我用不同的方法解密它时,我得到了错误。另外,加密后的图像被保存到一个文件中,然后提取出来解密。这也是我的加密方法(它不使用任何填充):
int w = img.getWidth();
int h = img.getHeight();
byte[] bytes = null;
ByteBuffer wrappedo = null;
int nom = 0;
ByteBuffer wrapped = null;
int num = 0;
int pixel = 0;
System.out.println("width, height: " + w + ", " + h);
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
pixel = img.getRGB(j, i);
bytes = ByteBuffer.allocate(4).putInt(pixel).array();
bytes = rsa.RSAEncrypt(bytes);
wrappedo = ByteBuffer.wrap(bytes); // big-endian by default
nom = wrappedo.getInt();
img.setRGB(j, i, nom);
}
}
然后是 RSAEncrypt 方法:
public static byte[] RSAEncrypt(byte[] data) {
byte[] cipherData = null;
try {
PublicKey pubKey = readKeysFromFile();
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
cipherData = cipher.doFinal(data);
}
catch (Exception e) {}
return cipherData;
}
您需要用于加密图像的方法。几乎可以肯定,它无法按照您目前期望的方式进行加密。它可能是普通的/原始的/教科书的/玩具 RSA(只是模幂)但在那种情况下你需要自己创建解密例程。
每个像素都单独加密的可能性很小。正如 JB Nizet 已经提到的,那将是 非常 低效的。 RSA 输出是密钥对的大小(这又与模数的字节大小相同)。 RSA 密钥对的密钥大小至少应为 512 位才能使其 难以 解密,并且大约 2048 位是安全的。通常使用混合方案使用 RSA 加密较大的文本(例如,首先使用 AES 加密,然后使用 RSA 加密 AES 密钥)。
此外,您目前指定 "RSA"
作为算法。对于 SUNRSA 提供者(以及大多数其他提供者),这将转换为 "RSA/ECB/PKCS1Padding"
,因为 "ECB"
和 "PKCS1Padding"
是默认值。 PKCS#1 填充有 11 个字节的开销。因此,如果您的密文小于模数 或 密文小于 11 个字节,那么解密 必须 失败 - 它确实如此。