Golang编码字符串UTF16 little endian和hash with MD5

时间:2015-11-14 16:33:32

标签: hash go md5

我是一名Go初学者并且遇到了问题。 我想用UTF16小端编码一个字符串,然后用MD5(十六进制)散列它。我找到了一段Python代码,它完全符合我的要求。但我无法将其转移到Google Go。

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

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

3 个答案:

答案 0 :(得分:6)

您可以使用golang.org/x/text/encodinggolang.org/x/text/transform创建一个编写链,在没有太多手动字节切片的情况下进行编码和散列,从而减少工作量(或至少更易理解,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)
}

答案 1 :(得分:3)

您可以使用unicode/utf16包进行UTF-16编码。 utf16.Encode()返回Unicode代码点序列的UTF-16编码(符文切片:[]rune)。您只需将string转换为一片符文,例如: []rune("some string"),您可以通过uint16代码的范围轻松生成小端编码的字节序列,然后首先发送/附加低字节,然后将高字节发送到输出(这就是Little Endian意味着)。

对于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 :(得分:1)

因此,作为参考,我使用了这个完整的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
}