Requires Rust and Cargo to build; also requires OpenSSL v1.1.0 or higher.
Run `cargo build --release`, the binary will be built to `./target/release/chacha20`.
### Testing
@ -10,22 +10,37 @@ Run `cargo test && cargo build && ./test.sh debug` to test the program.
Alternatively, run `./test.sh` after building to test the release build's correctness.
# Usage
Copies stdin to stdout while encrypting or decrypting with the stream cipher.
Copies stdin to stdout while encrypting or decrypting with the stream cipher`chacha20_poly1305`.
## Modes
* Encrypt - Encrypt stdin to stdout
* Decrypt - Decrypt stdin to stdout
* Keygen - Generate a random key and IV and print them to stdout
To see a more detailed explenation run `chacha20` with no arguments.
To see a more detailed explenation run `chacha20 help`.
## Formats
The key and IV is expected/generated in base64 format.
The key and IV sizes respectively are 32 and 12 bytes.
The ciphertext input and output is raw binary data. You can encode this to text formats if you want with whatever tool you choose (Example with `base64` below.)
## Example
Encrypting and decrypting a string to binary with randomly generated keys
```shell
$ echo "Hello world!" | chacha20 e 2>keys.cck > output.cc20
$ chacha20 d $(cat keys.cck) <output.cc20
Hello world!
```
The same but with text instead of binary ciphertexts
Add `b-encrypt` mode to write the outputted bytes in base64 instead of raw bytes, and `b-decrypt` mode to read the inputted bytes in base64 instead of raw bytes
eprintln!("(Key size is {}, IV size is {})",cha::KEY_SIZE,cha::IV_SIZE);
eprintln!("\nencrypt/decrypt:\n\tIf key and/or IV are not provided, they are generated randomly and printed to stderr in order on one line each");
eprintln!("\tIf the key and/or IV provided's size is lower than the cipher's key/IV size, the rest of the key/IV padded with 0s. If the size is higher, the extra bytes are ignored.");
eprintln!("\nkeygen:\n\tThe key/iv is printed in the same way as auto-generated keys for the en/decryption modes, but to stdout instead of stderr");
std::process::exit(1)
eprintln!("(requires OpenSSL 1.1.0 or newer)");
eprintln!("\nencrypt/decrypt:\n\tIf a key and/or IV are not provided, they are generated randomly and printed to stderr in order on one line each.");
eprintln!("\tIf the key and/or IV provided's size is lower than the cipher's key/IV size, the rest of the key/IV is padded with 0s. If the size is higher, the extra bytes are ignored.");
eprintln!("\nkeygen:\n\tThe key/iv is printed in the same way as auto-generated keys for the en/decryption modes, but to stdout instead of stderr.");
eprintln!("\nhelp:\n\tPrint this message to stderr then exit with code 0");
/// When writing, a temporary buffer stored in the structure is used. This buffer is **not** cleared after a write, for efficiency reasons. This may leave sensitive information in the buffer after the write operation.
/// The `flush()` implementation *does* clear this buffer.
//#[derive(Debug)]
pubstructSink<W>
{
@ -36,7 +40,7 @@ impl<W> Sink<W>
whereW: Write
{
/// Create a new Chacha Sink stream wrapper
pubfnnew(stream: W,crypter: Crypter)-> Self
#[inline]fnnew(stream: W,crypter: Crypter)-> Self
{
Self{stream,crypter,buffer: SmallVec::new()}
}
@ -55,69 +59,72 @@ where W: Write
/// Consume into the inner stream
pubfninto_inner(self)-> W
#[inline]pubfninto_inner(self)-> W
{
self.stream
}
/// Consume into the inner stream and crypter
pubfninto_parts(self)-> (W,Crypter)
#[inline]pubfninto_parts(self)-> (W,Crypter)
{
(self.stream,self.crypter)
}
/// The crypter of this instance
pubfncrypter(&self)-> &Crypter
#[inline]pubfncrypter(&self)-> &Crypter
{
&self.crypter
}
/// The crypter of this instance
pubfncrypter_mut(&mutself)-> &mutCrypter
#[inline]pubfncrypter_mut(&mutself)-> &mutCrypter
{
&mutself.crypter
}
/// The inner stream
pubfninner(&self)-> &W
#[inline]pubfninner(&self)-> &W
{
&self.stream
}
/// The inner stream
pubfninner_mut(&mutself)-> &mutW
#[inline]pubfninner_mut(&mutself)-> &mutW
{
&mutself.stream
}
}
impl<W: Write>WriteforSink<W>
{
fnwrite(&mutself,buf: &[u8])-> io::Result<usize>{
prog1!{
/// Perform the cipher transform on this input to the inner buffer, returning the number of bytes updated.