package bhash import ( "bytes" "crypto/sha512" "log" "golang.org/x/crypto/blowfish" ) var magic = []byte("OxychromaticBlowfishSwatDynamite") const rounds = 64 func Hash(pass, salt []byte) []byte { c, err := blowfish.NewSaltedCipher(pass, salt) if err != nil { panic(err) } // key expansion for i := 0; i < rounds; i++ { blowfish.ExpandKey(salt, c) blowfish.ExpandKey(pass, c) } // encryption buf := new(bytes.Buffer) bSz := c.BlockSize() for n := 0; n < len(magic)/bSz; n++ { b := make([]byte, bSz) copy(b, magic[n*bSz:(n+1)*bSz]) for i := 0; i < rounds; i++ { c.Encrypt(b, b) } // copy out b[0], b[1], b[2], b[3] = b[3], b[2], b[1], b[0] b[4], b[5], b[6], b[7] = b[7], b[6], b[5], b[4] buf.Write(b) } return buf.Bytes() } func Pbkdf(pass, salt []byte, iter, keyLen int) []byte { // collapse password h := sha512.New() h.Write(pass) sha2pass := h.Sum(nil) out := make([]byte, 4*blowfish.BlockSize) // XXX for count := 1; keyLen > 0; count++ { countSalt := []byte{ byte(count >> 24), byte(count >> 16), byte(count >> 8), byte(count), } // first round, salt is salt h.Reset() h.Write(salt) h.Write(countSalt) sha2salt := h.Sum(nil) tmp := Hash(sha2pass, sha2salt) copy(out, tmp) log.Println(out) for i := 1; i < iter; i++ { h.Reset() h.Write(tmp) sha2salt = h.Sum(nil) tmp = Hash(sha2pass, sha2salt) for i := range out { out[i] ^= tmp[i] } log.Println(out) } // pbkdf2 deviation: output the key material non-linearly // TODO keyLen-- // XXX } return nil }