如何在C#中实现PHP的AES-256-CBC加密(openssl_encrypt)
PHP AES-256-CBC加密逻辑的C#等效实现问题
对接第三方API时,要求按照以下PHP示例实现POST请求payload的加密,但只能使用C#开发:
class RESTfulAPI { function __construct($DomainOrIP, $Key, $Secret) { $this->BaseUri = $DomainOrIP ."/api/v2/"; $this->ApiKey = $Key; $this->ApiSecret = $Secret; // Encryption vector initialization $this->SecretIV = substr(hash("SHA256", $this->ApiKey, true), 0, 16); } function base64Url_Encode($data) { return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); } // Encryption for properties function APIEncryptData($Data) { $output = openssl_encrypt( $Data, "AES-256-CBC", md5($this->ApiSecret), OPENSSL_RAW_DATA, $this->SecretIV); return $this->base64Url_Encode($output); } }
加密逻辑说明
该PHP示例的核心加密规则:
- 加密模式:AES-256-CBC
- 密钥:ApiSecret的MD5哈希值
- IV向量:ApiKey经SHA256哈希后取前16位字节
- 输出:加密后的原始字节做Base64Url编码(替换
+为-、/为_,去除末尾=)
已实现的C#辅助方法
已完成与PHP等效的SHA256、MD5哈希及Base64Url编码方法:
private static byte[] Sha256(string input) { using (SHA256 sha = SHA256.Create()) { return sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes(input)); } } private static byte[] Md5(string input) { using (MD5 md5 = MD5.Create()) { return md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(input)); } } private string Base64UrlEncode(byte[] data) { var base64 = Convert.ToBase64String(data); base64 = base64.Replace("+", "-").Replace("/", "_").TrimEnd('='); return base64; }
尝试的C#加密实现
已尝试原生AES和BouncyCastle两种方式,但结果均与PHP不一致:
// 初始化参数 _secretIV = Sha256(Key).Take(16).ToArray(); _hashedApiKey = Md5(Secret); // 原生AES实现 private string APIEncryptDataV1(string data) { using (var aes = Aes.Create()) { aes.Key = _hashedApiKey; aes.IV = _secretIV; aes.Mode = CipherMode.CBC; using (var encryptor = aes.CreateEncryptor()) { using (var msEncrypt = new MemoryStream()) { using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) { using (var swEncrypt = new StreamWriter(csEncrypt)) { swEncrypt.Write(data); } return Base64UrlEncode(msEncrypt.ToArray()); } } } } } // BouncyCastle实现 public string APIEncryptDataV2(string data) { var dataBytes = Encoding.UTF8.GetBytes(data); // Create AES Engine AesEngine engine = new AesEngine(); // Create CBC Mode CbcBlockCipher blockCipher = new CbcBlockCipher(engine); // Create Padding Pkcs7Padding padding = new Pkcs7Padding(); // Create BufferedBlockCipher BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(blockCipher, padding); // Create Key Parameter KeyParameter keyParam = new KeyParameter(_hashedApiKey); // Create IV Parameter ParametersWithIV ivParam = new ParametersWithIV(keyParam, _secretIV); // Init Cipher cipher.Init(true, ivParam); // Encrypt Data var output = new byte[cipher.GetOutputSize(dataBytes.Length)]; int outputLength = cipher.ProcessBytes(dataBytes, output, 0); cipher.DoFinal(output, outputLength); return Base64UrlEncode(output); }
测试样本及结果
Key: Q8ZHQ8P5RH5V1RVYS29S3XHDV4PTS7XX Secret: 527L1MDDQ7WDNDZ13ZHWLNY2D7JV5LXX Data: Test123 PHP APIEncryptData result: xwMzbdEVqer8Py-c9hapFQ C# APIEncryptDataV1 result: fcklnK82vuNT3DlLJF8h1A C# APIEncryptDataV2 result: fcklnK82vuNT3DlLJF8h1A
两种C#实现的结果一致,但均与PHP的加密结果不符,缺乏密码学经验无法定位问题,请求排查错误。
内容的提问来源于stack exchange,提问作者Francesco Bonizzi
相关产品推荐
相关产品推荐

