Example #1
0
// Seal fulfills the crypto.AEAD interface
func (c AesCbcHmac) Seal(dst, nonce, plaintext, data []byte) []byte {
	ctlen := len(plaintext)
	ciphertext := make([]byte, ctlen+c.Overhead())[:ctlen]
	copy(ciphertext, plaintext)
	ciphertext = padbuf.PadBuffer(ciphertext).Pad(c.blockCipher.BlockSize())

	cbc := cipher.NewCBCEncrypter(c.blockCipher, nonce)
	cbc.CryptBlocks(ciphertext, ciphertext)

	authtag := c.ComputeAuthTag(data, nonce, ciphertext)

	retlen := len(dst) + len(ciphertext) + len(authtag)

	ret := ensureSize(dst, retlen)
	out := ret[len(dst):]
	n := copy(out, ciphertext)
	n += copy(out[n:], authtag)

	if debug.Enabled {
		debug.Printf("Seal: ciphertext = %x (%d)\n", ciphertext, len(ciphertext))
		debug.Printf("Seal: authtag    = %x (%d)\n", authtag, len(authtag))
		debug.Printf("Seal: ret        = %x (%d)\n", ret, len(ret))
	}
	return ret
}
Example #2
0
// Open fulfills the crypto.AEAD interface
func (c AesCbcHmac) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
	if len(ciphertext) < c.keysize {
		return nil, errors.New("invalid ciphertext (too short)")
	}

	tagOffset := len(ciphertext) - c.tagsize
	if tagOffset%c.blockCipher.BlockSize() != 0 {
		return nil, fmt.Errorf(
			"invalid ciphertext (invalid length: %d %% %d != 0)",
			tagOffset,
			c.blockCipher.BlockSize(),
		)
	}
	tag := ciphertext[tagOffset:]
	ciphertext = ciphertext[:tagOffset]

	expectedTag := c.ComputeAuthTag(data, nonce, ciphertext)
	if subtle.ConstantTimeCompare(expectedTag, tag) != 1 {
		if debug.Enabled {
			debug.Printf("provided tag = %x\n", tag)
			debug.Printf("expected tag = %x\n", expectedTag)
		}
		return nil, errors.New("invalid ciphertext (tag mismatch)")
	}

	cbc := cipher.NewCBCDecrypter(c.blockCipher, nonce)
	buf := make([]byte, tagOffset)
	cbc.CryptBlocks(buf, ciphertext)

	plaintext, err := padbuf.PadBuffer(buf).Unpad(c.blockCipher.BlockSize())
	if err != nil {
		return nil, err
	}
	ret := ensureSize(dst, len(plaintext))
	out := ret[len(dst):]
	copy(out, plaintext)
	return ret, nil
}