C#中的RSA加密与其他语言不同

问题描述

我正在尝试用 C# 加密数据

在其他语言中,每个加密数据都以“==”结尾,但在 C# 中,它们不是

为什么会这样?

在python中

import base64
from Crypto.Cipher import PKCS1_v1_5 as Cipher_pksc1_v1_5
from Crypto.PublicKey import RSA

def encrpt(password,public_key):
    rsakey = RSA.importKey(public_key)
    cipher = Cipher_pksc1_v1_5.new(rsakey)
    cipher_text = base64.b64encode(cipher.encrypt(password.encode("utf-8")))
    return cipher_text.decode()

public_key = '''-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA81dCnCKt0NVH7j5Oh2+S
GgEU0aqi5u6sYXemouJWXOlZO3jqDsHYM1qfEjVvCOmeoMNFXYSXdNhflU7mjWP8
jWUmkYIQ8o3FGqMzsMTNxr+bAp0cULWu9eYmycjJwWIxxB7vUwvpEUNicgW7v5nC
wmF5HS33Hmn7yDzcfjfBs99K5xJEppHG0qc+q3YXxxPpwZNIRFn0Wtxt0Muh1U8a
vvWyw03uQ/wMBnzhwUC8T4G5NclLEWzOQExbQ4oDlZBv8BM/WxxuOyu0I8bDUDdu
tJOfREYRZBlazFHvRKNNQQD2qDfjRz484uFs7b5nykjaMB9k/EJAuHjJzGs9MMMW
tQIDAQAB
-----END PUBLIC KEY-----
'''

print(encrpt("abc",public_key))

结果

jA14duvhdPVipkWYJrvRXuNpD6yNXRwb/VnyEmc8G1UFxQoxhm8j0nPNZFuQ48oB8jZmd0kGBfwwQluPtYrJCqbtZ9qamnNp+xtSHE5BUsbXtfuF55ppWGmPsQkEUADNodMidHeUgGuP4g3E25/Vumx6iN0vRNZNFw3WFOPwAZVQEmNGfN3J2Xa3BSuaVyDh4mLp/SD5wK6ffv5+aSXP3HZQPWVe/YW3+Ok6+O3adVJ4T6r2NNIwabR+aQDqH2rCAePIum8qm8ZcV93jX0y+8pvfHzaSMzNH1dpTjPR47rUatlx44jG2ORKnvfRkACcCS+HhHfQ87WCYxCVUhWuflQ==

在 JavaScript 中

<html>
<head>
  <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jsencrypt/2.3.1/jsencrypt.min.js"
    crossorigin="anonymous"></script>
  <script>
    const crypt = new JSEncrypt();
    crypt.setPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA81dCnCKt0NVH7j5Oh2+SGgEU0aqi5u6sYXemouJWXOlZO3jqDsHYM1qfEjVvCOmeoMNFXYSXdNhflU7mjWP8jWUmkYIQ8o3FGqMzsMTNxr+bAp0cULWu9eYmycjJwWIxxB7vUwvpEUNicgW7v5nCwmF5HS33Hmn7yDzcfjfBs99K5xJEppHG0qc+q3YXxxPpwZNIRFn0Wtxt0Muh1U8avvWyw03uQ/wMBnzhwUC8T4G5NclLEWzOQExbQ4oDlZBv8BM/WxxuOyu0I8bDUDdutJOfREYRZBlazFHvRKNNQQD2qDfjRz484uFs7b5nykjaMB9k/EJAuHjJzGs9MMMWtQIDAQAB");
    const encrypted = crypt.encrypt("abc").trim();

    document.write(encrypted);
  </script>
</head>
</html>

结果

a6zdvw+y8wfQUns1UbwWPXBuChZK9mDx6x8fuX+AFcZC/HwOhU9YIl4vnSlrU5l4Kh7IUMP4LOx5o3Y4n39vXxj4oAEE1ab35y2elp1bYjQUZfXgULRAcx3O2iBSP7Dqht43HKPImagtE/aopuOuK6mwl2a1aeR7J0FCEpF2TXM2Xc+4obq0xXw+fapiGv1qGher0RbyKFNALnUeAfRtfWpYjTJ2XUlWRyE5jU455xmMl5QYFNiJa9R7GynZbolNEf9FIHBrMyuMXNB1OOAyPc6jbeSb2/IckoNR4YNS3IdQY+SE++cm9AvEqfI6e/wCWfJ2pkDN0x3kn+FDb0la5w==

在 C# 中

public static void Main()
        {
            RSACryptoServiceProvider cipher = new RSACryptoServiceProvider();
            cipher.FromXmlString("<RSAKeyValue><Modulus>MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA81dCnCKt0NVH7j5Oh2+SGgEU0aqi5u6sYXemouJWXOlZO3jqDsHYM1qfEjVvCOmeoMNFXYSXdNhflU7mjWP8jWUmkYIQ8o3FGqMzsMTNxr+bAp0cULWu9eYmycjJwWIxxB7vUwvpEUNicgW7v5nCwmF5HS33Hmn7yDzcfjfBs99K5xJEppHG0qc+q3YXxxPpwZNIRFn0Wtxt0Muh1U8avvWyw03uQ/wMBnzhwUC8T4G5NclLEWzOQExbQ4oDlZBv8BM/WxxuOyu0I8bDUDdutJOfREYRZBlazFHvRKNNQQD2qDfjRz484uFs7b5nykjaMB9k/EJAuHjJzGs9MMMWtQIDAQAB</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>");
            byte[] data = Encoding.UTF8.GetBytes("abc");
            byte[] cipherText = cipher.Encrypt(data,true);
            var result = Convert.ToBase64String(cipherText);
            Console.WriteLine(result);
        }

