x.crypto.chacha20poly1305 #
chacha20poly1305
Chacha20Poly1305 Authenticated Encryption with Additional Data (AEAD) module for V Language
This module provides authenticated encryption with additional data (AEAD) algorithm in V Language. Its backed by experimental x.crypto.chacha20
symmetric key stream cipher encryption module and x.crypto.poly1305
message authentication code (MAC) module.
[!Warning] > This is an absolutely experimental module, which is subject to change. > Please use it carefully, thoroughly and wisely.
Supported features
The implemented features at the time of writing (2025/10/08) are:- The standard ChaCha20 and Poly1305 construct for IETF Protocols defined in RFC 8439
- ChaCha20 Poly1305 AEAD construct with 8-bytes nonce.
- Support for eXtended ChaCha20 Poly1305 AEAD construct with 24 bytes nonce.
- Support for nonce-misuse resistent and key-commiting AEAD through ChaCha20-Poly1305-PSIV construction defined in the A Robust Variant of ChaCha20-Poly1305 paper.
Examples
import encoding.hex
import x.crypto.chacha20poly1305
fn main() {
// plaintext message to be encrypted and authenticated
message := 'Ladies and Gentlemen of the class of '99: If I could offer you only one
tip for the future, sunscreen would be it.'.bytes()
// sets your secure random key
key := hex.decode('808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f')!
// give yours nonce
nonce := hex.decode('070000004041424344454647')!
// yours additional data
aad := hex.decode('50515253c0c1c2c3c4c5c6c7')!
// lets doing authenticated encryption
ciphertext := chacha20poly1305.encrypt(message, key, nonce, aad)!
// lets perform decryption back
plaintext := chacha20poly1305.decrypt(ciphertext, key, nonce, aad)!
assert plaintext == message
}
Constants #
const key_size = 32
key_size is the size of key (in bytes) which the Chacha20Poly1305 AEAD accepts.
const orig_nonce_size = 8
orig_nonce_size is the size (in bytes) of nonce of the original (DJ Bernstein) variant which the Chacha20Poly1305 AEAD accepts.
const nonce_size = 12
nonce_size is the size of the standard nonce (in bytes) which the Chacha20Poly1305 AEAD accepts.
const x_nonce_size = 24
nonce_size is the size of the extended nonce (in bytes) which the Chacha20Poly1305 AEAD accepts.
const tag_size = 16
tag_size is the size of the message authenticated code (in bytes) produced by Chacha20Poly1305 AEAD.
fn decrypt #
fn decrypt(ciphertext []u8, key []u8, nonce []u8, ad []u8, opt chacha20.Options) ![]u8
decrypt does one-shot decryption of given ciphertext with associated key, nonce and additional data. It return plaintext output and verify if resulting tag is a valid message authenticated code (mac) for given message, key and additional data.
fn encrypt #
fn encrypt(plaintext []u8, key []u8, nonce []u8, ad []u8, opt chacha20.Options) ![]u8
encrypt does one-shot encryption of given plaintext with associated key, nonce and additional data. It return ciphertext output and authenticated tag appended into it.
fn new #
fn new(key []u8, nsize int, opt chacha20.Options) !&AEAD
new creates a new Chacha20Poly1305 AEAD instance with given 32 bytes of key and the nonce size in nsize. The nsize should be 8, 12 or 24 length, otherwise it would return error.
fn new_psiv #
fn new_psiv(key []u8) !&Chacha20Poly1305RE
new_psiv creates a new Chacha20Poly1305RE with PSIV construct to operate on.
fn psiv_decrypt #
fn psiv_decrypt(ciphertext []u8, key []u8, nonce []u8, ad []u8) ![]u8
psiv_decrypt decrypts the ciphertext with provided key, nonce and additional data in ad. It also tries to validate message authenticated code within ciphertext compared with calculated tag. It returns successfully decrypted message or error on fails.
fn psiv_encrypt #
fn psiv_encrypt(plaintext []u8, key []u8, nonce []u8, ad []u8) ![]u8
psiv_encrypt encrypts plaintext with provided key, nonce and additional data ad. It returns a ciphertext plus message authentication code (mac) contained within the end of ciphertext
interface AEAD #
interface AEAD {
// nonce_size return the nonce size (in bytes) used by this AEAD algorithm that should be
// passed to `.encrypt` or `.decrypt`.
nonce_size() int
// overhead returns the maximum difference between the lengths of a plaintext and its ciphertext.
overhead() int
// encrypt encrypts and authenticates the provided plaintext along with a nonce, and
// to be authenticated additional data in `ad`.
// It returns ciphertext bytes where its encoded form is up to implementation and
// not dictated by the interfaces.
// Usually its contains encrypted text plus some authentication tag, and maybe some other bytes.
encrypt(plaintext []u8, nonce []u8, ad []u8) ![]u8
// decrypt decrypts and authenticates (verifies) the provided ciphertext along with a nonce, and
// additional data. If verified successfully, it returns the plaintext and error otherwise.
decrypt(ciphertext []u8, nonce []u8, ad []u8) ![]u8
}
This interface was a proposed draft for Authenticated Encryption with Additional Data (AEAD) interface AEAD
likes discussion at discord channel. see https://discord.com/channels/592103645835821068/592320321995014154/1206029352412778577 But its little modified to be more v-idiomatic.
Note: This interface should be more appropriately located in crypto.cipher
, we can move it into crypto.cipher
later. Authenticated Encryption with Additional Data (AEAD) interface
fn (Chacha20Poly1305) nonce_size #
fn (c Chacha20Poly1305) nonce_size() int
nonce_size returns the size of underlying nonce (in bytes) of AEAD algorithm.
fn (Chacha20Poly1305) overhead #
fn (c Chacha20Poly1305) overhead() int
overhead returns maximum difference between the lengths of a plaintext to be encrypted and ciphertext's output. In the context of Chacha20Poly1305, .overhead() == .tag_size
.
fn (Chacha20Poly1305) encrypt #
fn (c Chacha20Poly1305) encrypt(plaintext []u8, nonce []u8, ad []u8) ![]u8
encrypt encrypts plaintext, along with nonce and additional data and generates authenticated tag appended into ciphertext's output.
fn (Chacha20Poly1305) decrypt #
fn (c Chacha20Poly1305) decrypt(ciphertext []u8, nonce []u8, ad []u8) ![]u8
decrypt decrypts ciphertext along with provided nonce and additional data. Decryption is similar with the encryption process with slight differences in: The roles of ciphertext and plaintext are reversed, so the ChaCha20 encryption function is applied to the ciphertext, producing the plaintext. The Poly1305 function is still run on the AAD and the ciphertext, not the plaintext. The calculated mac is bitwise compared to the received mac. The message is authenticated if and only if the tags match, return error if failed to verify.
struct Chacha20Poly1305RE #
struct Chacha20Poly1305RE implements AEAD {
mut:
// An underlying 32-bytes of key
key []u8
// flags that tells derivation keys has been precomputed
precomp bool
mac_key []u8
enc_key []u8
po &poly1305.Poly1305 = unsafe { nil }
}
Chacha20Poly1305RE is a Chacha20Poly1305 opaque with nonce-misuse resistent and key-commiting AEAD scheme with PSIV construct.
fn (Chacha20Poly1305RE) free #
fn (mut c Chacha20Poly1305RE) free()
free releases resources taken by c. Dont use c after .free
call.
fn (Chacha20Poly1305RE) nonce_size #
fn (c &Chacha20Poly1305RE) nonce_size() int
nonce_size return the size of the nonce of underlying c. Currently, it only support for standard 12-bytes nonce.
fn (Chacha20Poly1305RE) overhead #
fn (c &Chacha20Poly1305RE) overhead() int
overhead returns difference between the lengths of a plaintext and its ciphertext. Its normally returns a tag size produced by this scheme.
fn (Chacha20Poly1305RE) encrypt #
fn (c Chacha20Poly1305RE) encrypt(plaintext []u8, nonce []u8, ad []u8) ![]u8
encrypt encrypts and authenticates the provided plaintext along with a nonce, and to be authenticated additional data in ad
. It returns a ciphertext with message authenticated code stored within the end of ciphertext.
fn (Chacha20Poly1305RE) decrypt #
fn (c Chacha20Poly1305RE) decrypt(ciphertext []u8, nonce []u8, ad []u8) ![]u8
decrypt decrypts the ciphertext with provided key, nonce and additional data in ad. It also tries to validate message authenticated code within ciphertext compared with calculated tag. It returns successfully decrypted message or error on fails.