2017-03-07 68 views
2

我需要將一些舊的C#代碼Golang和我堅持的地方。 C#代碼看起來是這樣的 '轉換C#SHA1代碼Golang

byte[] bytes = Encoding.Unicode.GetBytes(password); 
byte[] src = Encoding.Unicode.GetBytes(salt); 
byte[] dst = new byte[src.Length + bytes.Length]; 
Buffer.BlockCopy(src, 0, dst, 0, src.Length); 
Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length); 
HashAlgorithm algorithm = HashAlgorithm.Create("SHA1"); 
byte[] inArray = algorithm.ComputeHash(dst); 
return Convert.ToBase64String(inArray); 

所以通過線檢查的代碼行,並作爲我明白他使用轉換的鹽和密碼字節數組然後他複製這些陣列爲「DST」數組。然後,他使用SHA1算法和這個數組轉換爲base64string。

我Golang代碼看起來是這樣,但它不會產生存儲數據庫相同的字符串。

s := "fish123" 
salt := "227EA7ABD26E40608A6EDEB209058D93A632D1D1A52246D0A27F6E447B16AEBF" 

h1 := sha1.New() 
h1.Write([]byte(salt)) 
h1.Write([]byte(s)) 

hashedPassword := base64.StdEncoding.EncodeToString(h1.Sum(nil)) 

任何人都可以找到我的錯嗎?由於

+2

我不知道Golang,但我注意到的第一件事是,他使用'Encoding.Unicode.GetBytes',這意味着它會產生每個字符2個字節的'bytes'和'src'陣列,並隨後'dst'數組。你能檢查你的Golang代碼,它是否正確處理? – Paya

+0

@icza我不明白爲什麼鹽需要被解釋爲一個十六進制字符串?在數據庫中它保存爲一個字符串。 –

回答

4

的問題是,C#代碼是使用Encoding.Unicode。在圍棋應該是:

package main 

import (
    "crypto/sha1" 
    "encoding/base64" 
    "encoding/binary" 
    "fmt" 
    "unicode/utf16" 
) 

func main() { 
    s := "fish123" 
    salt := "227EA7ABD26E40608A6EDEB209058D93A632D1D1A52246D0A27F6E447B16AEBF" 

    h1 := sha1.New() 
    h1.Write(convertUTF16ToLittleEndianBytes(salt)) 
    h1.Write(convertUTF16ToLittleEndianBytes(s)) 

    b64 := base64.StdEncoding.EncodeToString(h1.Sum(nil)) 
    fmt.Println(b64) 
} 

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

convertUTF16ToLittleEndianBytes是從SO另一個響應服用。

+0

作品般的魅力!謝謝你,我一直在爲此掙扎2天 –