PHP和C#HMAC SHA256

我需要在C#中转换以下php代码:

$res = mac256($ent, $key); $result = encodeBase64($res); 

哪里

 function encodeBase64($data) { $data = base64_encode($data); return $data; } 

 function mac256($ent,$key) { $res = hash_hmac('sha256', $ent, $key, true);//(PHP 5 >= 5.1.2) return $res; } 

我使用以下C#代码:

 byte[] res = HashHMAC(ent, key); string result = System.Convert.ToBase64String(res); 

哪里

 public byte[] HashHMAC(string ent, byte[] key) { byte[] toEncryptArray =System.Text.Encoding.GetEncoding(28591).GetBytes(ent); HMACSHA256 hash = new HMACSHA256(key); return hash.ComputeHash(toEncryptArray); } 

这个链接提供完整的php源代码

我也在php中检查了这篇文章hmac_sha256和c#的区别

而这一个C#相当于PHP中的hash_hmac

但结果却不尽相同。

这段代码应该可以解决问题:

 static byte[] hmacSHA256(String data, String key) { using (HMACSHA256 hmac = new HMACSHA256(Encoding.ASCII.GetBytes(key))) { return hmac.ComputeHash(Encoding.ASCII.GetBytes(data)); } } 

如果我调用此代码:

 Console.WriteLine(BitConverter.ToString(hmacSHA256("1234", "1234")).Replace("-", "").ToLower()); 

它返回:

 4e4feaea959d426155a480dc07ef92f4754ee93edbe56d993d74f131497e66fb 

当我在PHP中运行时:

 echo hash_hmac('sha256', "1234", "1234", false); 

它回来了

 4e4feaea959d426155a480dc07ef92f4754ee93edbe56d993d74f131497e66fb 

我很确定你正在处理新的RedSys SHA256签名实现。 另外我看到你在PHP和C#之间的3DES加密方面存在一些问题。

首先,您必须获得包含所有付款参数的base 64字符串。 您可以使用以下代码实现它:

 public static string GetParameters(string merchantCode, string terminal, int currency, string transactionType, decimal amount, string merchantOrder, string merchantIdentifier, string merchantPost, string urlOk, string urlKo) { var jsonValues = new Dictionary { { "Ds_Merchant_Amount", amount.ToString().Replace(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator, "") }, { "Ds_Merchant_Order", merchantOrder}, { "Ds_Merchant_MerchantCode", merchantCode }, { "Ds_Merchant_Currency", currency.ToString() }, { "Ds_Merchant_TransactionType", transactionType }, { "Ds_Merchant_Terminal", terminal }, { "Ds_Merchant_Identifier", merchantIdentifier }, { "Ds_Merchant_MerchantURL", merchantPost }, { "Ds_Merchant_UrlOK", urlOk}, { "Ds_Merchant_UrlKO", urlKo} }.Select(kvp => "\"{0}\":\"{1}\"".Formato(kvp.Key.ToUpper(), kvp.Value)); var jsonString = "{" + string.Join(",", jsonValues) + "}"; return Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(jsonString)); } 

在base 64中有JSON字符串后,必须使用RedSys提供的密钥将3DES应用于商家订单参数:

 public static string GetTransactionEncryptionKey(string merchantOrder, string encryptKey) { using (var tdes = new TripleDESCryptoServiceProvider()) { tdes.IV = new byte[8] { 0, 0, 0, 0, 0, 0, 0, 0 }; tdes.Key = Convert.FromBase64String(encryptKey); tdes.Padding = PaddingMode.Zeros; tdes.Mode = CipherMode.CBC; var toEncrypt = ASCIIEncoding.ASCII.GetBytes(merchantOrder); var result = tdes.CreateEncryptor().TransformFinalBlock(toEncrypt, 0, toEncrypt.Length); return Convert.ToBase64String(result); } } 

如您所见,RedSys提供的加密密钥是64位字符串,因此您无需计算3DES算法的MD5哈希值。

然后我们去找SHA256签名:

 public static string GetSignature(string base64Parameters, string base64tranEncryptKey) { using (var sha = new HMACSHA256(Convert.FromBase64String(base64tranEncryptKey))) { var hash = sha.ComputeHash(ASCIIEncoding.ASCII.GetBytes(base64Parameters)); return Convert.ToBase64String(hash); } } 

祝好运!

Redsys为php和java提供了库。

从java库开始,我将ApiMacSha256类翻译成C#

 public class ApiMacSha256 { ////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////// //////////// FUNCIONES AUXILIARES: /////////// ////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////// /** 3DES Function */ private byte[] encrypt_3DES(byte[] key, string data) { //http://www.mywebexperiences.com/2012/12/11/crypting-data-using-3des-c/ //http://stackoverflow.com/a/33479952/2938518 using (var tdes = new TripleDESCryptoServiceProvider()) { tdes.IV = new byte[8] { 0, 0, 0, 0, 0, 0, 0, 0 }; tdes.Key = key; tdes.Padding = PaddingMode.Zeros; tdes.Mode = CipherMode.CBC; var toEncrypt = Encoding.ASCII.GetBytes(data); var result = tdes.CreateEncryptor().TransformFinalBlock(toEncrypt, 0, toEncrypt.Length); return result; } } /** MAC Function */ private byte[] mac256(string dsMerchantParameters, byte[] secretKo) { //http://stackoverflow.com/a/17315619/2938518 byte[] hash; using (var hmac = new HMACSHA256(secretKo)) { hash = hmac.ComputeHash(Encoding.ASCII.GetBytes(dsMerchantParameters)); } return hash; } /** Base64 Functions */ private string encodeB64String(byte[] data) { return Convert.ToBase64String(data, Base64FormattingOptions.None); } ////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////// //////////// FUNCIONES PARA LA GENERACIÓN DEL FORMULARIO DE PAGO: //////////// ////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////// public String createMerchantSignature(string merchantParamsB64, string claveComercio, string OrderId) { byte[] clave = Convert.FromBase64String(claveComercio); byte[] secretKo = encrypt_3DES(clave, OrderId); // Se hace el MAC con la clave de la operación "Ko" y se codifica en BASE64 byte[] hash = mac256(merchantParamsB64, secretKo); String res = encodeB64String(hash); return res; } } 

主要方法’createMerchantSignature’,需要在嵌入json结构的商家参数的base64中编码的字符串,商家的密钥和OrderId。