【发布时间】:2018-09-18 11:24:54
【问题描述】:
在我的 Java 代码中,我尝试使用 RSA 和公钥加密字符串。该字符串是一个 Base64 编码的字符串,表示一个图像(图像已转换为字符串)。它将使用私钥解密。
在加密期间,我首先遇到了一个异常“javax.crypto.IllegalBlockSizeException:数据不能超过 190 字节”。因此,我以 189 个块处理了字符串(明文),然后解决了它。
在解密过程中,我遇到了另一个异常“javax.crypto.IllegalBlockSizeException:数据不得超过 256 字节”。所以,我处理了字节[](密文),首先将其转换为字符串,以 256 个块为单位,然后也将其解析。
再次,在我的解密过程中,我最终得到一个“javax.crypto.BadPaddingException: Decryption error”异常,我一直无法解决。
根据本站专家的推荐,我使用了“OAEPWithSHA-256AndMGF1Padding”。我什至尝试在其他填充方法之后使用无填充,以查看异常是否会消失,但它不起作用。我做错了什么?
我能够确定该异常是在该行中引发的 - decryptedImagePartial = t.rsaDecrypt(cipherTextTrimmed.getBytes(), privateKey); - 在 main 方法的解密部分。
如果我的编码习惯很差,请多多包涵。我现在真的更愿意找出异常背后的错误。
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
public class Tester
{
public KeyPair buildKeyPair() throws NoSuchAlgorithmException
{
final int keySize = 2048;
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(keySize);
return keyPairGenerator.genKeyPair();
}
public byte[] encrypt(PublicKey publicKey, String message) throws Exception
{
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(message.getBytes());
}
public String decrypt(PrivateKey privateKey, byte [] encrypted) throws Exception
{
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return new String(cipher.doFinal(encrypted));
}
public byte[] rsaEncrypt(String watermarkMsg, PublicKey publicKey) throws Exception
{
byte[] cipherText = encrypt(publicKey, watermarkMsg);
return cipherText;
}
public String rsaDecrypt(byte[] cipherText, PrivateKey privateKey) throws Exception
{
String plainText = decrypt(privateKey, cipherText);
return plainText;
}
public static void main(String args[]) throws NoSuchAlgorithmException
{
Tester t = new Tester();
String inputImageFilePath = "<file_path_here";
String stringOfImage = null;
byte[] encryptedImage = null;
byte[] encryptedImagePartial = null;
KeyPair keyPair = t.buildKeyPair();
PublicKey pubKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate()
//-----------IMAGE TO STRING CONVERSION----------------
//The imagetostring() function retrieves the image at the file path and converts it into a Base64 encoded String
try
{
stringOfImage = t.imagetostring(inputImageFilePath);
}
catch(Exception e)
{
System.out.println(e.toString());
}
//-----------ENCRYPTION OF STRING----------------
//The encryption is done in blocks of 189, because earlier I got an exception - "javax.crypto.IllegalBlockSizeException: Data must not be longer than 190 bytes"
try
{
String plaintext = stringOfImage;
String plaintextTrimmed = "";
System.out.println(stringOfImage);
encryptedImage = new byte[15512]; //The size is given as 15512 because the length of the particular string was found to be 15512
while(plaintext!="")
{
if(plaintext.length()>189)
{
plaintextTrimmed = plaintext.substring(0, 189);
plaintext = plaintext.substring(189);
}
else
{
plaintextTrimmed = plaintext;
plaintext = "";
}
encryptedImagePartial = t.rsaEncrypt(plaintextTrimmed, pubKey);
encryptedImage = t.concatenate(encryptedImage, encryptedImagePartial);
System.out.println(encryptedImage.length);
}
}
catch(Exception e)
{
System.out.println(e.toString());
}
t.byteDigest(encryptedImage);
//-----------DECRYPTION OF STRING--------------
//The decryption is done in blocks of 189, because earlier I got an exception - "javax.crypto.IllegalBlockSizeException: Data must not be longer than 256 bytes"
try
{
// The ciphertext is located in the variable encryptedImage which is a byte[]
String stringRepOfCipherText = new String(encryptedImage); String cipherTextTrimmed = "";
String decryptedImagePartial;
String decryptedImage = "";
while(stringRepOfCipherText!="")
{
if(stringRepOfCipherText.length()>189)
{
cipherTextTrimmed = stringRepOfCipherText.substring(0, 189);
stringRepOfCipherText = stringRepOfCipherText.substring(189);
}
else
{
cipherTextTrimmed = stringRepOfCipherText;
stringRepOfCipherText = "";
}
decryptedImagePartial = t.rsaDecrypt(cipherTextTrimmed.getBytes(), privateKey);
decryptedImage = decryptedImage + decryptedImagePartial;
}
}
catch(BadPaddingException e)
{
System.out.println(e.toString());
}
catch(Exception e)
{
System.out.println(e.toString());
}
}
}
此外,我注意到其他一些使用 KeyFactory 生成密钥的示例。谁能告诉我使用 KeyFactory 和我用过的区别?
【问题讨论】:
-
生成密钥,使用对称密码用这个密钥加密图像,然后用 RSA 加密密钥。 RSA 不适用于大文件加密
-
@Sebastian S 我明白你的意思,但这是实验性的,我必须遵循框架 - 文件使用 RSA 加密。
标签: java encryption cryptography rsa padding