func (c *aead) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { if n := len(nonce); n != NonceSize { return nil, crypto.NonceSizeError(n) } if len(ciphertext) < c.tagsize { return nil, crypto.AuthenticationError{} } if len(dst) < len(ciphertext)-c.tagsize { panic("dst buffer to small") } var Nonce [12]byte copy(Nonce[:], nonce) hash := ciphertext[len(ciphertext)-c.tagsize:] ciphertext = ciphertext[:len(ciphertext)-c.tagsize] // create the poly1305 key var polyKey [32]byte chacha.XORKeyStream(polyKey[:], polyKey[:], &Nonce, &(c.key), 0, 20) // authenticate the ciphertext var tag [poly1305.TagSize]byte authenticate(&tag, ciphertext, additionalData, &polyKey) if subtle.ConstantTimeCompare(tag[:c.tagsize], hash[:c.tagsize]) != 1 { return nil, crypto.AuthenticationError{} } // decrypt ciphertext chacha.XORKeyStream(dst, ciphertext, &Nonce, &(c.key), 1, 20) return dst[:len(ciphertext)], nil }
func (c *aead) Seal(dst, nonce, plaintext, additionalData []byte) []byte { if n := len(nonce); n != NonceSize { panic(crypto.NonceSizeError(n)) } if len(dst) < len(plaintext)+c.tagsize { panic("dst buffer to small") } var Nonce [12]byte copy(Nonce[:], nonce) // create the poly1305 key var polyKey [32]byte chacha.XORKeyStream(polyKey[:], polyKey[:], &Nonce, &(c.key), 0, 20) // encrypt the plaintext n := len(plaintext) chacha.XORKeyStream(dst, plaintext, &Nonce, &(c.key), 1, 20) // authenticate the ciphertext var tag [poly1305.TagSize]byte authenticate(&tag, dst[:n], additionalData, &polyKey) return append(dst[:n], tag[:c.tagsize]...) }
// XORKeyStream crypts bytes from src to dst using the given key, nonce and counter. Src // and dst may be the same slice but otherwise should not overlap. If len(dst) < len(src) // this function panics. func XORKeyStream(dst, src []byte, nonce *[NonceSize]byte, key *[32]byte, counter uint32) { chacha.XORKeyStream(dst, src, nonce, key, counter, 20) }