使用Golang编码字符串为UTF16小端,并使用MD5进行哈希

6

我是一个Go语言初学者,目前遇到了麻烦。 我想要将一个字符串使用UTF16小端编码,然后使用MD5(十六进制)进行哈希。我已经找到了一段Python代码,可以完美地实现我的需求。但我无法将其转换为Google Go。

md5 = hashlib.md5()
md5.update(challenge.encode('utf-16le'))
response = md5.hexdigest()

挑战是一个包含字符串的变量。
3个回答

9
你可以通过使用 golang.org/x/text/encodinggolang.org/x/text/transform 创建一个 Writer 链,以更少的工作量(或者至少更易于理解)来完成编码和散列处理,而无需进行复杂的字节切片处理。等效函数为:
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)
}

5
您可以使用 unicode/utf16 包进行 UTF-16 编码。 utf16.Encode() 返回 Unicode 代码点序列(符文切片:[]rune)的 UTF-16 编码。您只需将 string 转换为符文切片,例如 []rune("some string"),并通过遍历 uint16 代码并首先发送/附加低位字节然后是高位字节以输出轻松生成小端编码的字节序列(这就是 Little Endian 的含义)。
对于小端编码,您还可以使用 encoding/binary 包:它具有导出的 LittleEndian 变量和一个 PutUint16() 方法。
至于 MD5 校验和,crypto/md5 包具有您想要的功能,md5.Sum() 简单地返回传递给它的字节切片的 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

Go Playground上试试。

使用encoding/binary的变体如下所示:

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

(虽然这样做速度较慢,因为它会创建大量新的切片头。)

2

因此,供参考,我使用了这个完整的Python程序:

import hashlib
import codecs

md5 = hashlib.md5()
md5.update(codecs.encode('Hello, playground', 'utf-16le'))
response = md5.hexdigest()
print response

它会打印出 8f4a54c6ac7b88936e990256cc9d335b

这里是 Go 语言的等效代码:https://play.golang.org/p/Nbzz1dCSGI

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
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接