std.crypto.chacha.ChaCha20
class pub ChaCha20
The ChaCha20 stream cipher.
ChaCha is a stream cipher similar to Salsa20. Our implementation is based on RFC 8439.
This type provides only a stream cipher, and integrity/authenticity validation is performed.
For more information about ChaCha, consider reading/watching the following resources:
- https://datatracker.ietf.org/doc/html/rfc8439
- https://en.wikipedia.org/wiki/Salsa20#ChaCha_variant
- https://www.youtube.com/watch?v=UeIpq-C-GSA
Limitations
As our implementation is based on RFC 8439, the total message size is limited to 256 GiB. When reaching this limit the cipher panics, as the alternative is a silent overflow that could lead to weaker/broken encryption.
Examples
Encrypting and decrypting using the same cipher:
import std.crypto.chacha (ChaCha20)
import std.rand (Random)
let rand = Random.new
let key = rand.bytes(size: 32)
let nonce = rand.bytes(size: 12)
let cipher = ChaCha20.new(key, nonce)
let plaintext = 'I like turtles'
let encrypted = cipher.encrypt(plaintext.to_byte_array)
# If we want to decrypt reusing the same cipher, we must first reset the
# block counter to its initial value:
cipher.counter = 0
cipher.decrypt(encrypted).to_string # => 'I like turtles'
You can also decrypt using a new cipher, as long as the key, nonce and starting block counter are the same:
import std.crypto.chacha (ChaCha20)
import std.rand (Random)
let rand = Random.new
let key = rand.bytes(size: 32)
let nonce = rand.bytes(size: 12)
let plaintext = 'I like turtles'
let encrypted = ChaCha20.new(key, nonce).encrypt(plaintext.to_byte_array)
ChaCha20
.new(key, nonce)
.decrypt(encrypted)
.to_string # => 'I like turtles'
Static methods
new
Show source codeHide source code
fn pub static new(key: ref ByteArray, nonce: ref ByteArray) -> ChaCha20 {
if key.size != KEY_SIZE {
panic('ChaCha20 key sizes must be exactly ${KEY_SIZE} bytes')
}
if nonce.size != CHACHA_NONCE_SIZE {
panic('ChaCha20 nonce sizes must be exactly ${CHACHA_NONCE_SIZE} bytes')
}
ChaCha20(
Matrix(
[
0x61707865,
0x3320646E,
0x79622D32,
0x6B206574,
little.read_u32(from: key, at: 0),
little.read_u32(from: key, at: 4),
little.read_u32(from: key, at: 8),
little.read_u32(from: key, at: 12),
little.read_u32(from: key, at: 16),
little.read_u32(from: key, at: 20),
little.read_u32(from: key, at: 24),
little.read_u32(from: key, at: 28),
DEFAULT_COUNTER,
little.read_u32(from: nonce, at: 0),
little.read_u32(from: nonce, at: 4),
little.read_u32(from: nonce, at: 8),
],
),
)
}
fn pub static new(key: ref ByteArray, nonce: ref ByteArray) -> ChaCha20
Returns a new ChaCha20 cipher from the given key and nonce.
The key must be something generated randomly and securely, not something predictable.
The nonce must be unique for every message encrypted using this cipher. Using the same nonce for different messages weakens the encryption.
The block counter defaults to zero.
Panics
This method panics if key
isn't exactly 32 bytes, or if nonce
isn't
exactly 8 bytes.
Examples
import std.crypto.chacha (ChaCha20)
import std.rand (Random)
let rand = Random.new
let key = rand.bytes(size: 32)
let nonce = rand.bytes(size: 12)
ChaCha20.new(key, nonce)
In this example we use a randomly generated key and nonce. In production environments you must ensure that the nonce is never reused for the same key. Simply generating a random nonce isn't enough, as given enough time and bad luck the same nonce may be produced.
Instance methods
counter=
Show source codeHide source code
fn pub mut counter=(value: Int) {
if value < 0 or value > MAX_COUNTER {
panic('ChaCha block counters must be between 0 and ${MAX_COUNTER}')
} else {
@matrix.set(12, value)
}
}
fn pub mut counter=(value: Int)
Sets the block counter to the given value.
Panics
This method panics if the value doesn't fit in the range valid for an unsigned 32-bits integer.
decrypt
Show source codeHide source code
fn pub mut decrypt(bytes: mut ByteArray) -> ByteArray {
apply(bytes)
}
fn pub mut decrypt(bytes: mut ByteArray) -> ByteArray
Decrypts a ByteArray
and returns the decrypted result as a new
ByteArray
.
encrypt
Show source codeHide source code
fn pub mut encrypt(bytes: mut ByteArray) -> ByteArray {
apply(bytes)
}
fn pub mut encrypt(bytes: mut ByteArray) -> ByteArray
Encrypts a ByteArray
and returns the encrypted result as a new
ByteArray
.
Implemented traits
Cipher
impl Cipher for ChaCha20