当前位置: 首页 > 知识库问答 >
问题:

hash_hmac3个参数在PHP,相当于cSharp,javascript

公冶俊达
2023-03-14

说明:

我似乎不明白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));

链接以联机查看输出(需要复制/粘贴)。

正如留档所说,您需要具有适当输出的数据和密钥来创建SHA1 HMAC哈希。

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

我想要的是使用csharp和javascript创建精确的输出。

尝试:

当我有了数据和密钥,并且可以在csharp和javascript上生成相同的SHA1 HMAC哈希时,这就没问题了。

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

链接以联机查看输出(需要复制/粘贴)。

// 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);
    }
}

链接以联机查看输出(需要复制/粘贴)。

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

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

链接以联机查看输出。

问题:

在不使用必需的两个参数的情况下,如何创建描述中所示的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);
    }
}

链接以联机查看输出(需要复制/粘贴)。

// 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'));

链接以联机查看输出。

共有1个答案

蒋培
2023-03-14

这里的关键是PHP将在内部将true转换为字符串。在php中,true强制转换为“1”so

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

完全等同于

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

如果您没有将第4个参数传递给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)查看您实际使用的密钥,您可以随时检查要强制转换的内容。

 类似资料:
  • 问题内容: 我有这个字符串: 0000000020C90037:TEMP:数据 我需要这个字符串: TEMP:数据。 使用PHP,我可以这样做: 如何像在PHP中一样有效地在JavaScript中使用字符串? 问题答案: 这是您的PHP代码的直接转换:

  • 问题内容: 真的很喜欢那个功能。 是否有与之等效的Javascript? 问题答案: 在Javascript的“较新”版本中有:解构分配-Javascript 1.7 。它可能仅在基于Mozilla的浏览器中支持,也许在Rhino中也受支持。 编辑: 实际上,如果V8 Javascript库(以及由此而来的Chrome)支持此功能,这也不会令我感到惊讶。 但也不要指望它 现在所有现代浏览器都支持(

  • 问题内容: 我正在将PHP代码迁移到Google App Engine-Java。 因此,我需要使用Java中的PHP的crypt函数, 因为我已经 使用crypt 将注册用户的所有密码存储在数据库中。 编辑1 :这是我的php密码加密代码: $ password =“ test123”; $ pwd = crypt($ password,$ password); 回声$ pwd; 输出为(在 W

  • 问题内容: PHP中的这一行代码评估为true 我需要的是Golang中的一个crypt函数,该函数也将评估为true。 尝试1 我试过了,但评估为假: 尝试2 我还尝试定义和使用在其他地方找到的这个crypt函数,但它也返回false: 所以我的问题是: 我如何获得一个golang地穴功能完全一样的琴弦的PHP crypt函数和? 问题答案: 尽管我还没有找到与PHP的crypt函数完全相同的“

  • 问题内容: 我正在将应用程序从PHP迁移到Java,并且在代码中大量使用了正则表达式。我遇到了PHP中似乎没有Java等效项的某些问题: 对于正则表达式中的每个匹配项,它都会调用一个函数,该函数将匹配文本作为参数传递给该函数。作为示例用法: 用Java做到这一点的理想方法是什么? 问题答案: 我不知道Java内置有什么类似的东西。您可以使用Matcher类轻松滚动自己的游戏: 然后致电: 请注意,

  • 问题内容: 我在php中将以下语句转换为。 我需要在另一个程序中做同样的事情吗? 有任何想法吗 ? 干杯, 问题答案: 该模块具有,它可以满足您的需求。

  • 问题内容: 我是Java新手,尽管在PHP方面有很好的经验,并且正在寻找Java中爆炸和爆破(PHP中可用)功能的完美替代品。 我已经用Google搜索了相同的结果,但对结果不满意。任何人对我的问题都有好的解决方案将不胜感激。 例如: 所需的输出: 问题答案: 用于String的Javadoc揭示了您正在寻找的东西。 Java不包括等效的“连接”的“内爆”。您可能只想编写几行代码,而不是像其他答案

  • 问题内容: 我正在寻找一个等效于此php调用的Java: 我使用java.crypto.Mac尝试了此操作,但两者不同意: 键=“ secret”和test =“ test”的输出似乎不匹配。 问题答案: 实际上,他们确实同意。 正如Hans Doggen已经指出的那样,除非将raw输出参数设置为true,否则PHP使用十六进制表示法来输出消息摘要。 如果要在Java中使用相同的符号,可以使用类似