【问题标题】:hash_hmac with 3 params in php, equivalent csharp, javascripthash_hmac 在 php 中具有 3 个参数,等效 csharp,javascript
【发布时间】:2017-08-11 19:23:24
【问题描述】:

描述:

似乎我无法弄清楚 PHP 是如何产生以下内容的:

echo hash_hmac("sha1", "what is this", true);
echo PHP_EOL; // end of line
echo base64_encode(hash_hmac("sha1", "what is this", true));

在线查看output的链接(需要复制/粘贴)。

如文档所述,您需要 datakey 以及适当的 output 来创建 SHA1 HMAC 哈希。

string hash_hmac(string $algo, string $data, string $key [, bool $raw_output = false])

我想要的是用 csharpjavascript 创建精确的输出。


尝试过:

当我有 datakey 并且我可以在 csharp 和 javascript 上生成相同的 SHA1 HMAC 哈希时很好。

// PHP
echo base64_encode(hash_hmac("sha1", "data", "key", true));

在线查看output的链接(需要复制/粘贴)。

// CSharp
public static void Main(string[] args)
{
    Console.WriteLine(CreatePhpSha1HmacHash("data", "key"));
}

public static string CreatePhpSha1HmacHash(string data, string key)
{
    if (data == null)
    {
        data = string.Empty;
    }

    var encoding = new System.Text.UTF8Encoding(); // It's UTF-8 for my example

    var keyBytes = encoding.GetBytes(key);
    var dataBytes = encoding.GetBytes(data);

    using (var hmac = new System.Security.Cryptography.HMACSHA1(keyBytes))
    {
        var hash = hmac.ComputeHash(dataBytes);

        return Convert.ToBase64String(hash);
    }
}

在线查看output的链接(需要复制/粘贴)。

// Javascript
var hash = CryptoJS.HmacSHA1('data', 'key');
var base64 = CryptoJS.enc.Base64.stringify(hash);

console.log('Sha1 hmac hash: ' + base64);

在线查看output的链接。


问题

当不使用必需的两个参数时,如何创建准确的输出,如描述中所示的 php 示例?有人可以向我解释一下 php 在这种情况下在做什么吗?


回答

@GentlemanMax:PHP 将在内部将 TRUE 转换为 STRING,因此 KEY 将转换为 "1" 作为字符串值。当 raw_output 设置为 TRUE 时,它输出原始二进制数据。 FALSE 输出小写十六进制。


解决方案

// CSharp
public static void Main(string[] args)
{
    // echo base64_encode(hash_hmac("sha1", "what is this", true));
    // echo base64_encode(hash_hmac("sha1", "what is this", true, false));
    Console.WriteLine(ToBase64EncodedHmacSha1("what is this", "1", false));
    Console.WriteLine(ToBase64EncodedHmacSha1("what is this", "1", false.ToString()));

    // echo base64_encode(hash_hmac("sha1", "what is this", true, true));
    Console.WriteLine(ToBase64EncodedHmacSha1("what is this", "1", true));
    Console.WriteLine(ToBase64EncodedHmacSha1("what is this", "1", true.ToString()));
}

public static string ToBase64EncodedHmacSha1(string data, string key, bool rawOutput = false)
{
    bool result;

    if (bool.TryParse(key, out result))
    {
        key = result ? 1.ToString() : 0.ToString();
    }

    var keyBytes = Encoding.UTF8.GetBytes(key);
    var dataBytes = Encoding.UTF8.GetBytes(data);

    using (var hmac = new HMACSHA1(keyBytes))
    {
        var hash = hmac.ComputeHash(dataBytes);

        if (rawOutput)
        {
            // output: raw binary
            return Convert.ToBase64String(hash);
        }

        // Convert an array of bytes to a string of hex digits.
        var hex = string.Concat(hash.Select(x => x.ToString("x2").ToLower()));

        var hexBytes = Encoding.UTF8.GetBytes(hex);

        // output: lowercase hexits
        return Convert.ToBase64String(hexBytes);
    }
}

在线查看output的链接(需要复制/粘贴)。


// Javascript 
function toBase64EncodedHmacSha1(data, key, rawOutput) {
    // if boolean, cast to string
    if (typeof(key) === 'boolean') {
        key = key ? '1' : '0';
    }

    // optional
    if (typeof(rawOutput) === 'undefined') {
        rawOutput = false;
    }

    // check type
    if (typeof(rawOutput) !== 'boolean') {
        throw new Error('Raw output is Boolean value: true/false');
    }

    var hash = CryptoJS.HmacSHA1(data, key);

    if (rawOutput) {
        // output: raw binary
        return CryptoJS.enc.Base64.stringify(hash);
    }

    var hex = CryptoJS.enc.Hex.stringify(hash);
    var wordArray = CryptoJS.enc.Utf8.parse(hex);

    // output: lowercase hexits
    return CryptoJS.enc.Base64.stringify(wordArray);
}

// echo base64_encode(hash_hmac("sha1", "what is this", true));
// echo base64_encode(hash_hmac("sha1", "what is this", true, false));
console.log(toBase64EncodedHmacSha1('what is this', true));
console.log(toBase64EncodedHmacSha1('what is this', true, false));

// echo base64_encode(hash_hmac("sha1", "what is this", true, true));
console.log(toBase64EncodedHmacSha1('what is this', true, true));

console.log(toBase64EncodedHmacSha1('what is this', true, 'This will throw error'));

在线查看output的链接。

【问题讨论】:

    标签: javascript c# php hmacsha1


    【解决方案1】:

    这里的关键点是 PHP 将在内部将 true 转换为字符串。在 php 中,true 转换为 "1" 所以

    hash_hmac("sha1", "data", true);
    

    完全等价于

    hash_hmac("sha1", "data", "1")
    

    如果您没有将第四个参数传递给hash_hmac,那么它将以十六进制输出哈希。这不是您在 c# 或 javascript 中所做的。以下是一些等价物供您使用:

    //PHP
    hash_hmac("sha1", "data", true)
    

    将输出相同的

    //JS
    var hash = CryptoJS.HmacSHA1('data', "1")
    console.log ( CryptoJS.enc.Hex.stringify(hash) ); //Note .Hex instead of .Base64
    

    同样,

    //PHP
    base64_encode(hash_hmac("sha1", "data", true, true));
    

    和做的一样

    //JS
    var hash = CryptoJS.HmacSHA1('data', "1")
    console.log ( CryptoJS.enc.Base64.stringify(hash) );
    

    顺便说一句,PHP 将尝试将 $key 的所有非字符串值转换为字符串。您可以随时通过调用 strval($key) 来查看您实际使用的密钥是什么。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-25
      • 2014-12-04
      • 2014-08-02
      • 1970-01-01
      相关资源
      最近更新 更多