Skip to content

x.crypto.chacha20 #

module chacha20

chacha20

Chacha20 (and XChacha20) stream cipher encryption algorithm in pure V. Its mostly based on RFC 8439 and inspired by Go version of the same library.

Examples

module main

import encoding.hex
import x.crypto.chacha20

fn main() {
    // example of random key
    // you should make sure the key (and nonce) are random enough.
    // The security guarantees of the ChaCha20 require that the same nonce
    // value is never used twice with the same key.
    key := hex.decode('bf32a829ebf86d23f6a32a74ef0333401e54a6b2900d35bfadef82c5d49da15f')!
    nonce := hex.decode('a7d7cf3405631f25cc1054bd')!

    input := 'Good of gambler'.bytes()

    // encrypt and the decrypt back
    output := chacha20.encrypt(key, nonce, input)!
    input_back := chacha20.decrypt(key, nonce, output)!

    // should true
    assert input == input_back
}

Constants #

const key_size = 32

size of ChaCha20 key, ie 256 bits size, in bytes

const nonce_size = 12

size of ietf ChaCha20 nonce, ie 96 bits size, in bytes

const x_nonce_size = 24

size of extended ChaCha20 nonce, called XChaCha20, 192 bits

fn decrypt #

fn decrypt(key []u8, nonce []u8, ciphertext []u8) ![]u8

decrypt does reverse of encrypt operation by decrypting ciphertext with ChaCha20 cipher instance with provided key and nonce.

fn encrypt #

fn encrypt(key []u8, nonce []u8, plaintext []u8) ![]u8

encrypt encrypts plaintext bytes with ChaCha20 cipher instance with provided key and nonce. It was a thin wrapper around two supported nonce size, ChaCha20 with 96 bits and XChaCha20 with 192 bits nonce. Internally, encrypt start with 0's counter value. If you want more control, use Cipher instance and setup the counter by your self.

fn new_cipher #

fn new_cipher(key []u8, nonce []u8) !&Cipher

new_cipher creates a new ChaCha20 stream cipher with the given 32 bytes key, a 12 or 24 bytes nonce. If 24 bytes of nonce was provided, the XChaCha20 construction will be used. It returns new ChaCha20 cipher instance or an error if key or nonce have any other length.

struct Cipher #

struct Cipher {
mut:
	// internal's of ChaCha20 states, ie, 16 of u32 words, 4 of ChaCha20 constants,
	// 8 word (32 bytes) of keys, 3 word (24 bytes) of nonces and 1 word of counter
	key      [8]u32
	nonce    [3]u32
	counter  u32
	overflow bool
	// internal buffer for storing key stream results
	block []u8 = []u8{len: block_size}
	// additional fields, follow the go version
	precomp bool
	p1      u32
	p5      u32
	p9      u32
	p13     u32
	p2      u32
	p6      u32
	p10     u32
	p14     u32
	p3      u32
	p7      u32
	p11     u32
	p15     u32
}

Cipher represents ChaCha20 stream cipher instances.

fn (Cipher) xor_key_stream #

fn (mut c Cipher) xor_key_stream(mut dst []u8, src []u8)

xor_key_stream xors each byte in the given slice in the src with a byte from the cipher's key stream. It fulfills cipher.Stream interface. It encrypts the plaintext message in src and stores the ciphertext result in dst in a single run of encryption. You must never use the same (key, nonce) pair more than once for encryption. This would void any confidentiality guarantees for the messages encrypted with the same nonce and key.

fn (Cipher) free #

unsafe
fn (mut c Cipher) free()

free the resources taken by the Cipher c. Dont use cipher after .free call

fn (Cipher) reset #

unsafe
fn (mut c Cipher) reset()

reset quickly sets all Cipher's fields to default value

fn (Cipher) set_counter #

fn (mut c Cipher) set_counter(ctr u32)

set_counter sets Cipher's counter

fn (Cipher) rekey #

fn (mut c Cipher) rekey(key []u8, nonce []u8) !

rekey resets internal Cipher's state and reinitializes state with the provided key and nonce