C# RSA加密结果末尾无==与其他语言存在差异的原因是什么
问题根因
这个现象和RSA加密本身的规则无关,是两个问题共同导致的:
- C#代码中公钥导入逻辑完全错误
- Base64编码的填充规则差异
1. Base64填充规则说明
Base64编码的本质是把每3字节原始数据转换为4个可打印字符,末尾的==是填充符:
- 原始数据长度模3余1:末尾补2个
= - 原始数据长度模3余2:末尾补1个
= - 原始数据长度模3余0:不需要补填充符,末尾没有
=
你用的是2048位RSA密钥,标准加密后的密文长度固定为256字节,256除以3余1,所以正常加密后的密文转Base64之后末尾必然带2个=,Python和JS的结果是符合预期的。
2. C#代码的错误点
你直接把完整的PEM格式公钥(整个-----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----之间的内容)塞进了<RSAKeyValue>的<Modulus>节点,这是完全错误的用法:
- RSA的XML格式公钥中,
<Modulus>节点仅接受RSA公钥解析后的模数N的Base64编码,<Exponent>节点接受公钥指数E的Base64编码 - 你把整个公钥结构当做模数导入,相当于使用了一个长度不符合规范的RSA密钥,加密出来的密文长度不是标准的256字节,转Base64之后长度刚好模3余0,自然就没有末尾的
==
修复方案
如果你用的是.NET Core 3.0+ / .NET 5+,可以直接导入PEM公钥,不需要手动转XML格式,示例代码如下:
using System.Security.Cryptography; using System.Text; public static void Main() { string publicKeyPem = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA81dCnCKt0NVH7j5Oh2+SGgEU0aqi5u6sYXemouJWXOlZO3jqDsHYM1qfEjVvCOmeoMNFXYSXdNhflU7mjWP8jWUmkYIQ8o3FGqMzsMTNxr+bAp0cULWu9eYmycjJwWIxxB7vUwvpEUNicgW7v5nCwmF5HS33Hmn7yDzcfjfBs99K5xJEppHG0qc+q3YXxxPpwZNIRFn0Wtxt0Muh1U8avvWyw03uQ/wMBnzhwUC8T4G5NclLEWzOQExbQ4oDlZBv8BM/WxxuOyu0I8bDUDdutJOfREYRZBlazFHvRKNNQQD2qDfjRz484uFs7b5nykjaMB9k/EJAuHjJzGs9MMMWtQIDAQAB"; byte[] publicKeyBytes = Convert.FromBase64String(publicKeyPem); using RSA rsa = RSA.Create(); rsa.ImportSubjectPublicKeyInfo(publicKeyBytes, out _); byte[] data = Encoding.UTF8.GetBytes("abc"); byte[] cipherText = rsa.Encrypt(data, RSAEncryptionPadding.Pkcs1); string result = Convert.ToBase64String(cipherText); Console.WriteLine(result); }
修复后加密出来的密文也是256字节,转Base64之后末尾就会出现==,另外RSA的PKCS#1填充是带随机数的,所以每次加密结果不同属于正常现象,不影响解密。
内容的提问来源于stack exchange,提问作者YJU
相关产品推荐
相关产品推荐

