Ejemplo n.º 1
0
// 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
}
Ejemplo n.º 2
0
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
}
Ejemplo n.º 3
0
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
}
Ejemplo n.º 4
0
// 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
}
Ejemplo n.º 5
0
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
}
Ejemplo n.º 6
0
// 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
}