package auth import "crypto/md5" import "strings" const itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" var md5_crypt_swaps = [16]int{12, 6, 0, 13, 7, 1, 14, 8, 2, 15, 9, 3, 5, 10, 4, 11} type MD5Entry struct { Magic, Salt, Hash []byte } func NewMD5Entry(e string) *MD5Entry { parts := strings.SplitN(e, "$", 4) if len(parts) != 4 { return nil } return &MD5Entry{ Magic: []byte("$" + parts[1] + "$"), Salt: []byte(parts[2]), Hash: []byte(parts[3]), } } /* MD5 password crypt implementation */ func MD5Crypt(password, salt, magic []byte) []byte { d := md5.New() d.Write(password) d.Write(magic) d.Write(salt) d2 := md5.New() d2.Write(password) d2.Write(salt) d2.Write(password) for i, mixin := 0, d2.Sum(nil); i < len(password); i++ { d.Write([]byte{mixin[i%16]}) } for i := len(password); i != 0; i >>= 1 { if i&1 == 0 { d.Write([]byte{password[0]}) } else { d.Write([]byte{0}) } } final := d.Sum(nil) for i := 0; i < 1000; i++ { d2 := md5.New() if i&1 == 0 { d2.Write(final) } else { d2.Write(password) } if i%3 != 0 { d2.Write(salt) } if i%7 != 0 { d2.Write(password) } if i&1 == 0 { d2.Write(password) } else { d2.Write(final) } final = d2.Sum(nil) } result := make([]byte, 0, 22) v := uint(0) bits := uint(0) for _, i := range md5_crypt_swaps { v |= (uint(final[i]) << bits) for bits = bits + 8; bits > 6; bits -= 6 { result = append(result, itoa64[v&0x3f]) v >>= 6 } } result = append(result, itoa64[v&0x3f]) return append(append(append(magic, salt...), '$'), result...) }