C# 使用Bouncy Castle解决C和Java之间的RSA加密问题

C# 使用Bouncy Castle解决C和Java之间的RSA加密问题,c#,java,encryption,bouncycastle,C#,Java,Encryption,Bouncycastle,我在一个Java应用程序和另一个C语言应用程序中遇到了几个问题。有一个服务器应用程序,它通过HTTP接收请求,处理并发送 支持回答。该服务器使用Bouncy Castle用Java编写,我们使用PKI加密请求中的敏感数据。我们有许多服务器可以识别的操作 其中一个用于生成用于和客户端交换的公钥和私钥。每个客户端都有一个唯一的ID,因此当此操作命名为 执行GetEncryptionKey时,它会生成私钥并将其保存在服务器本地,并生成以PEM格式发回的公钥,如下所示: encryptionKey=--

我在一个Java应用程序和另一个C语言应用程序中遇到了几个问题。有一个服务器应用程序,它通过HTTP接收请求,处理并发送 支持回答。该服务器使用Bouncy Castle用Java编写,我们使用PKI加密请求中的敏感数据。我们有许多服务器可以识别的操作 其中一个用于生成用于和客户端交换的公钥和私钥。每个客户端都有一个唯一的ID,因此当此操作命名为 执行GetEncryptionKey时,它会生成私钥并将其保存在服务器本地,并生成以PEM格式发回的公钥,如下所示:

encryptionKey=-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAon1WDHdarN7yq0UOevzW
5PiFsSC8bEkTUOZ6X3RIth+RCU42pUj/Z8fp9T8rbWp8CqbhlFDxU4c+YucpGljC
7A10nkrPoBT0lpHEuXJiSgx+9qqsyo9q6GddhOpdMa+Z6VCfI+JCM3kdJNMH3r+o
i+WLPHLB8lxnfT2CHyZVQGhkzrH9fk1XhdenXxjtPGpwYBOsUZUwRt8EeW6JUwSI
mKXiXag0IViEcyAa2BvProkxklbQB3BczLHdXjIDwnE6u1aMA7pYPSkBtY6tuQ0F
5sNWXHsaKWON33MnbhlM7sieYDi9L4dWksala/m/mdIeHIXzX4ZCYdOhayWWKZ1N
HwIDAQAB
-----END PUBLIC KEY-----
这工作正常。用于生成密钥的代码如下所示:

private void getEncryptedKey()  throws GWTranException {

    PEMWriter pemWriter;

    Security.addProvider(new BouncyCastleProvider());
    KeyPair keyPair = null;

    KeyPairGenerator keyPairGenerator = null;

    try {
        keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }

    keyPairGenerator.initialize(2048);
    keyPair = keyPairGenerator.generateKeyPair();

    StringWriter writer = new StringWriter();

    try {

        pemWriter = new PEMWriter(new PrintWriter(writer));
        pemWriter.writeObject(keyPair.getPublic());
        pemWriter.flush();
        String pem = writer.toString();

        savePrivateKey(keyPair, pem);           // save the private key locally

    } catch (IOException e) {
        e.printStackTrace();
    }
}
现在我有了一个用C编写的客户端,它连接到服务器,检索响应中发送的公钥,并使用它加密将加密的字符串。 这是非常简单的.NET代码,因为我只是在测试功能:

private string EncryptDataWithRSA(string data) {

    string cryptedData = string.Empty;

    RsaKeyParameters rsaParams;
        using (var reader = new StringReader(txtKey.Text)) {
        rsaParams = (RsaKeyParameters)new PemReader(reader).ReadObject();
        reader.Close();
    }

    IAsymmetricBlockCipher eng = new RsaEngine();
    eng = new OaepEncoding(eng);
    eng.Init(true, rsaParams);

    var dataBytes = Encoding.UTF8.GetBytes(data);
    var cryptedDataBytes = eng.ProcessBlock(dataBytes, 0, dataBytes.Length);
    cryptedData = Convert.ToBase64String(cryptedDataBytes);

    return cryptedData;
}
一切看起来都不错,但问题是,当服务器Java应用程序尝试解密数据时,我遇到了一个异常:

javax.crypto.BadPaddingException: data hash wrong
    at org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi.engineDoFinal(Unknown Source)
    at javax.crypto.Cipher.doFinal(DashoA13*..)
    at com.verifone.gateway.security.RSAEncryptUtil.decrypt(RSAEncryptUtil.java:127)
    at com.verifone.gateway.security.RSAEncryptUtil.decrypt(RSAEncryptUtil.java:152)
    at com.verifone.gateway.preonline.PreOnlineJob.decryptData(PreOnlineJob.java:1661)
    at com.verifone.gateway.preonline.PreOnlineJob.extractCardData(PreOnlineJob.java:989)
    at com.verifone.gateway.preonline.PreOnlineJob.run(PreOnlineJob.java:288)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
这与另一个客户端在iOS中写的情况很好,但我没有访问源代码的权限。我正在用.NET写一个模拟器,但我不能 正确解密信息。在服务器端,这是用于解密数据的代码的一部分:

public static byte[] decrypt(byte[] text, PrivateKey key) throws Exception
{
    byte[] dectyptedText = null;
    try {
        // decrypt the text using the private key
        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPadding");
        cipher.init(Cipher.DECRYPT_MODE, key);

        dectyptedText = cipher.doFinal(text);
    }
    catch (Exception e) {
        //_log.error(e, e);
        throw e;
    }

    return dectyptedText;
}
我没有主意了,我什么都试过了。你看到我没有看到的东西了吗?
感谢您的帮助。

删除起始“encryptionKey=”中的文本这可能是个问题。此外,如果您在代码中的任何地方编辑了密钥,请不要这样做。即使删除一个空链接也不是万能的。不,这部分不是用来获取密钥的。已正确创建RsaKeyParameters对象。我不会改变钥匙上的任何东西。谢谢ZeusI看到你在客户端上转换为base64,是从base64解码为byte[]吗?很好。无论如何,是的,它将它从Base64转换为:BASE64Decoder b64=新的BASE64Decoder;返回b64.decodeBuffertext;