Created
February 25, 2019 04:28
-
-
Save 0xef53/f56ac4e12869c41c7c02433ee80ddf77 to your computer and use it in GitHub Desktop.
MD5 hashing function (like mkpasswd --hash=md5)
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
func md5Crypt(password string, salt string, prefix string) string { | |
// start with a hash of password and salt | |
initBin := md5.Sum([]byte(password + salt + password)) | |
// begin an initial string with hash and salt | |
initText := bytes.NewBufferString(password + prefix + salt) | |
// add crap to the string willy-nilly | |
for i := len(password); i > 0; i -= 16 { | |
lim := i | |
if lim > 16 { | |
lim = 16 | |
} | |
initText.Write(initBin[0:lim]) | |
} | |
// add more crap to the string willy-nilly | |
for i := len(password); i > 0; i >>= 1 { | |
if (i & 1) == 1 { | |
initText.WriteByte(byte(0)) | |
} else { | |
initText.WriteByte(password[0]) | |
} | |
} | |
// Begin our hashing in earnest using our initial string | |
bin := md5.Sum(initText.Bytes()) | |
n := bytes.NewBuffer([]byte{}) | |
for i := 0; i < 1000; i++ { | |
// prepare to make a new muddle | |
n.Reset() | |
// alternate password+crap+bin with bin+crap+password | |
if (i & 1) == 1 { | |
n.WriteString(password) | |
} else { | |
n.Write(bin[:]) | |
} | |
// usually add the salt, but not always | |
if i%3 != 0 { | |
n.WriteString(salt) | |
} | |
// usually add the password but not always | |
if i%7 != 0 { | |
n.WriteString(password) | |
} | |
// the back half of that alternation | |
if (i & 1) == 1 { | |
n.Write(bin[:]) | |
} else { | |
n.WriteString(password) | |
} | |
// replace bin with the md5 of this muddle | |
bin = md5.Sum(n.Bytes()) | |
} | |
// At this point we stop transliterating the PHP code and flip back to | |
// reading the Apache source. The PHP uses their base64 library, but that | |
// uses the wrong character set so needs to be repaired afterwards and reversed | |
// and it is just really weird to read. | |
result := bytes.NewBuffer([]byte{}) | |
// This is our own little similar-to-base64-but-not-quite filler | |
fill := func(a byte, b byte, c byte) { | |
v := (uint(a) << 16) + (uint(b) << 8) + uint(c) // take our 24 input bits | |
for i := 0; i < 4; i++ { // and pump out a character for each 6 bits | |
result.WriteByte("./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[v&0x3f]) | |
v >>= 6 | |
} | |
} | |
// The order of these indices is strange, be careful | |
fill(bin[0], bin[6], bin[12]) | |
fill(bin[1], bin[7], bin[13]) | |
fill(bin[2], bin[8], bin[14]) | |
fill(bin[3], bin[9], bin[15]) | |
fill(bin[4], bin[10], bin[5]) // 5? Yes. | |
fill(0, 0, bin[11]) | |
resultString := string(result.Bytes()[0:22]) // we wrote two extras since we only need 22. | |
return resultString | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment