Skip to content

Instantly share code, notes, and snippets.

@trevordixon
Last active December 23, 2015 10:09
Show Gist options
  • Save trevordixon/6619563 to your computer and use it in GitHub Desktop.
Save trevordixon/6619563 to your computer and use it in GitHub Desktop.
SHA-1 collision finder
package main
import (
"bytes"
"crypto/rand"
"crypto/sha1"
"encoding/hex"
"flag"
"fmt"
)
const numBytes = 8
var hashBytes = flag.Int("bytes", 3, "the number of bytes at the beginning of the hash to consider")
var hasher = sha1.New()
func collision(hashBytes int) (attempts int, bytes1, bytes2, collisionHash []byte) {
hasher.Reset()
hashes := map[string][]byte{}
randBytes := make([]byte, numBytes)
for {
attempts++
rand.Read(randBytes)
hasher.Write(randBytes)
h := hasher.Sum(nil)[:hashBytes]
hashString := hex.EncodeToString(h)
if _randBytes, ok := hashes[hashString]; ok {
return attempts, _randBytes, randBytes, h
} else {
_randBytes := make([]byte, numBytes)
copy(_randBytes, randBytes)
hashes[hashString] = _randBytes
}
hasher.Reset()
}
}
func preImage(search []byte) (attempts int, collisionBytes, collisionHash []byte) {
hasher.Reset()
hashBytes := len(search)
randBytes := make([]byte, numBytes)
for {
attempts++
rand.Read(randBytes)
hasher.Write(randBytes)
h := hasher.Sum(nil)[:hashBytes]
if bytes.Equal(h, search) {
return attempts, randBytes, h
}
hasher.Reset()
}
}
var attackType = flag.String("type", "collision", "the type of attack to perform (collision, preimage, or both)")
func main() {
flag.Parse()
if *attackType == "collision" || *attackType == "both" {
fmt.Println("Finding collision...")
attempts, bytes1, bytes2, collisionHash := collision(*hashBytes)
// attempts, _, _, _ := collision(*hashBytes)
// fmt.Printf("%v,weak,%v\n", *hashBytes*8, attempts)
fmt.Printf("Found collision in %v attempts: %x and %x both hash to %x\n\n",
attempts,
bytes1,
bytes2,
collisionHash,
)
}
if *attackType == "preimage" || *attackType == "both" {
randBytes := make([]byte, numBytes)
rand.Read(randBytes)
hasher.Write(randBytes)
search := hasher.Sum(nil)[:*hashBytes]
fmt.Printf("Searching for: %x (%x)\n", search, randBytes)
attempts, collisionBytes, collisionHash := preImage(search)
// attempts, _, _ = preImage(search)
// fmt.Printf("%v,strong,%v\n", *hashBytes*8, attempts)
fmt.Printf("Found collision in %v attempts: %x (%x)\n",
attempts,
collisionHash,
collisionBytes,
)
}
}
Use like:
sha1_attack --bytes 2 --type preimage
sha1_attack --bytes 4 --type collision
sha1_attack --bytes 3 --type both
--bytes is the number of bytes to consider (i.e. the number of bytes to which the SHA-1 digest will be truncated)
--type can be preimage, collision, or both
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment