当前位置: 首页 > 知识库问答 >
问题:

使用私钥的Java RSA解密产生BadPaddingException

澹台啸
2023-03-14

今天,我写了一些代码,用AES加密字符串,用RSA加密密钥。当我试图解密所有内容时,Java给了我一个BadPaddingException。这是我的代码:

测验爪哇:

import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.PrintWriter;
import java.security.Key;
import java.security.SecureRandom;
import java.util.Scanner;

public class Test {

private static String publicName = null;
private static String privateName = null;

public static void main(String[] args) throws Exception {
    Scanner scanner = new Scanner(System.in);
    System.out.println("Choose an option: \n(1) Decrypt \n(2) Encrypt \n(3) Generate Keypair");
    int choice = scanner.nextInt();
    if(choice == 1) decrypt();
    else if(choice == 2) encrypt();
    else if(choice == 3) makeKeypair();
}

private static void makeKeypair() throws Exception {
    Scanner scanner = new Scanner(System.in);
    System.out.println("Enter the name of your public key: ");
    publicName = scanner.nextLine() + ".key";
    System.out.println("Enter the name of your private key: ");
    privateName = scanner.nextLine() + ".key";
    KeyMaker keyMaker = new KeyMaker(publicName, privateName);
    keyMaker.generateKeys();
}

public static void encrypt() throws Exception {
    Scanner scanner = new Scanner(System.in);
    System.out.println("Enter the text you want to encrypt: ");
    String toEncrypt = scanner.nextLine();
    System.out.println("Enter the name of the public key you want to use: ");
    publicName = scanner.nextLine() + ".key";
    Encrypter encrypter = new Encrypter(publicName);

    Key key = generateKey();
    String encryptedWithAES = encryptAES(toEncrypt, key);

    String encodedKey = java.util.Base64.getEncoder().encodeToString(key.getEncoded());
    String encryptedKey = encrypter.rsaEncrypt(encodedKey);
    String finalOutput = encryptedKey + encryptedWithAES;

    System.out.println("Enter the name of the file encrypted file which will be created: ");
    String fileName = scanner.nextLine();
    PrintWriter out = new PrintWriter(fileName + ".txt");
    out.println(finalOutput);
    out.close();

    System.out.println("DONE - saved as: " + fileName + ".txt");
    scanner.close();
}

public static void decrypt() throws Exception {
    Scanner scanner = new Scanner(System.in);
    System.out.println("Enter the name of your encrypted file: ");
    String fileName = scanner.nextLine() + ".txt";

    String givenInput = null;
    try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {
        String line;
        while ((line = br.readLine()) != null) {
            givenInput = givenInput + line;
        }
    }
    assert givenInput != null;
    String encryptedKey = givenInput.substring(0,172);
    String encryptedWithAES = givenInput.replace(encryptedKey, "");

    System.out.println("Enter the name of your private key: ");
    privateName = scanner.nextLine() + ".key";
    Decrypter decrypter = new Decrypter(privateName);
    String decryptedKey = decrypter.rsaDecrypt(encryptedKey);

    byte[] decodedKey = java.util.Base64.getDecoder().decode(decryptedKey);
    Key originalKey = new SecretKeySpec(decodedKey, "AES");

    String decryptedWithAES = decryptAES(encryptedWithAES, originalKey);
    System.out.println(decryptedWithAES);
    scanner.close();
}

public static Key generateKey() throws Exception {
    KeyGenerator kg = KeyGenerator.getInstance("AES");
    SecureRandom random = new SecureRandom();
    kg.init(random);
    return kg.generateKey();
}

private static String encryptAES(String message, Key key) throws Exception {
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE,key);

    byte[] stringBytes = message.getBytes();
    byte[] raw = cipher.doFinal(stringBytes);
    return Base64.encodeBase64String(raw);
}

public static String decryptAES(String encrypted, Key key) throws Exception       {
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.DECRYPT_MODE, key);

    byte[] raw = Base64.decodeBase64(encrypted);
    byte[] stringBytes = cipher.doFinal(raw);
    return new String(stringBytes, "UTF8");
}
}

钥匙匠。爪哇:

import java.io.FileOutputStream;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public class KeyMaker {
String publicName;
String privateName;

public KeyMaker(String publicName, String privateName) {
    this.publicName = publicName;
    this.privateName = privateName;
}

public void generateKeys() throws Exception{
    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
    kpg.initialize(1024);
    KeyPair kp = kpg.genKeyPair();

    PrivateKey privateKey = kp.getPrivate();
    PublicKey publicKey = kp.getPublic();

    X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(
            publicKey.getEncoded());
    FileOutputStream fos = new FileOutputStream(publicName);
    fos.write(x509EncodedKeySpec.getEncoded());
    fos.close();

    PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(
            privateKey.getEncoded());
    fos = new FileOutputStream(privateName);
    fos.write(pkcs8EncodedKeySpec.getEncoded());
    fos.close();
}
}

加密机。爪哇:

import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.io.*;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;

public class Encrypter {
String keyFileName;

public Encrypter(String keyFileName) {
    this.keyFileName = keyFileName;
}

public String rsaEncrypt(String data) throws Exception {
    PublicKey pubKey = readPublicKeyFromFile(keyFileName);
            byte[] utf8 = data.getBytes("UTF-8");
    Cipher cipher = Cipher.getInstance("RSA");

    cipher.init(Cipher.ENCRYPT_MODE, pubKey);
    byte[] enc = cipher.doFinal(Base64.encodeBase64(utf8));
    return Base64.encodeBase64String(enc);
}

private PublicKey readPublicKeyFromFile(String keyFileName) throws Exception {
    File filePublicKey = new File(keyFileName);
    FileInputStream fis = new FileInputStream(keyFileName);
    byte[] encodedPublicKey = new byte[(int) filePublicKey.length()];
    fis.read(encodedPublicKey);
    fis.close();

    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(
            encodedPublicKey);
    PublicKey pubKey = keyFactory.generatePublic(publicKeySpec);
    return pubKey;
}
}

解密程序。爪哇:

import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.io.*;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;

public class Decrypter {
String keyFileName;

public Decrypter(String keyFileName) {
    this.keyFileName = keyFileName;
}

public String rsaDecrypt(String str) throws Exception {
    PrivateKey privateKey = readPrivateKeyFromFile(keyFileName);
    Cipher cipher = Cipher.getInstance("RSA");

    cipher.init(Cipher.DECRYPT_MODE, privateKey);
    byte[] dec = Base64.decodeBase64(str);
    byte[] utf8 = cipher.doFinal(Base64.decodeBase64(dec));
    return Base64.encodeBase64String(utf8);

}

private PrivateKey readPrivateKeyFromFile(String keyFileName) throws Exception {
    File filePrivateKey = new File(keyFileName);
    FileInputStream fis = new FileInputStream(keyFileName);
    byte[] encodedPrivateKey = new byte[(int) filePrivateKey.length()];
    fis.read(encodedPrivateKey);
    fis.close();

    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(
            encodedPrivateKey);
    PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
    return privateKey;
}
}

共有1个答案

戚俊健
2023-03-14

在解密程序中,将Base64编码的字符串解码为字节,然后再次解码。在加密机中,将加密的字节编码到Base64中一次。这可能就是你的问题所在。

奇怪的是,您执行的Base64操作似乎比必要的多。例如,在Encrypter中,可以获得要加密的字符串字节。为什么要重新对这些字节进行Base64编码?

 类似资料:
  • 我已经使用openssl生成了一个私钥,并在Terminal/command中执行以下命令: null 所有这些都无法解密我的密钥。下面是我根据这篇文章编写的类[https://stackoverflow.com/questions/35276820/decrypting-an-openssl-pem-encoded-rsa-privest-key-with-java]: 我对安全问题一无所知,所

  • 我一直在搜索,但我似乎找不到一个简单的方法解密使用RSA。 我生成了一个公钥和私钥,它们存储在两个单独的文件中,并且是XML格式的。使用FromXmlString将公钥关联到RSACryptoServiceProvider对象,然后加密一个字符串,这一点没有问题。当我试图解密一个加密的字符串时,我的困惑就来了。我不确定如何将私钥数据与RSACryptoServiceProvider关联,以便使用D

  • 我想使用带有RSA算法的OpenSSL使用私钥加密文件: 现在,如果我执行解密操作: 此操作需要私钥 我知道我应该使用公钥进行加密,如果我使用私钥,我会得到一个签名。 然而,我想这样做是为了学习。

  • 我被告知,对于非对称密码学,您使用公钥加密明文,并使用私钥解密明文。所以我尝试了以下方法: 以及加密和解密函数 我希望控制台显示,但它显示的是这个。我是否错误地使用了RSACryptoServiceProvider?

  • 我在C#程序(我在下面提到)中使用了RSA非对称密钥加密算法,我必须通过java程序加密数据。我希望我的java程序生成与C#程序相同的加密密钥。 公钥: C#加密程序: Java加密方案: 我尝试了上述java程序,但结果如下: O+gw 7+X hY x A 9 ltD V 5 zE RsF 4 Dy Xg MTc/gx 82 wR tT 1 x fR 3 su Y 0 XB JLa dp 7

  • 我找到了几个可以使用的解决方案。Net RSA Provider使用公钥对消息进行加密,并使用私钥对其解密。 但我想要的是用私钥加密,用公钥解密。 我希望在我的应用程序中存储公钥,并使用私钥加密许可证,例如在我的开发人员计算机上,将其发送到应用程序,并让信息使用公钥解密。 我怎样才能做到这一点?