How does “go get” get to know what version control system to use with remote repos?

How does “go get” get to know what version control system to use with remote repos?

I am new to golang. I learned that go get serves as a package manager and contact remote repos with various version control systems. 
So, given a package import path, how does go get decide which VCS to use?  I always see below query string in the reqeust:
?go-get=1

So seems some protocol/convention here?

Solutions/Answers:

Answer 1:

One of the nice things about Go is that everything is in, well, Go 🙂 Including almost all of the standard library and tools.

In cmd/go/vcs.go we can see how this is done, and in cmd/go/alldocs.go it is documented.

Specifically, look at repoRootForImportPath:

// repoRootForImportPath analyzes importPath to determine the
// version control system, and code repository to use.
func repoRootForImportPath(importPath string, security securityMode) (*repoRoot, error) {

What this does is:

  1. vcsPaths holds a static lists of “known hosts”. For some (e.g. GitHub) this is easy and we can just set the VCS. For others (e.g. BitBucket) a callback function is used which examines the URL to see which repo can be used.

  2. If that fails, it tries to look at a “VCS extension” in the path, such as example.com/foo.git or example.com/foo.git/dir.

  3. And finally go get will look for a go-import meta tag, which looks like:

    <meta name="go-import" content="example.com/path git https://github.com/Example/repo.git">
    

    Also see parseMetaGoImports(). Vanity Imports with Hugo is a nice introduction on how to use this.

There is no real “auto-detection” mechanism. So if you repo lives at https://example.com/stuff then go get example.com/stuff will not work. You need the extension or meta tags.

The go-get=1 parameter is added so that it’s easy for website builders to see that this is a request from go get, which may be useful in some cases.

References

Rfc2898DeriveBytes vs golang pbkdf2

Rfc2898DeriveBytes vs golang pbkdf2

Here is my C# Rfc2898DeriveBytes 
using System;
using System.Text;
using System.Security.Cryptography;

public class Program
{
    public static void Main()
    {
        byte[] saltBytes = Encoding.Unicode.GetBytes("47687");
        Console.WriteLine(Convert.ToBase64String(saltBytes));

        byte[] passBytes = Encoding.Unicode.GetBytes("123456");
        Console.WriteLine(Convert.ToBase64String(passBytes));

        Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(passBytes, saltBytes, 1000);
        byte[] hashbyte = k1.GetBytes(32);

        Console.WriteLine(Convert.ToBase64String(hashbyte));
    }
}

Result is 
NAA3ADYAOAA3AA==
MQAyADMANAA1ADYA
aOyDnGG22ebqGmMvY7zQwdT+UKF6hUUmAt2Uc0jj2io=
My golang code is 
package main

import (
    "crypto/sha1"
    "fmt"
    "golang.org/x/crypto/pbkdf2"
    b64 "encoding/base64"
)

var (
    PasswordSecuritySalt       = "47687"
    PasswordSecurityIterations = 1000
    PasswordSecurityKeylen     = 32
)

func HashPassword(str string) string {
    hashedPassword := pbkdf2.Key([]byte(str), []byte(PasswordSecuritySalt), PasswordSecurityIterations, PasswordSecurityKeylen, sha1.New)
    return  b64.StdEncoding.EncodeToString(hashedPassword)
}

func main() {
    password := "123456"
    fmt.Println(PasswordSecuritySalt + " " + password)
    fmt.Println(HashPassword(password))

}

Result is 
47687 123456
EVqb1dCe8p+iVEquNjJmHhSjruGATNQX73F6msXivM8=
Why golang result hash password is different with C#. Please help me.

Solutions/Answers:

Answer 1:

.NET is using UTF-16 strings, so each character is represented by at least 2 bytes, while Go is using UTF-8 strings.

C#:

Encoding.Unicode.GetBytes("47687") // [52 0 55 0 54 0 56 0 55 0]

Go:

[]byte("47687") // [52 55 54 56 55]

If you want to get the same results in your Go application as in C#, you’ll have to convert Go strings to UTF-16 byte slices:

package main

import (
    "crypto/sha1"
    b64 "encoding/base64"
    "encoding/binary"
    "fmt"
    "golang.org/x/crypto/pbkdf2"
    "unicode/utf16"
)

var (
    PasswordSecuritySalt       = "47687"
    PasswordSecurityIterations = 1000
    PasswordSecurityKeylen     = 32
)

func stringToUTF16Bytes(s string) []byte {
    runes := utf16.Encode([]rune(s))
    bytes := make([]byte, len(runes)*2)
    for i, r := range runes {
        binary.LittleEndian.PutUint16(bytes[i*2:], r)
    }
    return bytes
}

func HashPassword(str string) string {
    hashedPassword := pbkdf2.Key(stringToUTF16Bytes(str), stringToUTF16Bytes(PasswordSecuritySalt), PasswordSecurityIterations, PasswordSecurityKeylen, sha1.New)
    return b64.StdEncoding.EncodeToString(hashedPassword)
}

func main() {
    fmt.Println(HashPassword("123456"))
}

References