将 HMAC-SHA1 PHP 脚本转换为 C# 脚本
Convert HMAC-SHA1 PHP script to C# script
我正在开发一个使用 API 的项目,我需要为 Web 服务调用 header 生成签名。 API 文档提供了一些 PHP 示例代码和 "known good" 结果,因此您可以将其转换为您选择的编程语言,我已经 运行 撞墙了,我需要一些帮助。
我以前从未使用过 HMAC,所以这对我来说很陌生,如果能提供任何反馈,我将不胜感激。
基本上 API 提供了一个示例 PHP 脚本及其结果,以便您可以编写您的版本并进行测试。
这是 PHP 示例及其结果。我将 post 我当前的 C# 尝试使用下面的相同代码。再次感谢您提供的任何帮助。
Use the following code example to compare your signature generation with a
known signature. The PHP code example that follows provides a reference to
the generation of a signature for a GET call into the CDRN API. Use your
code with the parameter values listed to validate the same signature is
generated.
<?php
$cdrn_domain = "api.testing.cdrn.com";
$secret_key = "cdrnpassword";
$api_version = "1.1";
$method_type = "GET";
$case_id = "12345";
$string_date = "2014-06-20T12:06:31Z";
$string_to_sign = $method_type . "\n" . $cdrn_domain . "\n" . "/partners/cases/$case_id" . "\n" . "" . "\n" . $api_version . "\n" . $string_date . "\n";
$signature = utf8_encode(base64_encode(hash_hmac('sha1', $string_to_sign, $secret_key, false)));
echo "SIGNATURE[$signature]";
?>
输出:
签名[NWY3N2Q0NTdmZDQxZjA4YWI0Njg3YTEwODljODdiNTEwMTdmMzNlZg==]
这是我需要帮助的 C# 代码:
using System.Security.Cryptography;
string cdrn_domain = "api.testing.cdrn.com";
string secret_key = "cdrnpassword";
string api_version = "1.1";
string method_type = "GET";
string case_id = "12345";
string string_date = "2014-06-20T12:06:31Z";
string string_to_sign = method_type + "\n" + cdrn_domain + "\n" + "/partners/cases/" + case_id + "\n" + "" + "\n" + api_version + "\n" + string_date + "\n";
var result = CreateSignature(string_to_sign, secret_key);
public string CreateSignature(string message, string key)
{
var encoding = new System.Text.UTF8Encoding();
byte[] keyByte = encoding.GetBytes(key);
byte[] messageBytes = encoding.GetBytes(message);
using (var hmacsha1 = new HMACSHA1(keyByte, false))
{
byte[] hashmessage = hmacsha1.ComputeHash(messageBytes);
return Convert.ToBase64String(hashmessage);
}
}
从我的 C# 代码生成的签名是:
X3fUV/1B8Iq0aHoQich7UQF/M+8=
这里的问题是因为您(或API)编码了错误的散列值。
来自 hash_hmac
的 PHP 文档:
string hash_hmac ( string $algo , string $data , string $key [, bool $raw_output = false ] )
Parameters
...
raw_output
When set to TRUE, outputs raw binary data. FALSE outputs lowercase hexits.
所以行:
$signature = utf8_encode(base64_encode(hash_hmac('sha1', $string_to_sign, $secret_key, false)));
它不是生成 base64 编码的 HMAC 哈希值,而是实际生成一个... HMAC 哈希 本身的小写十六进制值的 base64 编码字符串 ...在 UTF-8 中...¯\_(ツ)_/¯
您应该注意到,通过将 hash_mac
的第三个参数从 false
替换为 true
,它实际上会产生与您的 C# 函数相同的值。
$signature = utf8_encode(base64_encode(hash_hmac('sha1', $string_to_sign, $secret_key, true)));
显然,要从您这边 (C#) 修复问题以匹配 API 输出,我们需要在将哈希编码为 base64 之前将其小写十六进制:
public static string CreateSignature(string message, string key)
{
var encoding = new System.Text.UTF8Encoding();
byte[] keyByte = encoding.GetBytes(key);
byte[] messageBytes = encoding.GetBytes(message);
using (var hmacsha1 = new HMACSHA1(keyByte, false))
{
byte[] hashmessage = hmacsha1.ComputeHash(messageBytes);
string hashstring = BitConverter.ToString(hmacsha1.ComputeHash(messageBytes)).Replace("-","").ToLower();
return Convert.ToBase64String(encoding.GetBytes(hashstring));
}
}
我正在开发一个使用 API 的项目,我需要为 Web 服务调用 header 生成签名。 API 文档提供了一些 PHP 示例代码和 "known good" 结果,因此您可以将其转换为您选择的编程语言,我已经 运行 撞墙了,我需要一些帮助。
我以前从未使用过 HMAC,所以这对我来说很陌生,如果能提供任何反馈,我将不胜感激。
基本上 API 提供了一个示例 PHP 脚本及其结果,以便您可以编写您的版本并进行测试。
这是 PHP 示例及其结果。我将 post 我当前的 C# 尝试使用下面的相同代码。再次感谢您提供的任何帮助。
Use the following code example to compare your signature generation with a
known signature. The PHP code example that follows provides a reference to
the generation of a signature for a GET call into the CDRN API. Use your
code with the parameter values listed to validate the same signature is
generated.
<?php
$cdrn_domain = "api.testing.cdrn.com";
$secret_key = "cdrnpassword";
$api_version = "1.1";
$method_type = "GET";
$case_id = "12345";
$string_date = "2014-06-20T12:06:31Z";
$string_to_sign = $method_type . "\n" . $cdrn_domain . "\n" . "/partners/cases/$case_id" . "\n" . "" . "\n" . $api_version . "\n" . $string_date . "\n";
$signature = utf8_encode(base64_encode(hash_hmac('sha1', $string_to_sign, $secret_key, false)));
echo "SIGNATURE[$signature]";
?>
输出: 签名[NWY3N2Q0NTdmZDQxZjA4YWI0Njg3YTEwODljODdiNTEwMTdmMzNlZg==]
这是我需要帮助的 C# 代码:
using System.Security.Cryptography;
string cdrn_domain = "api.testing.cdrn.com";
string secret_key = "cdrnpassword";
string api_version = "1.1";
string method_type = "GET";
string case_id = "12345";
string string_date = "2014-06-20T12:06:31Z";
string string_to_sign = method_type + "\n" + cdrn_domain + "\n" + "/partners/cases/" + case_id + "\n" + "" + "\n" + api_version + "\n" + string_date + "\n";
var result = CreateSignature(string_to_sign, secret_key);
public string CreateSignature(string message, string key)
{
var encoding = new System.Text.UTF8Encoding();
byte[] keyByte = encoding.GetBytes(key);
byte[] messageBytes = encoding.GetBytes(message);
using (var hmacsha1 = new HMACSHA1(keyByte, false))
{
byte[] hashmessage = hmacsha1.ComputeHash(messageBytes);
return Convert.ToBase64String(hashmessage);
}
}
从我的 C# 代码生成的签名是: X3fUV/1B8Iq0aHoQich7UQF/M+8=
这里的问题是因为您(或API)编码了错误的散列值。
来自 hash_hmac
的 PHP 文档:
string hash_hmac ( string $algo , string $data , string $key [, bool $raw_output = false ] )
Parameters
...
raw_output
When set to TRUE, outputs raw binary data. FALSE outputs lowercase hexits.
所以行:
$signature = utf8_encode(base64_encode(hash_hmac('sha1', $string_to_sign, $secret_key, false)));
它不是生成 base64 编码的 HMAC 哈希值,而是实际生成一个... HMAC 哈希 本身的小写十六进制值的 base64 编码字符串 ...在 UTF-8 中...¯\_(ツ)_/¯
您应该注意到,通过将 hash_mac
的第三个参数从 false
替换为 true
,它实际上会产生与您的 C# 函数相同的值。
$signature = utf8_encode(base64_encode(hash_hmac('sha1', $string_to_sign, $secret_key, true)));
显然,要从您这边 (C#) 修复问题以匹配 API 输出,我们需要在将哈希编码为 base64 之前将其小写十六进制:
public static string CreateSignature(string message, string key)
{
var encoding = new System.Text.UTF8Encoding();
byte[] keyByte = encoding.GetBytes(key);
byte[] messageBytes = encoding.GetBytes(message);
using (var hmacsha1 = new HMACSHA1(keyByte, false))
{
byte[] hashmessage = hmacsha1.ComputeHash(messageBytes);
string hashstring = BitConverter.ToString(hmacsha1.ComputeHash(messageBytes)).Replace("-","").ToLower();
return Convert.ToBase64String(encoding.GetBytes(hashstring));
}
}