结果

IK47Ed8Yw8uAECMFgTMX7Ij7rAqj149QyO2AJ9P4YMzqu2MSAmRcSCKWaPzF9k8OXQmV/aXACjwJMBq2ikZjfBwuoax1rdiIdXFmvUSIbrTDAx83feTDRF+1wO31MROSXi99+LErMMMRPXacqYqcB1fy7b/NhbEdmNLHWCV62B1BvO+DCoDXHM+3ImkhbCTGU2Jeq1EkfCbJSL42RryJv6sKefmwjAcyEdXl/mSHUVdgOJrSbsCsNbkvy/iKq6ZcQnoSkxmlmF/VfFu0Ivj+31fcjY0OGkzD9CkCZGmxsRF1kG0F+lNbwbRPEU5q8pXPqCcas55BMKHJGt2EuK/662qqGr6iiSv1+YxOQ1aofV7dfoNe3sOTekpj3cVM5ART4uwOKNee

仅在 c# 中没有“==”结尾。 试了很多次,每次都是这样

我想我对 rsa 加密有很大的误解,但我不知道我误解了什么。 请帮帮我

解决方法

三个代码的密文都是Base64编码的。 Base64 使用填充 (=)。是否应用填充取决于数据的长度。由于密钥导入中的错误,C# 代码生成了不正确的密文(见下文)。因此,密文的长度与其他两个代码的密文长度不同,这就是填充不同的原因。


在 Python 和 JavaScript 代码中,公钥被导入为 PEM 编码的 X.509/SPKI 密钥。在 C# 代码中,它是作为 XML 导入的,使用 PEM 编码密钥的主体而不是模数,这是不正确的。

要解决此问题,必须从 PEM 密钥中提取模数。为此,可以使用 PEM 解析器加载 PEM 密钥,例如lapo.it/asn1js,可以确定模数:

f357429c22add0d547ee3e4e876f921a0114d1aaa2e6eeac6177a6a2e2565ce9593b78ea0ec1d8335a9f12356f08e99ea0c3455d849774d85f954ee68d63fc8d6526918210f28dc51aa333b0c4cdc6bf9b029d1c50b5aef5e626c9c8c9c16231c41eef530be91143627205bbbf99c2c261791d2df71e69fbc83cdc7e37c1b3df4ae71244a691c6d2a73eab7617c713e9c193484459f45adc6dd0cba1d54f1abef5b2c34dee43fc0c067ce1c140bc4f81b935c94b116cce404c5b438a0395906ff0133f5b1c6e3b2bb423c6c350376eb4939f44461164195acc51ef44a34d4100f6a837e3473e3ce2e16cedbe67ca48da301f64fc4240b878c9cc6b3d30c316b5

在 XML 格式中,模数是预期的 Base64 编码,这是可行的,例如在线与cryptii.com/pipes/base64-to-hex

81dCnCKt0NVH7j5Oh2+SGgEU0aqi5u6sYXemouJWXOlZO3jqDsHYM1qfEjVvCOmeoMNFXYSXdNhflU7mjWP8jWUmkYIQ8o3FGqMzsMTNxr+bAp0cULWu9eYmycjJwWIxxB7vUwvpEUNicgW7v5nCwmF5HS33Hmn7yDzcfjfBs99K5xJEppHG0qc+q3YXxxPpwZNIRFn0Wtxt0Muh1U8avvWyw03uQ/wMBnzhwUC8T4G5NclLEWzOQExbQ4oDlZBv8BM/WxxuOyu0I8bDUDdutJOfREYRZBlazFHvRKNNQQD2qDfjRz484uFs7b5nykjaMB9k/EJAuHjJzGs9MMMWtQ==

或者,可以使用在线转换器将 PEM 密钥直接转换为 XML 格式,例如superdry.apphb.com/tools/online-rsa-key-converter

<RSAKeyValue>
    <Modulus>81dCnCKt0NVH7j5Oh2+SGgEU0aqi5u6sYXemouJWXOlZO3jqDsHYM1qfEjVvCOmeoMNFXYSXdNhflU7mjWP8jWUmkYIQ8o3FGqMzsMTNxr+bAp0cULWu9eYmycjJwWIxxB7vUwvpEUNicgW7v5nCwmF5HS33Hmn7yDzcfjfBs99K5xJEppHG0qc+q3YXxxPpwZNIRFn0Wtxt0Muh1U8avvWyw03uQ/wMBnzhwUC8T4G5NclLEWzOQExbQ4oDlZBv8BM/WxxuOyu0I8bDUDdutJOfREYRZBlazFHvRKNNQQD2qDfjRz484uFs7b5nykjaMB9k/EJAuHjJzGs9MMMWtQ==</Modulus>
    <Exponent>AQAB</Exponent>
</RSAKeyValue>

当然,两者都提供相同的模数。

另一种可能性是,在 C# 代码中,PEM 密钥是直接导入的。在 .NET Core 中,从 3.0 版开始,可以使用 RSA.ImportSubjectPublicKeyInfo() 方法导入 X.509/SPKI 格式的 DER 编码密钥。 DER 编码通过删除页眉、页脚和换行符以及 Base64 解码其余部分由 PEM 编码的密钥产生。在较低的 .NET Core 版本或 .NET Framework 中,BouncyCastle 支持导入 PEM 密钥。

使用正确的模数,C# 代码提供正确的密文。


请注意,Python 和 JavaScript 代码使用与 C# 代码不同的填充。 Python 和 JavaScript 代码应用 PKCS#1 v1.5 填充,而 C# 代码使用 OAEP。要使 C# 代码也应用 PKCS#1 v1.5,RSACryptoServiceProvider.Encrypt() 必须在第二个参数中传递 false

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...