Last active
December 23, 2015 10:09
-
-
Save trevordixon/6619563 to your computer and use it in GitHub Desktop.
SHA-1 collision finder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | |
) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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