在跨平台业务场景中,经常需要实现C#端对敏感数据加密,PHP端解密验证的功能,由于C#和PHP的RSA实现默认参数存在差异,直接对接容易出现解密失败的情况,需要针对性处理密钥格式和加密参数。

C#端RSA加密实现
密钥生成与导出
C#的RSA密钥默认是XML格式,需要先生成密钥对并导出为可适配PHP的格式,这里使用PKCS1格式的PEM公钥,方便PHP端读取。
using System;
using System.Security.Cryptography;
using System.Text;
public class CSharpRSAEncrypt
{
// 生成RSA密钥对,返回公钥和私钥
public static (string publicKey, string privateKey) GenerateKey()
{
using (RSA rsa = RSA.Create(2048))
{
// 导出PKCS1格式的公钥
byte[] publicKeyBytes = rsa.ExportRSAPublicKey();
string publicKeyPem = "-----BEGIN RSA PUBLIC KEY-----n" +
Convert.ToBase64String(publicKeyBytes, Base64FormattingOptions.InsertLineBreaks) +
"n-----END RSA PUBLIC KEY-----";
// 导出PKCS1格式的私钥
byte[] privateKeyBytes = rsa.ExportRSAPrivateKey();
string privateKeyPem = "-----BEGIN RSA PRIVATE KEY-----n" +
Convert.ToBase64String(privateKeyBytes, Base64FormattingOptions.InsertLineBreaks) +
"n-----END RSA PRIVATE KEY-----";
return (publicKeyPem, privateKeyPem);
}
}
// RSA加密方法,使用公钥加密,填充方式为PKCS1
public static string Encrypt(string data, string publicKeyPem)
{
using (RSA rsa = RSA.Create())
{
// 加载公钥
rsa.ImportFromPem(publicKeyPem);
byte[] dataBytes = Encoding.UTF8.GetBytes(data);
// 使用PKCS1填充加密
byte[] encryptedBytes = rsa.Encrypt(dataBytes, RSAEncryptionPadding.Pkcs1);
return Convert.ToBase64String(encryptedBytes);
}
}
}
// 使用示例
class Program
{
static void Main()
{
var (pubKey, priKey) = CSharpRSAEncrypt.GenerateKey();
Console.WriteLine("公钥:n" + pubKey);
Console.WriteLine("私钥:n" + priKey);
string encrypted = CSharpRSAEncrypt.Encrypt("测试跨平台加密数据", pubKey);
Console.WriteLine("加密结果:" + encrypted);
}
}
关键参数说明
C#端加密时需要注意两个核心点,一是密钥格式要使用ImportFromPem方法加载标准PEM格式,二是填充方式要和PHP端保持一致,这里选择RSAEncryptionPadding.Pkcs1,对应PHP的OPENSSL_PKCS1_PADDING。
PHP端RSA解密实现
密钥处理与解密
PHP的openssl扩展默认支持PEM格式的RSA密钥,直接使用C#导出的公钥即可,解密时填充模式要和C#端对应。
<?php
class PhpRSADecrypt {
// PHP端解密方法,使用私钥解密
public static function decrypt($encryptedData, $privateKeyPem) {
// 解密时填充模式使用OPENSSL_PKCS1_PADDING,和C#端的Pkcs1对应
$decrypted = openssl_private_decrypt(
base64_decode($encryptedData),
$output,
$privateKeyPem,
OPENSSL_PKCS1_PADDING
);
if ($decrypted) {
return $output;
} else {
// 打印错误信息方便排查问题
echo "解密失败,错误:" . openssl_error_string();
return null;
}
}
}
// 假设从C#端获取到的私钥和加密数据
$privateKey = "-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAxxxxxx(替换为实际私钥内容)
-----END RSA PRIVATE KEY-----";
$encryptedData = "xxxxxx(替换为C#加密后的Base64字符串)";
$result = PhpRSADecrypt::decrypt($encryptedData, $privateKey);
if ($result != null) {
echo "解密结果:" . $result;
}
?>
常见问题排查
- 密钥格式不匹配:C#导出的PEM密钥需要包含正确的头尾标识,PHP端加载时如果报错,检查密钥是否有换行、是否缺少头尾行。
- 填充方式不一致:C#和PHP的填充方式必须完全对应,否则会解密失败,PKCS1对应OPENSSL_PKCS1_PADDING,OAEP对应OPENSSL_PKCS1_OAEP_PADDING。
- 数据长度限制:RSA加密有长度限制,2048位密钥单次最多加密245字节数据,超过长度需要分段加密,或者改用混合加密方案。
总结
实现C# RSA加密与PHP解密的跨平台对接,核心是统一密钥格式和加密填充参数,C#端导出标准PEM格式的PKCS1密钥,使用Pkcs1填充加密,PHP端使用对应的私钥和OPENSSL_PKCS1_PADDING填充解密,即可完成稳定的跨平台加密解密流程。