// An implementation of PBKDF2 (Password-Based Key Derivation Function 2) as // specified in PKCS #5 v2.0 from RSA Laboratorie and in `RFC 2898 // <http://www.ietf.org/rfc/rfc2898.txt>`. func PBKDF2(hashfunc func([]byte) hash.Hash, password, salt []byte, iterations, keylen int) (key []byte) { var ( digest []byte i, j, k, length int ) key = make([]byte, keylen) slice := key hash := hashfunc(password) hashlen := hash.Size() scratch := make([]byte, 4) for keylen > 0 { if hashlen > keylen { length = keylen } else { length = hashlen } i += 1 scratch[0] = byte(i >> 24) scratch[1] = byte(i >> 16) scratch[2] = byte(i >> 8) scratch[3] = byte(i) hash.Write(salt) hash.Write(scratch) digest = hash.Sum() hash.Reset() for j = 0; j < length; j++ { slice[j] = digest[j] } for k = 1; k < iterations; k++ { hash.Write(digest) digest = hash.Sum() for j = 0; j < length; j++ { slice[j] ^= digest[j] } hash.Reset() } keylen -= length slice = slice[length:] } return }
// index returns the array index for the given data. func (i *InverseBloomFilter) index(data []byte) uint32 { hash := i.hashPool.Get().(hash.Hash32) hash.Write(data) index := hash.Sum32() % uint32(i.capacity) hash.Reset() i.hashPool.Put(hash) return index }
// Encrypt encrypts a message using ECIES as specified in SEC 1, 5.1. // // s1 and s2 contain shared information that is not part of the resulting // ciphertext. s1 is fed into key derivation, s2 is fed into the MAC. If the // shared information parameters aren't being used, they should be nil. func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err error) { params := pub.Params if params == nil { if params = ParamsFromCurve(pub.Curve); params == nil { err = ErrUnsupportedECIESParameters return } } R, err := GenerateKey(rand, pub.Curve, params) if err != nil { return } hash := params.Hash() z, err := R.GenerateShared(pub, params.KeyLen, params.KeyLen) if err != nil { return } K, err := concatKDF(hash, z, s1, params.KeyLen+params.KeyLen) if err != nil { return } Ke := K[:params.KeyLen] Km := K[params.KeyLen:] hash.Write(Km) Km = hash.Sum(nil) hash.Reset() em, err := symEncrypt(rand, params, Ke, m) if err != nil || len(em) <= params.BlockSize { return } d := messageTag(params.Hash, Km, em, s2) Rb := elliptic.Marshal(pub.Curve, R.PublicKey.X, R.PublicKey.Y) ct = make([]byte, len(Rb)+len(em)+len(d)) copy(ct, Rb) copy(ct[len(Rb):], em) copy(ct[len(Rb)+len(em):], d) return }
// Decrypt decrypts an ECIES ciphertext. func (prv *PrivateKey) Decrypt(rand io.Reader, c, s1, s2 []byte) (m []byte, err error) { if c == nil || len(c) == 0 { err = ErrInvalidMessage return } params := prv.PublicKey.Params if params == nil { if params = ParamsFromCurve(prv.PublicKey.Curve); params == nil { err = ErrUnsupportedECIESParameters return } } hash := params.Hash() var ( rLen int hLen int = hash.Size() mStart int mEnd int ) switch c[0] { case 2, 3, 4: rLen = ((prv.PublicKey.Curve.Params().BitSize + 7) / 4) if len(c) < (rLen + hLen + 1) { err = ErrInvalidMessage return } default: err = ErrInvalidPublicKey return } mStart = rLen mEnd = len(c) - hLen R := new(PublicKey) R.Curve = prv.PublicKey.Curve R.X, R.Y = elliptic.Unmarshal(R.Curve, c[:rLen]) if R.X == nil { err = ErrInvalidPublicKey return } if !R.Curve.IsOnCurve(R.X, R.Y) { err = ErrInvalidCurve return } z, err := prv.GenerateShared(R, params.KeyLen, params.KeyLen) if err != nil { return } K, err := concatKDF(hash, z, s1, params.KeyLen+params.KeyLen) if err != nil { return } Ke := K[:params.KeyLen] Km := K[params.KeyLen:] hash.Write(Km) Km = hash.Sum(nil) hash.Reset() d := messageTag(params.Hash, Km, c[mStart:mEnd], s2) if subtle.ConstantTimeCompare(c[mEnd:], d) != 1 { err = ErrInvalidMessage return } m, err = symDecrypt(rand, params, Ke, c[mStart:mEnd]) return }