我收到错误" BadPaddingException:数据必须从0开始"即使数据确实从零开始

时间:2012-07-30 20:17:29

标签: c# java

作为一项学习练习,我正在用Java构建一个聊天服务器,在C#中构建一个客户端。我正在使用RSA和AES在邮件发送之前对其进行加密。问题是我在使用RSA加密和解密AES密钥时遇到问题。

服务器通过序列化从文件加载私有和公共RSA密钥,或者如果找不到文件则生成新的密钥对:

public RSA(ChatServer chatServer) {
    this.server = chatServer;
    try {
        FileInputStream fileInputStream = new FileInputStream("rsa.key");
        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
        keyPair = (KeyPair)objectInputStream.readObject();
        objectInputStream.close();
        chatServer.log("RSA key pair loaded.");
    } catch (FileNotFoundException e) {
        chatServer.logWarning("No RSA key found.");
        chatServer.log("Generating new RSA key pair (This may take a few moments)...");
        keyPair = this.generateKeyPair();
        try {
            this.saveKeys();
        } catch (IOException ioe) {
            this.server.logException(ioe);
        }
    } catch (Exception e) {
        this.server.logException(e);
    }
}

public KeyPair generateKeyPair() {
    KeyPairGenerator kpg;
    try {
        kpg = KeyPairGenerator.getInstance("RSA");

        kpg.initialize(3072);

        return kpg.generateKeyPair();
    } catch (Exception e) {
        this.server.logException(e);
        return null;
    }
}

public void saveKeys() throws IOException {
    ObjectOutputStream oout = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("rsa.key")));

    try {
        oout.writeObject(this.keyPair);
    } catch (Exception e) {
        this.server.logException(e);
    } finally {
        oout.close();
    }
}

当客户端连接时,服务器将其公钥转换为.NET使用的XML格式并发送它:

public String getPublicKeyXML() {
    try {
        KeyFactory factory = KeyFactory.getInstance("RSA");
        RSAPublicKeySpec publicKey = factory.getKeySpec(this.keyPair.getPublic(), RSAPublicKeySpec.class);

        byte[] modulus = publicKey.getModulus().toByteArray();
        byte[] exponent = publicKey.getPublicExponent().toByteArray();

        String modulusStr = Base64.encodeBytes(modulus);
        String exponentStr = Base64.encodeBytes(exponent);

        String format = 
            "<RSAKeyValue>" +
                "<Modulus>%s</Modulus>" +
                "<Exponent>%s</Exponent>" +
            "</RSAKeyValue>";

        return String.format(format, modulusStr, exponentStr);
    } catch (Exception e) {
        this.server.logException(e);
        return null;
    }
}

客户收到钥匙罚款,并毫不费力地加载它。客户端然后加密随机选择的AES密钥以发送到服务器(请注意,此代码来自客户端,因此是C#而不是Java):

public static byte[] encrypt(string xmlKey, byte[] bytes)
{
    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
    rsa.FromXmlString(xmlKey);
    System.Diagnostics.Debug.WriteLine(rsa.ToXmlString(false));
    byte[] cipherBytes = rsa.Encrypt(bytes, false);
    rsa.Clear();
    return cipherBytes;
}

此代码打印的公钥与服务器发送的公钥相同,到目前为止,所有内容似乎都运行正常。服务器尝试解密时会发生此问题:

public byte[] decrypt(byte[] data) {
    try {
        PrivateKey privateKey = this.keyPair.getPrivate();
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        this.server.logDebug("Decrypting data: " + this.bytesToHex(data));
        byte[] cipherData = cipher.doFinal(data);
        return cipherData;
    } catch (Exception e) {
        this.server.logException(e);
        return new byte[0];
    }
}

这是事情变得奇怪的地方。我收到BadPaddingException告诉我数据必须以0开头;但是,作为调试措施,我让服务器打印出要解密的数据,第一个字节实际上是00!我不知道该怎么做,谷歌没有找到任何有这个问题的人。有谁知道这里可能出现什么问题?

0 个答案:

没有答案