java bouncy castle RSA 4096解密填充错误

时间:2017-03-28 09:18:06

标签: java encryption file-io rsa padding

我已经尝试了两天来解密一个包含&#39; lolilol&#39;的私钥的文件。用公钥rsa 4096加密之后。然后我得到填充错误,我尝试了一切,我收到错误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(); } } }

即使在读取填充文档后我也没有成功:加密工作正常,但解密包含错误。

这是我的代码:

[self.collectionView performBatchUpdates:^{
                                            [myCollectionView reloadData];
                                          } 
                              completion:^(BOOL finished) {}
];

1 个答案:

答案 0 :(得分:0)

您的代码中存在多个问题:

  • 您永远不会关闭文件流。如果你不这样做,可能会发生没有实际写入数据的情况。如果没有(完全)写入密文,那么解密显然会失败。

  • FileInputStream并未准确衡量基础文件包含的数据量。您必须使用File类:

    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();
    }
}