Switch blueprint commit to use a random SHA-1

Generating a SHA-1 based on time is not safe. A collision can easily be
generated, and if parallel operations are used they will eventually
collide. This reads random bytes and uses them for the SHA-1 hash. It
will return an error if the rand.Read() fails.
This commit is contained in:
Brian C. Lane 2020-01-31 14:21:20 -08:00 committed by Ondřej Budai
parent c054015440
commit 642b90c977
2 changed files with 29 additions and 7 deletions

View file

@ -4,9 +4,11 @@ package store
import (
"bytes"
"crypto/rand"
"crypto/sha1"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
@ -223,6 +225,19 @@ func writeFileAtomically(filename string, data []byte, mode os.FileMode) error {
return nil
}
func randomSHA1String() (string, error) {
hash := sha1.New()
data := make([]byte, 20)
n, err := rand.Read(data)
if err != nil {
return "", err
} else if n != 20 {
return "", errors.New("randomSHA1String: short read from rand")
}
hash.Write(data)
return hex.EncodeToString(hash.Sum(nil)), nil
}
func (s *Store) change(f func() error) error {
s.mu.Lock()
defer s.mu.Unlock()
@ -351,13 +366,10 @@ func bumpVersion(str string) string {
func (s *Store) PushBlueprint(bp blueprint.Blueprint, commitMsg string) {
s.change(func() error {
hash := sha1.New()
// Hash timestamp to create unique hash
hash.Write([]byte(time.Now().String()))
// Get hash as a byte slice
commitBytes := hash.Sum(nil)
// Get hash as a hex string
commit := hex.EncodeToString(commitBytes)
commit, err := randomSHA1String()
if err != nil {
return err
}
timestamp := time.Now().Format("2006-01-02T15:04:05Z")
change := blueprint.Change{
Commit: commit,

View file

@ -28,3 +28,13 @@ func TestBumpVersion(t *testing.T) {
}
}
}
func TestRandomSHA1String(t *testing.T) {
hash, err := randomSHA1String()
if err != nil {
t.Fatalf("RandomSHA1String failed: %s", err)
}
if len(hash) != 40 {
t.Fatalf("RandomSHA1String failed: hash is not 40 characters")
}
}