PHP 和 C# HMAC SHA256
PHP and 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 源代码可在此 link
这个我也查了posthmac_sha256 in php and c# differ
还有这个C# equivalent to hash_hmac in PHP
但是结果不一样
这段代码应该可以解决问题:
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());
它returns:
4e4feaea959d426155a480dc07ef92f4754ee93edbe56d993d74f131497e66fb
当我 运行 这个在 PHP:
echo hash_hmac('sha256', "1234", "1234", false);
它returns
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<string, string>
{
{ "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 提供的加密密钥是 base 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 class 翻译成 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/
//
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) {
//
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。
我需要在 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 源代码可在此 link
这个我也查了posthmac_sha256 in php and c# differ
还有这个C# equivalent to hash_hmac in PHP
但是结果不一样
这段代码应该可以解决问题:
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());
它returns:
4e4feaea959d426155a480dc07ef92f4754ee93edbe56d993d74f131497e66fb
当我 运行 这个在 PHP:
echo hash_hmac('sha256', "1234", "1234", false);
它returns
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<string, string>
{
{ "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 提供的加密密钥是 base 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 class 翻译成 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/
//
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) {
//
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。