java bouncy castle RSA 4096解密填充错误
java bouncy castle RSA 4096 decryption padding error
在用 public 密钥 rsa 4096 加密后,我已经尝试了两天用包含 'lolilol' 的私钥解密文件。然后我得到填充错误,我尝试了一切做,我得到错误 Javax.crypto.BadPaddingException: Decryption error
.
即使阅读了有关填充的文档,我也没有成功:加密工作正常,但解密包含错误。
这是我的代码:
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;
import javax.crypto.Cipher;
import sun.misc.BASE64Encoder;
public class GenerateRSAKeys{
private Key pubKey;
private Key privKey;
public static void main(String[] args)
{
String input = "C:\Users\toto\Desktop\nomFichier_entrant.ext";
String output = "C:\Users\toto\Desktop\nomFichier_entrant.ext.enc";
String dec = "C:\Users\toto\Desktop\nomFichier_entrant.ext.dec";
String publicKeyFilename = "C:\Users\toto\Desktop\HR_pubkey_prd.pem";
String privateKeyFilename = "C:\Users\toto\Desktop\PE_privkey_prd.pem";
GenerateRSAKeys generateRSAKeys = new GenerateRSAKeys();
/* if (args.length < 2)
{
System.err.println("Usage: java "+ generateRSAKeys.getClass().getName()+
" Public_Key_Filename Private_Key_Filename");
System.exit(1);
}
publicKeyFilename = args[0].trim();
privateKeyFilename = args[1].trim(); */
generateRSAKeys.generate(publicKeyFilename, privateKeyFilename);
//generateRSAKeys.encrypt(input, output);
generateRSAKeys.encrypt(input, output);
generateRSAKeys.decrypt(output, dec);
}
private void generate (String publicKeyFilename, String privateFilename){
try {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
// Create the public and private keys
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "BC");
BASE64Encoder b64 = new BASE64Encoder();
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
/* SecureRandom random = new SecureRandom();
keyGen.initialize(4096, random);
KeyPair pair = keyGen.generateKeyPair();
pubKey = pair.getPublic();
privKey = pair.getPrivate(); */
SecureRandom random = createFixedRandom();
generator.initialize(4096, random);
KeyPair pair = generator.generateKeyPair();
pubKey = pair.getPublic();
privKey = pair.getPrivate();
System.out.println("publicKey : " + b64.encode(pubKey.getEncoded()));
System.out.println("privateKey : " + b64.encode(privKey.getEncoded()));
BufferedWriter out = new BufferedWriter(new FileWriter(publicKeyFilename));
out.write(b64.encode(pubKey.getEncoded()));
out.close();
out = new BufferedWriter(new FileWriter(privateFilename));
out.write(b64.encode(privKey.getEncoded()));
out.close();
}
catch (Exception e) {
System.out.println(e);
}
}
public static SecureRandom createFixedRandom()
{
return new FixedRand();
}
private static class FixedRand extends SecureRandom {
MessageDigest sha;
byte[] state;
FixedRand() {
try
{
this.sha = MessageDigest.getInstance("SHA-1");
this.state = sha.digest();
}
catch (NoSuchAlgorithmException e)
{
throw new RuntimeException("can't find SHA-1!");
}
}
public void nextBytes(byte[] bytes){
int off = 0;
sha.update(state);
while (off < bytes.length)
{
state = sha.digest();
if (bytes.length - off > state.length)
{
System.arraycopy(state, 0, bytes, off, state.length);
}
else
{
System.arraycopy(state, 0, bytes, off, bytes.length - off);
}
off += state.length;
sha.update(state);
}
}
}
public void encrypt(String input, String output) {
File outputFile;
FileInputStream inputStream;
FileOutputStream outputStream;
Cipher cipher;
byte[] inputBytes;
byte[] outputBytes;
try {
outputFile = new File(output);
inputStream = new FileInputStream(input);
outputStream = new FileOutputStream(outputFile);
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
inputBytes = new byte[(int) input.length()];
inputStream.read(inputBytes);
outputBytes = cipher.doFinal(inputBytes);
outputStream.write(outputBytes);
// System.out.println(new String(inputBytes, "UTF-8"));
System.out.println("encrypt");
System.out.println(new String(outputBytes, "UTF-8"));
System.out.println("fin encrypt");
} catch (Exception e) {
e.printStackTrace();
}
}
public void decrypt(String input, String output) {
File outputFile;
FileInputStream inputStream;
FileOutputStream outputStream;
Cipher cipher;
byte[] inputBytes;
byte[] outputBytes;
try {
outputFile = new File(output);
inputStream = new FileInputStream(input);
outputStream = new FileOutputStream(outputFile);
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privKey);
inputBytes = new byte[(int) input.length()];
inputStream.read(inputBytes);
outputBytes = cipher.doFinal(inputBytes);
outputStream.write(outputBytes);
// System.out.println(new String(inputBytes, "UTF-8"));
System.out.println("decrypt");
System.out.println(new String(outputBytes, "UTF-8"));
System.out.println("fin decrypt");
} catch (Exception e) {
e.printStackTrace();
}
}
}
您的代码中存在多个问题:
您永远不会关闭文件流。如果不这样做,可能会发生实际没有写入数据的情况。如果密文没有(完全)写入那么解密显然会失败。
A FileInputStream
无法准确衡量基础文件包含的数据量。为此,您必须使用 File
class:
File inputFile = new File(input);
FileInputStream inputStream = new FileInputStream(inputFile);
FileOutputStream outputStream = new FileOutputStream(output);
byte[] inputBytes = new byte[(int) inputFile.length()];
当您阅读文件内容时,您必须始终检查您阅读了多少并准确使用该数量:
int readBytes = inputStream.read(inputBytes);
byte[] outputBytes = cipher.doFinal(inputBytes, 0, readBytes);
始终使用完全限定的密码字符串。 Cipher.getInstance("RSA");
可能会产生不同的密码,具体取决于默认的安全提供程序。在 OpenJDK 中,它默认为 Cipher.getInstance("RSA/ECB/PKCS1Padding");
。如今,您应该使用 OAEP 而不是默认的 PKCS#1 v1.5 填充。所以你应该使用 Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
。
下面是这两种方法的完整代码:
public void encrypt(String input, String output) {
File inputFile;
FileInputStream inputStream;
FileOutputStream outputStream;
Cipher cipher;
byte[] inputBytes;
byte[] outputBytes;
try {
System.out.println("encrypt");
cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
inputFile = new File(input);
inputStream = new FileInputStream(inputFile);
outputStream = new FileOutputStream(output);
inputBytes = new byte[(int) input.length()];
int readBytes = inputStream.read(inputBytes);
outputBytes = cipher.doFinal(inputBytes, 0, readBytes);
outputStream.write(outputBytes);
System.out.println("fin encrypt");
inputStream.close();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public void decrypt(String input, String output) {
File inputFile;
FileInputStream inputStream;
FileOutputStream outputStream;
Cipher cipher;
byte[] inputBytes;
byte[] outputBytes;
try {
System.out.println("decrypt");
cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
cipher.init(Cipher.DECRYPT_MODE, privKey);
inputFile = new File(input);
inputStream = new FileInputStream(inputFile);
outputStream = new FileOutputStream(output);
inputBytes = new byte[(int) inputFile.length()];
int readBytes = inputStream.read(inputBytes);
outputBytes = cipher.doFinal(inputBytes, 0, readBytes);
outputStream.write(outputBytes);
System.out.println("Decryption result: " + new String(outputBytes, "UTF-8"));
System.out.println("fin decrypt");
inputStream.close();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
在用 public 密钥 rsa 4096 加密后,我已经尝试了两天用包含 'lolilol' 的私钥解密文件。然后我得到填充错误,我尝试了一切做,我得到错误 Javax.crypto.BadPaddingException: Decryption error
.
即使阅读了有关填充的文档,我也没有成功:加密工作正常,但解密包含错误。
这是我的代码:
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;
import javax.crypto.Cipher;
import sun.misc.BASE64Encoder;
public class GenerateRSAKeys{
private Key pubKey;
private Key privKey;
public static void main(String[] args)
{
String input = "C:\Users\toto\Desktop\nomFichier_entrant.ext";
String output = "C:\Users\toto\Desktop\nomFichier_entrant.ext.enc";
String dec = "C:\Users\toto\Desktop\nomFichier_entrant.ext.dec";
String publicKeyFilename = "C:\Users\toto\Desktop\HR_pubkey_prd.pem";
String privateKeyFilename = "C:\Users\toto\Desktop\PE_privkey_prd.pem";
GenerateRSAKeys generateRSAKeys = new GenerateRSAKeys();
/* if (args.length < 2)
{
System.err.println("Usage: java "+ generateRSAKeys.getClass().getName()+
" Public_Key_Filename Private_Key_Filename");
System.exit(1);
}
publicKeyFilename = args[0].trim();
privateKeyFilename = args[1].trim(); */
generateRSAKeys.generate(publicKeyFilename, privateKeyFilename);
//generateRSAKeys.encrypt(input, output);
generateRSAKeys.encrypt(input, output);
generateRSAKeys.decrypt(output, dec);
}
private void generate (String publicKeyFilename, String privateFilename){
try {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
// Create the public and private keys
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "BC");
BASE64Encoder b64 = new BASE64Encoder();
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
/* SecureRandom random = new SecureRandom();
keyGen.initialize(4096, random);
KeyPair pair = keyGen.generateKeyPair();
pubKey = pair.getPublic();
privKey = pair.getPrivate(); */
SecureRandom random = createFixedRandom();
generator.initialize(4096, random);
KeyPair pair = generator.generateKeyPair();
pubKey = pair.getPublic();
privKey = pair.getPrivate();
System.out.println("publicKey : " + b64.encode(pubKey.getEncoded()));
System.out.println("privateKey : " + b64.encode(privKey.getEncoded()));
BufferedWriter out = new BufferedWriter(new FileWriter(publicKeyFilename));
out.write(b64.encode(pubKey.getEncoded()));
out.close();
out = new BufferedWriter(new FileWriter(privateFilename));
out.write(b64.encode(privKey.getEncoded()));
out.close();
}
catch (Exception e) {
System.out.println(e);
}
}
public static SecureRandom createFixedRandom()
{
return new FixedRand();
}
private static class FixedRand extends SecureRandom {
MessageDigest sha;
byte[] state;
FixedRand() {
try
{
this.sha = MessageDigest.getInstance("SHA-1");
this.state = sha.digest();
}
catch (NoSuchAlgorithmException e)
{
throw new RuntimeException("can't find SHA-1!");
}
}
public void nextBytes(byte[] bytes){
int off = 0;
sha.update(state);
while (off < bytes.length)
{
state = sha.digest();
if (bytes.length - off > state.length)
{
System.arraycopy(state, 0, bytes, off, state.length);
}
else
{
System.arraycopy(state, 0, bytes, off, bytes.length - off);
}
off += state.length;
sha.update(state);
}
}
}
public void encrypt(String input, String output) {
File outputFile;
FileInputStream inputStream;
FileOutputStream outputStream;
Cipher cipher;
byte[] inputBytes;
byte[] outputBytes;
try {
outputFile = new File(output);
inputStream = new FileInputStream(input);
outputStream = new FileOutputStream(outputFile);
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
inputBytes = new byte[(int) input.length()];
inputStream.read(inputBytes);
outputBytes = cipher.doFinal(inputBytes);
outputStream.write(outputBytes);
// System.out.println(new String(inputBytes, "UTF-8"));
System.out.println("encrypt");
System.out.println(new String(outputBytes, "UTF-8"));
System.out.println("fin encrypt");
} catch (Exception e) {
e.printStackTrace();
}
}
public void decrypt(String input, String output) {
File outputFile;
FileInputStream inputStream;
FileOutputStream outputStream;
Cipher cipher;
byte[] inputBytes;
byte[] outputBytes;
try {
outputFile = new File(output);
inputStream = new FileInputStream(input);
outputStream = new FileOutputStream(outputFile);
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privKey);
inputBytes = new byte[(int) input.length()];
inputStream.read(inputBytes);
outputBytes = cipher.doFinal(inputBytes);
outputStream.write(outputBytes);
// System.out.println(new String(inputBytes, "UTF-8"));
System.out.println("decrypt");
System.out.println(new String(outputBytes, "UTF-8"));
System.out.println("fin decrypt");
} catch (Exception e) {
e.printStackTrace();
}
}
}
您的代码中存在多个问题:
您永远不会关闭文件流。如果不这样做,可能会发生实际没有写入数据的情况。如果密文没有(完全)写入那么解密显然会失败。
A
FileInputStream
无法准确衡量基础文件包含的数据量。为此,您必须使用File
class:File inputFile = new File(input); FileInputStream inputStream = new FileInputStream(inputFile); FileOutputStream outputStream = new FileOutputStream(output); byte[] inputBytes = new byte[(int) inputFile.length()];
当您阅读文件内容时,您必须始终检查您阅读了多少并准确使用该数量:
int readBytes = inputStream.read(inputBytes); byte[] outputBytes = cipher.doFinal(inputBytes, 0, readBytes);
始终使用完全限定的密码字符串。
Cipher.getInstance("RSA");
可能会产生不同的密码,具体取决于默认的安全提供程序。在 OpenJDK 中,它默认为Cipher.getInstance("RSA/ECB/PKCS1Padding");
。如今,您应该使用 OAEP 而不是默认的 PKCS#1 v1.5 填充。所以你应该使用Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
。
下面是这两种方法的完整代码:
public void encrypt(String input, String output) {
File inputFile;
FileInputStream inputStream;
FileOutputStream outputStream;
Cipher cipher;
byte[] inputBytes;
byte[] outputBytes;
try {
System.out.println("encrypt");
cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
inputFile = new File(input);
inputStream = new FileInputStream(inputFile);
outputStream = new FileOutputStream(output);
inputBytes = new byte[(int) input.length()];
int readBytes = inputStream.read(inputBytes);
outputBytes = cipher.doFinal(inputBytes, 0, readBytes);
outputStream.write(outputBytes);
System.out.println("fin encrypt");
inputStream.close();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public void decrypt(String input, String output) {
File inputFile;
FileInputStream inputStream;
FileOutputStream outputStream;
Cipher cipher;
byte[] inputBytes;
byte[] outputBytes;
try {
System.out.println("decrypt");
cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
cipher.init(Cipher.DECRYPT_MODE, privKey);
inputFile = new File(input);
inputStream = new FileInputStream(inputFile);
outputStream = new FileOutputStream(output);
inputBytes = new byte[(int) inputFile.length()];
int readBytes = inputStream.read(inputBytes);
outputBytes = cipher.doFinal(inputBytes, 0, readBytes);
outputStream.write(outputBytes);
System.out.println("Decryption result: " + new String(outputBytes, "UTF-8"));
System.out.println("fin decrypt");
inputStream.close();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}