Rumah  >  Artikel  >  pembangunan bahagian belakang  >  hmac.New(h func() hash.Hash, key byte) hash.Hash setara dalam JavaScript

hmac.New(h func() hash.Hash, key byte) hash.Hash setara dalam JavaScript

WBOY
WBOYke hadapan
2024-02-09 08:12:18462semak imbas

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

Dalam PHP, kita selalunya perlu menggunakan algoritma penyulitan untuk melindungi keselamatan data. HMAC (Kod Pengesahan Mesej berasaskan Hash) ialah algoritma penyulitan yang biasa digunakan untuk mengesahkan integriti data dan pengesahan identiti. Dalam PHP, kita boleh mencipta contoh HMAC menggunakan fungsi hmac.New(), yang memerlukan penetapan fungsi cincang dan kunci. Begitu juga, dalam JavaScript, kita boleh menggunakan kaedah yang setara untuk mencapai fungsi yang sama. Dalam artikel ini, saya akan menunjukkan kepada anda cara membuat contoh HMAC menggunakan kaedah yang setara dalam JavaScript, serta cara menyulitkan dan menyahsulit data antara PHP dan JavaScript.

Kandungan soalan

Saya hampir terperangkap dalam pelaksanaan js go lang hmac.new selama beberapa hari. Namun, tiada kejayaan. Saya menggunakan cryptocrypto-jsstablelib 模块进行实现。问题是,在go lang版本中,hmac实例可以通过hmac penciptaan contoh. Contohnya (blok kod betul dan diuji):

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]))

Sebenarnya, saya juga tidak tahu bagaimana ia berfungsi! Kerana dalam semua modul berkaitan javascript anda tidak boleh mendapatkan nilai daripada hmac 创建 hmac,并且它们接受确定哈希算法的 string .

Mungkin lebih baik untuk bertanya bagaimana untuk mendapatkan dari hmac创建hmac dalam javascript.

Apakah penyelesaiannya?

Apabila output versi go adalah sama dengan output pelaksanaan anda;

Penyelesaian

Mengikut spesifikasi (rfc 2104), hmac menggunakan fungsi digest secara dalaman, seperti sha256.

Walau bagaimanapun, pelaksanaan anda terpakai (sebenarnya tidak serasi dengan) hmac yang menggunakan hmac lain secara dalaman dan bukannya digest, di mana hanya hmac tahap terendah menggunakan digest biasa secara dalaman. Ini mewujudkan struktur bersarang.

Berdasarkan spesifikasi hmac biasa (dengan digest), ini boleh dilanjutkan kepada hmac dengan hmac (bukannya digest) yang digunakan dalam kod go:

hmac(k xor opad, hmac(k xor ipad, text))s. rfc2104, Bahagian 2. Definisi hmac

Disebabkan perbezaan daripada spesifikasi, mungkin tidak semudah itu untuk mencari perpustakaan javascript yang menyokong fungsi sedemikian di luar kotak.
Walaupun kebanyakan perpustakaan pasti menyokong hmac, hanya membenarkan ringkasan ditentukan (bukan hmac), seperti modul kripto nodejs crypto.createhmac(), lihat juga jawapan lain. Saya tidak fikir pendekatan ini boleh digunakan untuk melaksanakan logik dalam kod go.

Jika pendekatan jawapan yang lain tidak berfungsi dan anda tidak dapat mencari perpustakaan javascript lain dengan fungsi yang anda inginkan, anda boleh melaksanakan logik dalam javascript sendiri, kerana spesifikasi hmac agak mudah (lihat di atas).

Kod berikut ialah contoh pelaksanaan modul crypto nodejs:

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()
}

Hasil:

2e631dcb4289f8256861a833ed985fa945cd714ebe7c3bd4ed4b4072b107b073

Ujian:

Kod go berikut menghasilkan hasil yang sama:

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
}

Editor:

Diinspirasikan oleh artikel ini, berikut adalah hmac_rec() 的更紧凑/高效的实现,它使用常规最后一个迭代步骤的 hmac(这也使得 gethash() sudah lapuk):

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 
}

Atas ialah kandungan terperinci hmac.New(h func() hash.Hash, key byte) hash.Hash setara dalam JavaScript. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam