2

I need to convert some old C# code to Golang and I stuck somewhere. C# code looks like this `

 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);

so I examined the code line by line and as I understand he used convert the salt and password byte array then he copied these arrays to 'dst' array. Then he used SHA1 algorithm and convert this array to base64string.

My Golang code looks like this but It doesn't create the same string which stores on database.

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

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

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

Can anyone find my fault? Thanks

2
  • 2
    I don't know Golang, but first thing I noticed is that he is using Encoding.Unicode.GetBytes, which means it will produce 2 bytes per character in the bytes and src array, and subsequently dst array. Can you check for your Golang code that it handles this correctly? Commented Mar 7, 2017 at 12:08
  • @icza I don't understand why salt need to be interpreted as a hex string? In database it saved as a string. Commented Mar 7, 2017 at 12:42

1 Answer 1

4

The problem is that the C# code is using the Encoding.Unicode. In Go it should be:

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
}

The convertUTF16ToLittleEndianBytes was taken from another response on SO.

Sign up to request clarification or add additional context in comments.

1 Comment

works like charm! thank you man I've been struggling with this for 2 days

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.