101

Can someone show me a working example of how to generate a SHA hash of a string that I have, say myPassword := "beautiful", using Go?

8
  • 12
    If password hashing is actually what you're doing, you should not be using bare SHA1 for this - use PBKDF2, SCRYPT, or BCRYPT. Commented May 23, 2012 at 3:22
  • Yes, I would like to do any of that. But golang does not support any of them natively and I don't want to rely on third party libraries. Commented May 23, 2012 at 6:03
  • 8
    Relying on a third party library is infinitely better than using unsalted, un-iterated SHA1 just because it's available. Commented May 23, 2012 at 6:06
  • 3
    @dystroy The issue is not the strength of SHA1; it's the lack of a salt and key stretching. Adding a salt alone is insufficient, too - you should use an algorithm that iterates. Commented May 23, 2012 at 6:06
  • You're right to point the risks of just using sha1 but are we talking about the last theoretical attack possibilities or the basic reality? SHA1 attacks won't be a thing before a long time and SHA 256 is strong enough (with a salt) for most usages. Commented May 23, 2012 at 6:09

9 Answers 9

116

An example :

import (
    "crypto/sha1"
    "encoding/base64"
)

func (ms *MapServer) storee(bv []byte) {
    hasher := sha1.New()
    hasher.Write(bv)
    sha := base64.URLEncoding.EncodeToString(hasher.Sum(nil))
        ...
}

In this example I make a sha from a byte array. You can get the byte array using

bv := []byte(myPassword) 

Of course you don't need to encode it in base64 if you don't have to : you may use the raw byte array returned by the Sum function.

There seems to be some little confusion in comments below. So let's clarify for next users the best practices on conversions to strings:

  • you never store a SHA as a string in a database, but as raw bytes
  • when you want to display a SHA to a user, a common way is Hexadecimal
  • when you want a string representation because it must fit in an URL or in a filename, the usual solution is Base64, which is more compact
Sign up to request clarification or add additional context in comments.

6 Comments

The usual way to represent a sha as a string is hex encoding not base64.
Depends on your need. Hex encoding is good for humans but even heavier than base64. If you want to store your hash in a db, or send it in json, or use it as a file name (as in my example), I think base64 is better.
@DenysSéguret if you're going to store it in a db then it might be best just to store the bytes since db contents generally shouldn't be stored encoded
@BrianLeishman In my answer I explicitly says "you never store a SHA as a string in a database, but as raw bytes"
@DenysSéguret Ah my bad, I was replying to your comment "If you want to store your hash in a db ... base64 is better"
|
101

Go By Example has a page on sha1 hashing.

package main

import (
    "fmt"
    "crypto/sha1"
    "encoding/hex"
)

func main() {

    s := "sha1 this string"
    h := sha1.New()
    h.Write([]byte(s))
    sha1_hash := hex.EncodeToString(h.Sum(nil))

    fmt.Println(s, sha1_hash)
}

You can run this example on play.golang.org

Comments

28

The package documentation at http://golang.org/pkg/crypto/sha1/ does have an example that demonstrates this. It's stated as an example of the New function, but it's the only example on the page and it has a link right near the top of the page so it is worth looking at. The complete example is,

Code:

h := sha1.New()
io.WriteString(h, "His money is twice tainted: 'taint yours and 'taint mine.")
fmt.Printf("% x", h.Sum(nil))

Output:

59 7f 6a 54 00 10 f9 4c 15 d7 18 06 a9 9a 2c 87 10 e7 47 bd

4 Comments

It does. Seems like it is so hard to find with so many hidden parts. Usability issue.
@SankarP : For now, especially if you don't program in Go every day, it's a little hard to understand how to use the API. I found it easier to read the API source code (which is generally simple). It will probably be easier with time and more online third parties examples and docs.
@SankarP: Try godock.org for easier standard library api navigation.
h.Write([]byte("some string") is more concise than your given example using WriteString
24

You can actually do this in a much more concise and idiomatic manner:

// Assuming 'r' is set to some inbound net/http request
form_value := []byte(r.PostFormValue("login_password"))
sha1_hash := fmt.Sprintf("%x", sha1.Sum(form_value))

// Then output optionally, to test
fmt.Println(sha1_hash)

In this trivial example of a http.Request POST containing a login_password field, it is worth noting that fmt.Sprintf() called with %x converted the hash value to hex without having to include an import "encoding/hex" declaration.

( We used fmt.Sprintf() as opposed to fmt.Printf() as we were outputting a string to a variable assignment, not an io.Writer interface. )

Also of reference, is that the sha1.Sum() function verbosely instantiates in the same manner as the sha1.New() definition:

func New() hash.Hash {
    d := new(digest)
    d.Reset()
    return d
}

func Sum(data []byte) [Size]byte {
    var d digest
    d.Reset()
    d.Write(data)
    return d.checkSum()
}

This holds true ( at least at the time of posting ) for the Sha library variants in Golang's standard crypto set, such as Sha512.

Lastly, if one wanted to, they could follow Golang's [to]String() implementation with something like func (h hash.Hash) String() string {...} to encapsulate the process.

That is most likely beyond the desired scope of the original question.

1 Comment

Thanks for all the extra detail Mr. Webster!
14
h := sha1.New()
h.Write(content)
sha := h.Sum(nil)  // "sha" is uint8 type, encoded in base16

shaStr := hex.EncodeToString(sha)  // String representation

fmt.Printf("%x\n", sha)
fmt.Println(shaStr)

Comments

8

Here's some good examples:

The second example targets sha256, to do sha1 hexadecimal you'd do:

// Calculate the hexadecimal HMAC SHA1 of requestDate using sKey                
key := []byte(c.SKey)                                                           
h := hmac.New(sha1.New, key)                                                    
h.Write([]byte(requestDate))                                                    
hmacString := hex.EncodeToString(h.Sum(nil))

(from https://github.com/soniah/dnsmadeeasy)

Comments

4

Here is a function you could use to generate a SHA1 hash:

// SHA1 hashes using sha1 algorithm
func SHA1(text string) string {
    algorithm := sha1.New()
    algorithm.Write([]byte(text))
    return hex.EncodeToString(algorithm.Sum(nil))
}

I put together a group of those utility hash functions here: https://github.com/shomali11/util

You will find FNV32, FNV32a, FNV64, FNV65a, MD5, SHA1, SHA256 and SHA512

Comments

3

As a one liner hashing in Go is more convenient:

sha := sha256.Sum256([]byte())

The result is a []byte and might be transformed into hex or base64.

Comments

2
// Get sha1 from string
func Hashstr(Txt string) string {
    h := sha1.New()
    h.Write([]byte(Txt))
    bs  := h.Sum(nil)
    sh:= string(fmt.Sprintf("%x\n", bs))
    return sh
}

1 Comment

Speed and useful.

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.