在PHP中,我們經常需要使用加密演算法來保護資料的安全性。 HMAC(Hash-based Message Authentication Code)是一種常用的加密演算法,用於驗證資料完整性和身份認證。在PHP中,我們可以使用hmac.New()函數來建立HMAC實例,該函數需要指定一個雜湊函數和一個金鑰。與此類似,在JavaScript中,我們可以使用等效的方法來實現相同的功能。在本文中,我將為您介紹如何在JavaScript中使用等效的方法來建立HMAC實例,以及如何在PHP和JavaScript之間進行資料的加密和解密。
差點在go lang hmac.new的js實作中卡住好幾天了。然而,沒有成功。我使用 crypto
、crypto-js
和 stablelib
模組進行實作。問題是,在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
。
當 go 版本的輸出與您的實作的輸出相同時;您的解決方案是正確的。
根據規格 (rfc 2104),hmac 使用摘要函數內部,例如sha256。
但是,您的實作應用了(實際上不相容)內部使用另一個 hmac 而不是摘要的 hmac,其中只有最低等級的 hmac 在內部使用常規摘要。這樣就創建了一個嵌套結構。
基於常規 hmac(帶有摘要)的規範,這可以擴展到 go 程式碼中使用的帶有 hmac(而不是摘要)的 hmac:
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 }
編輯:
受這篇文章的啟發,以下是hmac_rec()
的更緊湊/高效的實現,它使用常規最後一個迭代步驟的hmac(這也使得gethash()
過時):
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 }
以上是hmac.New(h func() hash.Hash, key byte) hash.Hash 在 JavaScript 中等效的詳細內容。更多資訊請關注PHP中文網其他相關文章!