// hkdfExpand implements HKDF-Expand from RFC 5869. func hkdfExpand(hash func() hash.Hash, prk, info []byte, length int) []byte { hashSize := hash().Size() if length > 255*hashSize { panic("hkdfExpand: length too long") } if len(prk) < hashSize { panic("hkdfExpand: prk too short") } var lastBlock []byte counter := byte(0) okm := make([]byte, length) hmac := hmac.New(hash, prk) for length > 0 { hmac.Reset() counter++ hmac.Write(lastBlock) hmac.Write(info) hmac.Write([]byte{counter}) block := hmac.Sum(nil) lastBlock = block copy(okm[(int(counter)-1)*hashSize:], block) length -= hashSize } return okm }
func (mp *MerkleProof) calcRootHash(seed []byte, lastNode []byte) []byte { hmac := hmac.New(sha256.New, seed) for i := len(mp.Level) - 1; i >= 0; i-- { hmac.Reset() if mp.Level[i].NodeHash != nil { if mp.Level[i].IsLeft { hmac.Write(mp.Level[i].NodeHash) hmac.Write(lastNode) } else { hmac.Write(lastNode) hmac.Write(mp.Level[i].NodeHash) } lastNode = hmac.Sum(nil) } } return lastNode }
// WithHMAC derives key of length outlen from the provided password, salt, // and the number of iterations using PKCS#5 PBKDF2 with the provided // hash function in HMAC. // // Caller is responsible to make sure that outlen < (2^32-1) * hash.Size(). func WithHMAC(hash func() hash.Hash, password []byte, salt []byte, iterations int, outlen int) []byte { out := make([]byte, outlen) hashSize := hash().Size() ibuf := make([]byte, 4) block := 1 p := out for outlen > 0 { clen := outlen if clen > hashSize { clen = hashSize } ibuf[0] = byte((block >> 24) & 0xff) ibuf[1] = byte((block >> 16) & 0xff) ibuf[2] = byte((block >> 8) & 0xff) ibuf[3] = byte((block) & 0xff) hmac := hmac.New(hash, password) hmac.Write(salt) hmac.Write(ibuf) tmp := hmac.Sum() for i := 0; i < clen; i++ { p[i] = tmp[i] } for j := 1; j < iterations; j++ { hmac.Reset() hmac.Write(tmp) tmp = hmac.Sum() for k := 0; k < clen; k++ { p[k] ^= tmp[k] } } outlen -= clen block++ p = p[clen:] } return out }