0

0

hmac.New(h func() hash.Hash, key byte) hash.Hash 在 JavaScript 中等效

WBOY

WBOY

发布时间:2024-02-09 08:12:18

|

657人浏览过

|

来源于stackoverflow

转载

hmac.new(h func() hash.hash, key byte) hash.hash 在 javascript 中等效

在PHP中,我们经常需要使用加密算法来保护数据的安全性。HMAC(Hash-based Message Authentication Code)是一种常用的加密算法,用于验证数据完整性和身份认证。在PHP中,我们可以使用hmac.New()函数来创建HMAC实例,该函数需要指定一个哈希函数和一个密钥。与此类似,在JavaScript中,我们可以使用等效的方法来实现相同的功能。在本文中,我将为您介绍如何在JavaScript中使用等效的方法来创建HMAC实例,以及如何在PHP和JavaScript之间进行数据的加密和解密。

问题内容

差点在go lang hmac.new的js实现中卡住好几天了。然而,没有成功。我使用 cryptocrypto-jsstablelib 模块进行实现。问题是,在go lang版本中,hmac实例可以通过hmac实例创建。例如(代码块正确且经过测试):

hmacf := hmac.New(func() hash.Hash {
    return hmac.New(func() hash.Hash {
        return hmac.New(func() hash.Hash {
            return hmac.New(sha256.New, []byte(SALT))
        }, []byte(path[0]))
    }, []byte(path[1]))
}, []byte(path[2]))

其实我也不知道它是怎么工作的!因为在所有与 javascript 相关的模块中,您无法从 hmac 创建 hmac,并且它们接受确定哈希算法的 string 值。

也许最好问一下如何在javascript中从hmac创建hmac

立即学习Java免费学习笔记(深入)”;

解决方案是什么?

当 go 版本的输出与你的实现的输出相同时;您的解决方案是正确的。

解决方法

根据规范 (rfc 2104),hmac 使用摘要函数内部,例如sha256。

但是,您的实现应用了(实际上不兼容)内部使用另一个 hmac 而不是摘要的 hmac,其中只有最低级别的 hmac 在内部使用常规摘要。这样就创建了一个嵌套结构。

基于常规 hmac(带有摘要)的规范,这可以扩展到 go 代码中使用的带有 hmac(而不是摘要)的 hmac:

360智图
360智图

AI驱动的图片版权查询平台

下载

hmac(k xor opad, hmac(k xor ipad, text)) s。 rfc2104,第 2 节。hmac 的定义

由于与规范的差异,找到一个开箱即用的支持此类功能的 javascript 库可能不会那么容易。
虽然大多数库当然支持 hmac,但只允许指定摘要(而不是 hmac),例如nodejs的crypto模块的crypto.createhmac(),参见还有其他答案。我认为这种方法不能用于实现 go 代码中的逻辑。

如果其他答案的方法不起作用,并且您找不到另一个具有所需功能的 javascript 库,您可以自己在 javascript 中实现逻辑,因为 hmac 的规范相对简单(见上文) )。

以下代码是 nodejs 的 crypto 模块的示例实现:

var crypto = require('crypto')

const digest = 'sha256'
const blocksize = 64 // block size of the digest

// define input parameter
var salt = buffer.from('salt')
var path = [ buffer.from('alfa'), buffer.from('beta'), buffer.from('gamma') ]
var data = buffer.from('data')

// calculate hmac
var hmac = hmac(data, salt, path)
console.log(hmac.tostring('hex'))

function hmac(data, salt, path) {
    
    // create keylist
    var keylist = []
    keylist.push(salt)
    keylist = keylist.concat(path)

    // determine hmac recursively
    var result = hmac_rec(data, keylist)
    return result
}

function hmac_rec(data, keylist) {

    // adjust key (according to hmac specification)
    var key = keylist.pop()
    if (key.length > blocksize) {        
        k = buffer.allocunsafe(blocksize).fill('\x00');
        if (keylist.length > 0) {
            hmac_rec(key, [...keylist]).copy(k)
        } else {
            gethash(key).copy(k)
        }
    } else if (key.length < blocksize) {
        k = buffer.allocunsafe(blocksize).fill('\x00');
        key.copy(k)
    } else {
        k = key
    }

    // create 'key xor ipad' and 'key xor opad' (according to hmac specification)  
    var ik = buffer.allocunsafe(blocksize)
    var ok = buffer.allocunsafe(blocksize)
    k.copy(ik)
    k.copy(ok)
    for (var i = 0; i < ik.length; i++) {
        ik[i] = 0x36 ^ ik[i] 
        ok[i] = 0x5c ^ ok[i]
    }

    // calculate hmac
    if (keylist.length > 0) {
        var innerhmac = hmac_rec(buffer.concat([ ik, data ]), [...keylist]) 
        var outerhmac = hmac_rec(buffer.concat([ ok, innerhmac ]), [...keylist])
    } else {
        var innerhmac = gethash(buffer.concat([ik, data]))
        var outerhmac = gethash(buffer.concat([ok, innerhmac]))
    }
  
    return outerhmac 
}

// calculate sha256 hash
function gethash(data){
    var hash = crypto.createhash(digest);
    hash.update(data)
    return hash.digest()
}

结果:

2e631dcb4289f8256861a833ed985fa945cd714ebe7c3bd4ed4b4072b107b073

测试:

以下 go 代码产生相同的结果:

package main

import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
    "fmt"
    "hash"
)

func main() {
    salt := "salt"
    path := []string{"alfa", "beta", "gamma"}
    hmacf := hmac.new(func() hash.hash {
        return hmac.new(func() hash.hash {
            return hmac.new(func() hash.hash {
                return hmac.new(sha256.new, []byte(salt))
            }, []byte(path[0]))
        }, []byte(path[1]))
    }, []byte(path[2]))
    hmacf.write([]byte("data"))
    result := hmacf.sum(nil)
    fmt.println(hex.encodetostring(result)) // 2e631dcb4289f8256861a833ed985fa945cd714ebe7c3bd4ed4b4072b107b073
}

编辑:

这篇文章的启发,以下是 crypto.createhmac() 的更紧凑/高效的实现,它使用常规最后一个迭代步骤的 hmac(这也使得 hmac_rec() 过时):

function hmac_rec(data, keyList) {
    var key = keyList.pop()
    if (keyList.length > 0) {
        
        // adjust key (according to HMAC specification)
        if (key.length > blockSize) {        
            k = Buffer.allocUnsafe(blockSize).fill('\x00');
            hmac_rec(key, [...keyList]).copy(k)
        } else if (key.length < blockSize) {
            k = Buffer.allocUnsafe(blockSize).fill('\x00');
            key.copy(k)
        } else {
            k = key
        }
    
        // create 'key xor ipad' and 'key xor opad' (according to HMAC specification)  
        var ik = Buffer.allocUnsafe(blockSize)
        var ok = Buffer.allocUnsafe(blockSize)
        k.copy(ik)
        k.copy(ok)
        for (var i = 0; i < ik.length; i++) {
            ik[i] = 0x36 ^ ik[i] 
            ok[i] = 0x5c ^ ok[i]
        }

        // calculate HMAC
        var innerHMac = hmac_rec(Buffer.concat([ ik, data ]), [...keyList]) 
        var outerHMac = hmac_rec(Buffer.concat([ ok, innerHMac ]), [...keyList])
    } else {
        var outerHMac = crypto.createHmac(digest, key).update(data).digest();
    }  
    return outerHMac 
}

相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

463

2023.08.02

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

514

2023.06.20

js获取当前时间
js获取当前时间

JS全称JavaScript,是一种具有函数优先的轻量级,解释型或即时编译型的编程语言;它是一种属于网络的高级脚本语言,主要用于Web,常用来为网页添加各式各样的动态功能。js怎么获取当前时间呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

244

2023.07.28

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

298

2023.08.03

js是什么意思
js是什么意思

JS是JavaScript的缩写,它是一种广泛应用于网页开发的脚本语言。JavaScript是一种解释性的、基于对象和事件驱动的编程语言,通常用于为网页增加交互性和动态性。它可以在网页上实现复杂的功能和效果,如表单验证、页面元素操作、动画效果、数据交互等。

5306

2023.08.17

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

481

2023.09.01

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

212

2023.09.04

Js中concat和push的区别
Js中concat和push的区别

Js中concat和push的区别:1、concat用于将两个或多个数组合并成一个新数组,并返回这个新数组,而push用于向数组的末尾添加一个或多个元素,并返回修改后的数组的新长度;2、concat不会修改原始数组,是创建新的数组,而push会修改原数组,将新元素添加到原数组的末尾等等。本专题为大家提供concat和push相关的文章、下载、课程内容,供大家免费下载体验。

218

2023.09.14

clawdbot ai使用教程 保姆级clawdbot部署安装手册
clawdbot ai使用教程 保姆级clawdbot部署安装手册

Clawdbot是一个“有灵魂”的AI助手,可以帮用户清空收件箱、发送电子邮件、管理日历、办理航班值机等等,并且可以接入用户常用的任何聊天APP,所有的操作均可通过WhatsApp、Telegram等平台完成,用户只需通过对话,就能操控设备自动执行各类任务。

2

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号