当前位置: 动力学知识库 > 问答 > 编程问答 >

cryptography - Why does Go generate hmac hashes different than PHP and JavaScript?

问题描述:

I'm starting to code in Go and I tried to do an simple request validation, by checking the signature sent by the client. At the first look everything was fine, but after a few tests validating real requests I found that Go is generating an awkward hash.

To prove the inconsistency between the Go backend and the JavaScript signature, I developed an PHP version of the same sign method, and it gave me identical results of the JavaScript version, so my expectation was right.

I've developed one sample test to each language: Go, PHP and JavaScript.

So, to achieve the same results of PHP and JavaScript in Go, what should I do?


Go

package main

import (

"crypto/hmac"

"crypto/sha256"

"encoding/base64"

"fmt"

)

func main() {

data := "My name is Danniel"

mac := hmac.New(sha256.New, []byte("secret"))

mac.Write([]byte(data))

macSum := mac.Sum(nil)

data64 := base64.StdEncoding.EncodeToString(macSum)

fmt.Println(fmt.Sprintf("mac: %s | b64: %s", macSum, data64))

data64 = base64.StdEncoding.EncodeToString([]byte("My name is Danniel"))

fmt.Println(fmt.Sprintf("b64: %s", data64))

}

Output

mac: 6��q��0��5й��|��G�#0��ih | b64: NqzRcf/FMLPvo678NdC58JB8lgOFR+wjMNQDDwSkaWg=

b64: TXkgbmFtZSBpcyBEYW5uaWVs


PHP

$data = 'My name is Danniel';

$macSum = hash_hmac('sha256', $data, 'secret');

$data64 = base64_encode($macSum);

echo sprintf('mac: %s | b64: %s', $macSum, $data64) . "\n";

$data64 = base64_encode('My name is Danniel');

echo sprintf('b64: %s', $data64) . "\n";

Output

mac: 36acd171ffc530b3efa3aefc35d0b9f0907c96038547ec2330d4030f04a46968 | b64: MzZhY2QxNzFmZmM1MzBiM2VmYTNhZWZjMzVkMGI5ZjA5MDdjOTYwMzg1NDdlYzIzMzBkNDAzMGYwNGE0Njk2OA==

b64: TXkgbmFtZSBpcyBEYW5uaWVs


JavaScript

var data = 'My name is Danniel';

var mac = CryptoJS.HmacSHA256(data, 'secret');

var macSum = mac.toString();

var data64 = btoa(macSum)

console.log('mac: ' + macSum + ' | b64: ' + data64);

var data64 = btoa('My name is Danniel')

console.log('b64: ' + data64);

Output

"mac: 36acd171ffc530b3efa3aefc35d0b9f0907c96038547ec2330d4030f04a46968 | b64: MzZhY2QxNzFmZmM1MzBiM2VmYTNhZWZjMzVkMGI5ZjA5MDdjOTYwMzg1NDdlYzIzMzBkNDAzMGYwNGE0Njk2OA=="

"b64: TXkgbmFtZSBpcyBEYW5uaWVs"

网友答案:

The problem is that both your PHP and JavaScript codes do this: Base64(Hex(Hmac(key, msg))). You really don't need the double encoding.

In PHP you can simply request raw_encoding instead of hex:

$macSum = hash_hmac('sha256', $data, 'secret', true);

and in CryptoJS, you have to encode directly to Base64 instead of encoding to hex and then using btoa() with:

var data64 = mac.toString(CryptoJS.enc.Base64);

For that, you will need to include the enc-base64.js component.

var data = 'My name is Danniel';
  
var mac = CryptoJS.HmacSHA256(data, 'secret');
var macSum = mac.toString();
var data64 = mac.toString(CryptoJS.enc.Base64)
document.write('mac: ' + macSum + ' | b64: ' + data64);

var data64 = btoa('My name is Danniel')
document.write('<br>b64: ' + data64);
<script src="https://raw.githubusercontent.com/CryptoStore/crypto-js/3.1.2/build/rollups/hmac-sha256.js"></script>
  <script src="https://raw.githubusercontent.com/CryptoStore/crypto-js/3.1.2/build/components/enc-base64.js"></script>
网友答案:

Your PHP function works differently than the Go function.

From the PHP documentation:

Returns a string containing the calculated message digest as lowercase hexits unless raw_output is set to true in which case the raw binary representation of the message digest is returned. Returns FALSE when algo is unknown.

So in this case, Go is encoding the raw bytes returned from the HMAC sum. In PHP (and I assume JS), you are b64 encoding a hex string returned from the hmac.

To achieve the same results in go, encode the []byte in hex, then base64 encode it.

Generally, however, it is best practice to operate on bytes, not an encoding of bytes. If you have to conform to a previous design, go ahead, but otherwise you should be using the raw_output option allowed in the PHP function and you should end up with the same results.

分享给朋友:
您可能感兴趣的文章:
随机阅读: