With symmetric key, Bob and Alice have the same key. NaCl uses the XChaCha20 method, and which supports stream encryption (and which does not require padding as a block cipher does, and is also faster than block cipher modes). ChaCha20 was created by Daniel J. Bernstein, and has an eight byte or 16 byte nonce. XChaCha20 (eXtended-nonce ChaCha) is an update to ChaCha20, and uses a 24 byte nonce. It has a lower propability of nonce misuse than ChaCha20. The cipher text is made up of the cipher message (and which is the same length of the plaintext message) is the same number of bytes as the message (five bytes), and that the cipher text has an extra 16 bytes (used for AEAD - Authenticated Encryption with Associated Data). The MAC bytes used Poly1305 and provide an integrity check for the cipher.
XChaCha20 in Rust |
An outline of the Rust code is:
extern crate base64; extern crate hex; extern crate crypto; use crypto::{symmetriccipher::{ SynchronousStreamCipher}}; use rustc_serialize::hex::FromHex; use std::env; use core::str; use std::iter::repeat; fn hex_to_bytes(s: &str) -> Vec<u8> { s.from_hex().unwrap() } fn main() { let mut mykey="0000000000000000000000000000000000000000000000000000000000000000"; let mut msg="Hello"; let mut myiv="000000000000000000000000000000000000000000000000"; let args: Vec<String> = env::args().collect(); if args.len() >1 { msg = args[1].as_str();} if args.len() >2 { mykey = args[2].as_str();} if args.len() >3 { myiv = args[3].as_str();} println!("== XChaCha20 =="); println!("Message: {:?}",msg); println!("Key: {:?}",mykey); println!("IV: {:?}",myiv); let key=&hex_to_bytes( mykey)[..]; let iv=&hex_to_bytes( myiv)[..]; let plain=msg.as_bytes(); // Encrypting let mut c = crypto::chacha20::ChaCha20::new_xchacha20(&key, iv); let mut output: Vec= repeat(0).take(plain.len()).collect(); c.process(&plain[..], &mut output[..]); println!("\nEncrypted: {}",hex::encode(output.clone())); // Decrypting let mut c = crypto::chacha20::ChaCha20::new_xchacha20(&key, iv); let mut newoutput: Vec = repeat(0).take(output.len()).collect(); c.process(&mut output[..], &mut newoutput[..]); println!("\nDecrypted: {}",str::from_utf8(&newoutput[..]).unwrap()); }
Finally we simply build with:
cargo build
A sample run is:
== XChaCha20 == Message: "This is a secret message!" Key: "0000000000000000000000000000000000000000000000000000000000000000" IV: "000000000000000000000000000000000000000000000001" Encrypted: ef507c4f0e68b27ed67bc6160c1feaa20bd01b7cafe98ab728 Decrypted: This is a secret message!