Hash Golang用MD5编码字符串UTF16小端和散列

Hash Golang用MD5编码字符串UTF16小端和散列,hash,go,md5,Hash,Go,Md5,我是一个新手,遇到了一个难题。 我想用UTF16小尾端编码一个字符串,然后用MD5(十六进制)散列它。我发现了一段Python代码,它正是我想要的。但我无法将其转移到Google Go md5 = hashlib.md5() md5.update(challenge.encode('utf-16le')) response = md5.hexdigest() 挑战是一个包含字符串的变量。您可以使用该包进行UTF-16编码。返回Unicode代码点序列的UTF-16编码(符文片段:[]符文)。您

我是一个新手,遇到了一个难题。 我想用UTF16小尾端编码一个字符串,然后用MD5(十六进制)散列它。我发现了一段Python代码,它正是我想要的。但我无法将其转移到Google Go

md5 = hashlib.md5()
md5.update(challenge.encode('utf-16le'))
response = md5.hexdigest()
挑战是一个包含字符串的变量。

您可以使用该包进行UTF-16编码。返回Unicode代码点序列的UTF-16编码(符文片段:
[]符文
)。您可以简单地将
字符串
转换为一段符文,例如
[]符文(“某些字符串”)
,通过在
uint16
代码上进行排列,并首先将低位字节发送/追加到输出中,然后将高位字节发送/追加到输出中,您就可以轻松地生成小端字节编码的字节序列(这就是小端字节的意思)

对于Little-Endian编码,您也可以使用这个包:它有一个导出的
LittleEndian
变量和一个
PutUint16()
方法

至于MD5校验和,包有您想要的,只返回传递给它的字节片的MD5校验和

这里有一个小函数,可以捕获您想要执行的操作:

func utf16leMd5(s string) [16]byte {
    codes := utf16.Encode([]rune(s))
    b := make([]byte, len(codes)*2)
    for i, r := range codes {
        b[i*2] = byte(r)
        b[i*2+1] = byte(r >> 8)
    }
    return md5.Sum(b)
}
使用它:

s := "Hello, playground"
fmt.Printf("%x\n", utf16leMd5(s))

s = "エヌガミ"
fmt.Printf("%x\n", utf16leMd5(s))
输出:

8f4a54c6ac7b88936e990256cc9d335b
5f0db9e9859fd27f750eb1a212ad6212
试穿一下

使用
编码/二进制
的变体如下所示:

for i, r := range codes {
    binary.LittleEndian.PutUint16(b[i*2:], r)
}

(虽然这会因为创建了大量新的切片头而变慢。)

您可以通过使用和创建一个编写器链来完成这项工作,而无需太多的手动字节切片处理,只需更少的工作(或者至少更容易理解,IMO)。等效功能:

func utf16leMd5(s string) []byte {
    enc := unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM).NewEncoder()
    hasher := md5.New()
    t := transform.NewWriter(hasher, enc)
    t.Write([]byte(s))
    return hasher.Sum(nil)
}

因此,作为参考,我使用了这个完整的python程序:

导入hashlib
导入编解码器
md5=hashlib.md5()
md5.update(codecs.encode('Hello,playerly','utf-16le'))
response=md5.hexdigest()
打印响应
它打印
8f4a54c6ac7b88936e990256cc9d335b

这是围棋的等价物:

package main

import (
    "crypto/md5"
    "encoding/binary"
    "encoding/hex"
    "fmt"
    "unicode/utf16"
)

func main() {
    s := "Hello, playground"

    fmt.Println(md5Utf16le(s))
}

func md5Utf16le(s string) string {
    encoded := utf16.Encode([]rune(s))

    b := convertUTF16ToLittleEndianBytes(encoded)

    return md5Hexadecimal(b)
}

func md5Hexadecimal(b []byte) string {
    h := md5.New()
    h.Write(b)
    return hex.EncodeToString(h.Sum(nil))
}

func convertUTF16ToLittleEndianBytes(u []uint16) []byte {
    b := make([]byte, 2*len(u))
    for index, value := range u {
        binary.LittleEndian.PutUint16(b[index*2:], value)
    }
    return b
}