Java 解密时出现RSA BadPaddingException

Java 解密时出现RSA BadPaddingException,java,encryption,rsa,public-key-encryption,javacard,Java,Encryption,Rsa,Public Key Encryption,Javacard,我正在使用我在桌面应用程序上生成的公钥加密java智能卡上的一些字节的数据,但是当我尝试解密桌面上的数据时,我得到了BadPaddingException:数据必须以零开始,我了解到这可能是由于使用假私钥解密数据造成的 首先,我在桌面应用程序上生成了一对公钥/私钥,并使用以下代码将其加载到智能卡上(在bigingertype中生成,我将其转换为十六进制,并将其从十六进制转换为字节数组): 以下是savetofile函数: public void saveToFile(String fi

我正在使用我在桌面应用程序上生成的公钥加密java智能卡上的一些字节的数据,但是当我尝试解密桌面上的数据时,我得到了
BadPaddingException:数据必须以零开始,我了解到这可能是由于使用假私钥解密数据造成的

  • 首先,我在桌面应用程序上生成了一对公钥/私钥,并使用以下代码将其加载到智能卡上(在
    biginger
    type中生成,我将其转换为十六进制,并将其从十六进制转换为字节数组):

  • 以下是savetofile函数:

        public void saveToFile(String fileName,  BigInteger mod, BigInteger exp) throws IOException {
              ObjectOutputStream oout = new ObjectOutputStream(
                new BufferedOutputStream(new FileOutputStream(fileName)));
              try {
                oout.writeObject(mod);
                oout.writeObject(exp);
              } catch (Exception e) {
                throw new IOException();
              } finally {
                oout.close();
              }
            }
    
    这是用于在智能卡上存储公钥的线路:

    Main.sRmi.setPub(Crypto.hexStringToByteArray(Main.crypto.getPubMod().toString(16)), 
     toByteArray("0"+Main.crypto.getPubexp().toString(16)));
    
    (零被添加到字符串中,因为我们无法将奇数十六进制字符串转换为字节)

  • 然后我尝试使用卡中的公钥加密数据,这是我正在使用的函数:

    private Cipher cipherRSA = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false);
    private byte[] cipherText = new byte[64];
    
    public byte[] encrypt(byte[] clearText){
    
        cipherRSA.init(rsa_PublicKey, Cipher.MODE_ENCRYPT);
        cipherRSA.doFinal(clearText, (short)0,  (short)clearText.length,cipherText, (short)0 );
        return cipherText;
    }
    
  • 然后我尝试在另一个桌面应用程序上获取此加密值,并使用从文件中读取的私钥对其进行解密:

  • public void init (String ID ) throws FileNotFoundException, IOException, Exception{
    
        Object o[] = openFile(ID+".pub");
        setPubMod((BigInteger) o[0]);
        setPubexp((BigInteger) o[1]);
        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(this.pubMod, this.pubexp);
        KeyFactory fact = KeyFactory.getInstance("RSA");
        pubKey = (RSAPublicKey) fact.generatePublic(keySpec);
        o = openFile(ID+".priv");
        setPrivMod((BigInteger) o[0]);
        setPrivexp((BigInteger) o[1]);
        RSAPrivateKeySpec keySpec1 = new RSAPrivateKeySpec(this.privMod, this.privexp);
        fact = KeyFactory.getInstance("RSA");
        privKey = (RSAPrivateKey) fact.generatePrivate(keySpec1);
        cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING"); 
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
    }
    
    以下是我从文件中读取私钥的方式:

    public void init (String ID ) throws FileNotFoundException, IOException, Exception{
    
        Object o[] = openFile(ID+".pub");
        setPubMod((BigInteger) o[0]);
        setPubexp((BigInteger) o[1]);
        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(this.pubMod, this.pubexp);
        KeyFactory fact = KeyFactory.getInstance("RSA");
        pubKey = (RSAPublicKey) fact.generatePublic(keySpec);
        o = openFile(ID+".priv");
        setPrivMod((BigInteger) o[0]);
        setPrivexp((BigInteger) o[1]);
        RSAPrivateKeySpec keySpec1 = new RSAPrivateKeySpec(this.privMod, this.privexp);
        fact = KeyFactory.getInstance("RSA");
        privKey = (RSAPrivateKey) fact.generatePrivate(keySpec1);
        cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING"); 
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
    }
    
    biginger
    变量中获取私钥后,我使用以下方法进行解密:

    public byte[] rsaDecrypt(byte[] data) throws Exception, BadPaddingException {
    
          Cipher cipher = Cipher.getInstance("RSA");
          cipher.init(Cipher.DECRYPT_MODE, privKey);
          byte[] clearData = cipher.doFinal(data);
          return clearData;
        }
    
    总之,我创建了一个
    biginger
    格式的密钥对,我将
    biginger
    变量保存到一个由两个biginger组成的
    序列化
    数组中,供另一个桌面应用程序使用,然后我将它们转换为Hexa
    字符串
    ,然后转换为一个字节数组,我将其放入智能卡中

    谁能告诉我这个程序有什么问题吗?太多了吗?有没有更好的办法


    我想我知道问题出在哪里了,问题出在智能卡中存储的密钥上,用我的方式转换显然不起作用,看看我是如何从卡中读取并打印出来的,得到了完全不同的结果,所以现在的问题是,我如何成功导出在java.crypto(在BigInteger中)上创建的公钥将公钥存储在字节中的智能卡

    我发现:

    设置键的公共指数值。纯文本数据格式是大端和右对齐的(最低有效位是最后一个字节的最低有效位)。输入指数数据被复制到内部表示中

    那么如何将一个大整数转换成这个大端字节格式呢

    现在我正在尝试设置公钥,下面是我为此执行的代码:

    public void setPub(byte[] expo,byte[] mod){
        rsa_PublicKey.clearKey();
        rsa_PublicKey.setExponent(expo, (short)0, (short)expo.length);
        rsa_PublicKey.setModulus(mod, (short)0, (short)mod.length);
    }
    

    其中expo是一个65字节的数组,mod是一个由key gen生成的3字节数组,但我得到了这个错误:

    Exception in thread "AWT-EventQueue-0" java.lang.UnsatisfiedLinkError: com.sun.javacard.impl.NativeMethods.getCurrentContext()B
    at com.sun.javacard.impl.NativeMethods.getCurrentContext(Native Method)
    at com.sun.javacard.impl.PrivAccess.getCurrentAppID(PrivAccess.java:454)
    at javacard.framework.CardRuntimeException.<init>(CardRuntimeException.java:46)
    at javacard.security.CryptoException.<init>(DashoA10*..:25)
    at com.sun.javacard.javax.smartcard.rmiclient.CardObjectFactory.throwIt(Unknown Source)
    at com.sun.javacard.javax.smartcard.rmiclient.CardObjectFactory.throwException(Unknown Source)
    at com.sun.javacard.javax.smartcard.rmiclient.CardObjectFactory.getObject(Unknown Source)
    at com.sun.javacard.rmiclientlib.JCRemoteRefImpl.parseAPDU(Unknown Source)
    at com.sun.javacard.rmiclientlib.JCRemoteRefImpl.invoke(Unknown Source)
    at sid2.CompteurImpl_Stub.setPub(Unknown Source)
    at sid2.ServerRmi.setPub(ServerRmi.java:27)
    at AddCard$2.actionPerformed(AddCard.java:160)
    
    “其中expo是一个65字节的数组,mod是一个由密钥生成器生成的3字节数组,但我得到了这个错误:…”


    难怪会出现错误,指数通常比模短,模的大小总是与键的大小相同。您正在切换模数和指数

    根据yeah thx,BigInteger已经是big-endian格式了,刚在谷歌上搜索过,但现在我又被卡住了。问题中唯一的stacktrace是针对
    java.lang.UnsatifiedLinkError
    ,这不是由交换exp和mod.Hi@OlegEstekhin引起的。是的,可能不是唯一的错误。。。我猜RMI运行时在调试此问题时出错了。一边更新了,另一边没有,再见。
    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(512);
        KeyPair kp = kpg.genKeyPair();
        this.pubKey = kp.getPublic();
        this.privKey = kp.getPrivate();
    
        KeyFactory fact = KeyFactory.getInstance("RSA");
        this.pub = fact.getKeySpec(kp.getPublic(), RSAPublicKeySpec.class);
        this.priv = fact.getKeySpec(kp.getPrivate(),  RSAPrivateKeySpec.class);