在C#中实现Java的RSA解密方法:异常及字节序疑问
Java RSA解密转C#的异常与字节序问题
我用Java实现了RSA解密:通过new RSAPrivateKeySpec(BigInteger modulus, BigInteger privateExponent)从十六进制字符串生成私钥,搭配BouncyCastle Provider和RSA/ECB/PKCS1Padding模式完成解密。转C#实现时,调用Decrypt方法抛出"Key does not exist"异常,同时不确定是否需要对Java的十六进制字符串执行SwapBytes操作,我的C#代码如下:
byte[] dataToDecrypt = Convert.FromBase64String("AJqdug3s19c6bi8FaQrz0Q+qLnX/7mFmaNL2ztFeZyx0yeg9+lI48qFBRoS000JHaljlhVJpjACLr/qYk4ZdZjJHD0ENJmv+lf4TmTGQZpv3uiUQpG7QbVP7c56yWK4MgyMd8EdhJLcviobShkW3lI1a46C4vF+37WzH6qvgMuuUvtPi8mi9GvhPHHuocAh05s+c5YN2R78+tpkrs05EU6fiSn3iqRnrXv48O9kxQs9S/w4xaFLgfu2wbcgyI62s2Xbri1WdfSPUIYaLmv1EvVnzBPIty4Wclun25RmB8UtH5EZXpFOGF5ER8OztCcUeTAQYP9n9W2aQOqfpIjcNMA=="); RSAParameters rsaparam = new RSAParameters(); rsaparam.Modulus = XUtils.SwapBytes( XUtils.HexStringToByteArray( "E86763F6B409ECCA94818F7438385D6C12237B5458974C5FD8573A62383DF55B7A39F73F27D5069981FB045042374A123828016AAD4BA94A77609624E44BD83D6F8CD4751D9F3E546D9E56BC55D8554ACFDF28FE9F97B01E53F9A4CE6DADFACC9D4499C186D41B65426206AC55DCBEC7F658104405E911D11034B462B3279E731B1D3E44244D3C60300261A82A5B28F01AD58F4A2D3B230501B00528956D820E1AA27FB25DC483376390A3C26C97AD84B744BDBB8F9C65E6CDA2A66AD12AE660D6CE26DC44F0AB055E6A7F7A19161F1ACFA09A14E34A555F43AC00B5BFAA834CCDB00AE5953696E38003EBEF1CA2531DF354929047858BFB50409FFEC2A1BF33")); rsaparam.D = XUtils.SwapBytes( XUtils.HexStringToByteArray( "7DF673DEE62C2EF489D3432E89BE3B1C752458171A413EFAFFE61F55D707F5F153E9111261037C253DA710EA7349465363AE833E0F995FB365CAAAF669EA95D48E9E7514D92E53792D44D1DC18673DAB63C99F8D8A708BDB94464DC638FA406220A76AF2D2A22A0B1314D06B1DCA9C7903132E15C06257EEC96AD78E5B6E10D967F480538FB9933E120750CDD31DC004BB94D0CD293C47EBC98D783B17C575DEC75751F99F82C026026773534B213446B14D4978EC44CD290908CBB3AF5FF35055A5698B096F66109B60C1A39D2A34FA791E421914E0137CCA3C95872FB39DD0586F2F4EFD6D1027596199F259D76FA3727B752EE76B4FE9C4A1BE18A6E67EC1")); rsaparam.Exponent = new byte[] { 0x1, 0x0, 0x1 }; RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); RSA.ImportParameters(rsaparam); byte[] decryptedData = RSA.Decrypt(dataToDecrypt, false); string s = Encoding.ASCII.GetString(decryptedData);
问题解决
核心原因:字节序错误
Java中BigInteger的十六进制字符串是大端字节序(高位在前),直接转字节数组后与C# RSAParameters要求的格式一致。你执行的SwapBytes会反转字节序,导致Modulus和D参数无效,触发"Key does not exist"异常。
修正步骤
- 移除
SwapBytes调用:直接将十六进制字符串转为字节数组即可,无需反转。 - 确认填充模式匹配:Java的
RSA/ECB/PKCS1Padding对应C#RSA.Decrypt(..., false)(false表示使用PKCS#1 v1.5填充),这部分无需修改。 - 验证Exponent参数:
new byte[] { 0x01, 0x00, 0x01 }是标准的65537公钥指数,格式正确。
修正后的代码
byte[] dataToDecrypt = Convert.FromBase64String("AJqdug3s19c6bi8FaQrz0Q+qLnX/7mFmaNL2ztFeZyx0yeg9+lI48qFBRoS000JHaljlhVJpjACLr/qYk4ZdZjJHD0ENJmv+lf4TmTGQZpv3uiUQpG7QbVP7c56yWK4MgyMd8EdhJLcviobShkW3lI1a46C4vF+37WzH6qvgMuuUvtPi8mi9GvhPHHuocAh05s+c5YN2R78+tpkrs05EU6fiSn3iqRnrXv48O9kxQs9S/w4xaFLgfu2wbcgyI62s2Xbri1WdfSPUIYaLmv1EvVnzBPIty4Wclun25RmB8UtH5EZXpFOGF5ER8OztCcUeTAQYP9n9W2aQOqfpIjcNMA=="); RSAParameters rsaparam = new RSAParameters(); // 直接转换十六进制字符串为字节数组,无需反转字节序 rsaparam.Modulus = XUtils.HexStringToByteArray( "E86763F6B409ECCA94818F7438385D6C12237B5458974C5FD8573A62383DF55B7A39F73F27D5069981FB045042374A123828016AAD4BA94A77609624E44BD83D6F8CD4751D9F3E546D9E56BC55D8554ACFDF28FE9F97B01E53F9A4CE6DADFACC9D4499C186D41B65426206AC55DCBEC7F658104405E911D11034B462B3279E731B1D3E44244D3C60300261A82A5B28F01AD58F4A2D3B230501B00528956D820E1AA27FB25DC483376390A3C26C97AD84B744BDBB8F9C65E6CDA2A66AD12AE660D6CE26DC44F0AB055E6A7F7A19161F1ACFA09A14E34A555F43AC00B5BFAA834CCDB00AE5953696E38003EBEF1CA2531DF354929047858BFB50409FFEC2A1BF33"); rsaparam.D = XUtils.HexStringToByteArray( "7DF673DEE62C2EF489D3432E89BE3B1C752458171A413EFAFFE61F55D707F5F153E9111261037C253DA710EA7349465363AE833E0F995FB365CAAAF669EA95D48E9E7514D92E53792D44D1DC18673DAB63C99F8D8A708BDB94464DC638FA406220A76AF2D2A22A0B1314D06B1DCA9C7903132E15C06257EEC96AD78E5B6E10D967F480538FB9933E120750CDD31DC004BB94D0CD293C47EBC98D783B17C575DEC75751F99F82C026026773534B213446B14D4978EC44CD290908CBB3AF5FF35055A5698B096F66109B60C1A39D2A34FA791E421914E0137CCA3C95872FB39DD0586F2F4EFD6D1027596199F259D76FA3727B752EE76B4FE9C4A1BE18A6E67EC1"); rsaparam.Exponent = new byte[] { 0x01, 0x00, 0x01 }; RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); RSA.ImportParameters(rsaparam); byte[] decryptedData = RSA.Decrypt(dataToDecrypt, false); string s = Encoding.ASCII.GetString(decryptedData);
额外注意
确保XUtils.HexStringToByteArray方法是按顺序转换(如"AB"转0xAB,"ABCD"转0xAB, 0xCD),不要额外处理字节序。
内容的提问来源于stack exchange,提问作者Denis
相关产品推荐
相关产品推荐

