// Open decrypts and authenticates a message encrypted using Seal. // It decrypts sealed message src and appends it onto plaintext buffer dst, // growing the dst buffer if it is too small (or nil), // and returns the resulting destination buffer or an error. // func (c Cipher) Open(dst, src []byte) ([]byte, error) { m := c.KeySize() l := len(src) - m if l < 0 { return nil, errors.New("sealed ciphertext too short") } ctx := src[:l] mac := src[l:] dst, msg := util.Grow(dst, l) if &msg[0] != &ctx[0] { // Decrypt and absorb ciphertext c.Message(msg, ctx, ctx) } else { tmp := make([]byte, l) c.Message(tmp, ctx, ctx) copy(msg, tmp) } c.Message(mac, mac, nil) // Compute MAC and XOR with received if subtle.ConstantTimeAllEq(mac, 0) == 0 { return nil, errors.New("ciphertext authentication failed") } return dst, nil }
func (ca *cipherAEAD) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { // Fork off a temporary Cipher state indexed via the nonce ct := ca.Clone() ct.Message(nil, nil, nonce) // Compute the plaintext's length authl := ct.KeySize() plainl := len(ciphertext) - authl if plainl < 0 { return nil, errors.New("AEAD ciphertext too short") } auth := ciphertext[plainl:] ciphertext = ciphertext[:plainl] // Decrypt the plaintext and update the temporary Cipher state dst, plaintext := util.Grow(dst, plainl) ct.Message(plaintext, ciphertext, ciphertext) // Compute and check the authenticator based on post-encryption state ct.Message(auth, auth, nil) if subtle.ConstantTimeAllEq(auth, 0) == 0 { return nil, errors.New("AEAD authenticator check failed") } return dst, nil }
func (ca *cipherAEAD) Seal(dst, nonce, plaintext, data []byte) []byte { // Fork off a temporary Cipher state indexed by the nonce ct := ca.Clone() ct.Message(nil, nil, nonce) // Encrypt the plaintext and update the temporary Cipher state dst, ciphertext := util.Grow(dst, len(plaintext)) ct.Message(ciphertext, plaintext, ciphertext) // Compute and append the authenticator based on post-encryption state dst, auth := util.Grow(dst, ct.KeySize()) ct.Message(auth, nil, nil) return dst }
// Sum ends the current message and produces a cryptographic checksum or hash // based on the Cipher's state after absorbing all previously-written data. // The resulting hash is appended to the dst slice, // which Sum will grow or allocate if dst is too small or nil. // A Cipher may be used as a hash function by absorbing data via Write // and then calling Sum to finalize the message and produce the hash. // Unlike the hash.Hash interface, this Sum method affects the Cipher's state: // two consecutive calls to Sum on the same Cipher // will produce two different hashes, not the same one. // func (c Cipher) Sum(dst []byte) []byte { c.EndMessage() // finalize any message in progress h := c.HashSize() // hash length dst, hash := util.Grow(dst, h) c.Message(hash, nil, nil) // squeeze out hash return dst }
func (ch *cipherHash) Sum(buf []byte) []byte { // Clone the Cipher to leave the original's state unaffected c := ch.cur.Clone() c.Message(nil, nil, nil) // finalize the message // Squeeze out a hash of any requested size. buf, hash := util.Grow(buf, ch.size) c.Partial(hash, nil, nil) return buf }
// Seal uses a stateful message cipher to implement authenticated encryption. // It encrypts the src message and appends it to the dst slice, // growing or allocating the dst slice if it is too small or nil. // Seal also absorbs the produced ciphertext into the Cipher's state, // then uses that state to append a message authentication check (MAC) // to the sealed message, to be verified by Open. // func (c Cipher) Seal(dst, src []byte) []byte { l := len(src) // message length m := c.KeySize() // MAC length dst, buf := util.Grow(dst, l+m) ctx := buf[:l] mac := buf[l:] c.Message(ctx, src, ctx) // Encrypt and absorb ciphertext c.Message(mac, nil, nil) // Append MAC return dst }