Git Product home page Git Product logo

stream-ciphers's Introduction

RustCrypto: stream ciphers

Project Chat dependency status Apache2/MIT licensed HAZMAT

Collection of stream ciphers written in pure Rust.

⚠️ Security Warning: Hazmat!

Crates in this repository do not ensure ciphertexts are authentic (i.e. by using a MAC to verify ciphertext integrity), which can lead to serious vulnerabilities if used incorrectly!

Aside from the chacha20 crate, no crates in this repository have yet received any formal cryptographic and security reviews/audits.

USE AT YOUR OWN RISK!

Crates

Name Crate name Crates.io Docs MSRV Security
ChaCha chacha20 crates.io Documentation MSRV 1.65 💚
HC-256 hc-256 crates.io Documentation MSRV 1.65 💛
Rabbit rabbit crates.io Documentation MSRV 1.65 💛
RC4 rc4 crates.io Documentation MSRV 1.65 💔
Salsa20 salsa20 crates.io Documentation MSRV 1.65 💚

Security Level Legend

The following describes the security level ratings associated with each hash function (i.e. algorithms, not the specific implementation):

Heart Description
💚 No known successful attacks
💛 Theoretical break: security lower than claimed
💔 Attack demonstrated in practice: avoid if at all possible

Minimum Supported Rust Version (MSRV) Policy

MSRV bump is considered a breaking change and will be performed only with a minor version bump.

Example

Crates functionality is expressed in terms of traits defined in the cipher crate.

Let's use ChaCha20 to demonstrate usage of synchronous stream cipher:

use chacha20::ChaCha20;
// Import relevant traits
use chacha20::cipher::{KeyIvInit, StreamCipher, StreamCipherSeek};
use hex_literal::hex;

let key = [0x42; 32];
let nonce = [0x24; 12];
let plaintext = hex!("00010203 04050607 08090a0b 0c0d0e0f");
let ciphertext = hex!("e405626e 4f1236b3 670ee428 332ea20e");

// Key and IV must be references to the `GenericArray` type.
// Here we use the `Into` trait to convert arrays into it.
let mut cipher = ChaCha20::new(&key.into(), &nonce.into());

let mut buffer = plaintext.clone();

// apply keystream (encrypt)
cipher.apply_keystream(&mut buffer);
assert_eq!(buffer, ciphertext);

let ciphertext = buffer.clone();

// ChaCha ciphers support seeking
cipher.seek(0u32);

// decrypt ciphertext by applying keystream again
cipher.apply_keystream(&mut buffer);
assert_eq!(buffer, plaintext);

// stream ciphers can be used with streaming messages
cipher.seek(0u32);
for chunk in buffer.chunks_mut(3) {
    cipher.apply_keystream(chunk);
}
assert_eq!(buffer, ciphertext);

License

All crates licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

stream-ciphers's People

Contributors

baloo avatar blackbeam avatar cdong1012 avatar codahale avatar dependabot[bot] avatar dhardy avatar emc2 avatar froydnj avatar joejacobs avatar jpdoyle avatar koivunej avatar magic-akari avatar newpavlov avatar oxarbitrage avatar paulgrandperrin avatar philipr-za avatar soerenmeier avatar srijs avatar sseemayer avatar str4d avatar striezel avatar tarcieri avatar wassasin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

stream-ciphers's Issues

aesni detection fatally fails with rustflags in ~/.cargo/config

I have target-cpu=native set in my rustflags, in ~/.cargo/config:

[target.'cfg(any(windows, unix))']
rustflags = ["-Ctarget-cpu=native"]

This causes aes-ctr to break my projects' build:

   Compiling aes-soft v0.3.3
   Compiling ctr v0.3.2
   Compiling aes-ctr v0.3.0
error[E0463]: can't find crate for `aesni`
  --> /home/faux/.cargo/registry/src/github.com-1ecc6299db9ec823/aes-ctr-0.3.0/src/lib.rs:62:1
   |
62 | extern crate aesni;
   | ^^^^^^^^^^^^^^^^^^^ can't find crate

error: aborting due to previous error

I guess cargo is using different rules to interpret target_feature in Cargo.toml vs. during the build? Note how it is loading the aes-soft crate above.

I tested stable and nightly cargo:
cargo 1.35.0-nightly (6f3e9c367 2019-04-04)
cargo 1.34.0 (6789d8a0a 2019-04-01)

If I remove ~/.cargo/config, and instead set RUSTFLAGS=, everything seems to work as expected:

% RUSTFLAGS=-Ctarget-cpu=native cargo build
...
   Compiling aesni v0.6.0
   Compiling aes-ctr v0.3.0
   Compiling lol v0.1.0 (/var/tmp/faux190416.sciatica/lol)

Add more warnings to crate docs

I have a couple of suggestions that might help people understand the security properties of this library, even if they don't know much about crypto.

  • The subcrates are published on crates.io, but the subcrates don't include the warning of the top-level crate that there has been no formal security review.
  • There is no mention of a common mistake made with stream ciphers: if you reuse the same keystream state to encrypt two different things it almost certainly gives an attacker enough information to break whatever security properties the cryptography is supposed to preserve. If an attacker only has the two ciphertexts they can determine the precise XOR difference between the corresponding plaintexts, and if the attacker knows (or can guess) part of one of the plaintexts they can recover that part of the other message's plaintext.
  • Related to the previous point, there should probably be an explicit link pointing people towards higher level cryptographic functionality that avoids such gotchas.

XChaCha20 unnecessarily limits keystream to 256gb

XChaCha20 can support a full 64-bit keystream for any given nonce, so the MAX_BLOCKS limit of 96-bit-nonce ChaCha20 shouldn't apply.

Technically this wouldn't comply with https://tools.ietf.org/html/draft-arciszewski-xchacha-03 but a cursory glance through the counter handling code makes me think that nothing would actually go wrong -- everything is done with a 64bit counter and split into two 32bit words in the backends.

As a side note, I'm preeeeetty sure that in this implementation 32-bit counter "overflows" would roll over to the next nonce instead of actually leading to nonce reuse. Not great, but #64 may not have been as critical as it looked.

sample code

hedy can you please provide some sample code as to how to encrypt strings i tried everything thanks mate.

salsa20: performance optimizations (e.g. SIMD)

There are two big optimizations we could do on both the chacha20 and salsa20 crates.

Avoid recomputing initial state

EDIT: both crates now have a new method to compute the initial state, and separate apply_keystream / generate methods to compute a block

  • chacha20 crate
  • salsa20 crate

RFC 8439 Section 3 describes caching the initial block state once computed as a performance optimization:

   Each block of ChaCha20 involves 16 move operations and one increment
   operation for loading the state, 80 each of XOR, addition and roll
   operations for the rounds, 16 more add operations and 16 XOR
   operations for protecting the plaintext.  Section 2.3 describes the
   ChaCha block function as "adding the original input words".  This
   implies that before starting the rounds on the ChaCha state, we copy
   it aside, only to add it in later.  This is correct, but we can save
   a few operations if we instead copy the state and do the work on the
   copy.  This way, for the next block you don't need to recreate the
   state, but only to increment the block counter.  This saves
   approximately 5.5% of the cycles.

SIMD support

Both ChaCha20 and Salsa20 are amenable to SIMD optimizations. We should add SIMD optimizations on x86/x86_64 at the very least.

x86/x86_64

  • chacha20
  • salsa20
    • SSE2
    • AVX2

Other CPU architectures

  • ARM?

chacha20: parallel block generation

I think to better optimize the ChaCha20 implementation we might consider switching to something like the BlockCipher trait (or potentially impling it and optionally exposing the raw block function as a BlockCipher), which I think would make it easier to implement a parallel implementation and also provides a common interface for all ChaCha20 block function implementations to conform to, e.g. using the encrypt_blocks method:

https://docs.rs/block-cipher-trait/0.6.2/block_cipher_trait/trait.BlockCipher.html#method.encrypt_blocks

(we could also use a ChaCha20-specific internal trait to avoid the extra dependency if we don't actually want to expose the block-based API publically)

I'd also like to make salsa20-core an optional dependency, allowing the crate to be used solely as a rand-core RNG instead, and if we expose the raw block function, via that API instead.

The chacha20poly1305 crate has much simpler needs than what the full stream-cipher API exposes, since it's doing a fairly straightforward CTR-mode-on-a-buffer operation, which makes it much easier to produce an optimized parallel implementation (with fewer dependencies).

Here's an example of the same idea in the aes-gcm crate:

https://github.com/RustCrypto/AEADs/blob/master/aes-gcm/src/ctr32.rs#L62

chacha20: Add wide (4-block) AVX2 impl

I've been digging into c2-chacha to figure out why its performance is consistently better than chacha20. I think I understand the main difference now: c2-chacha has a "wide" mode where it processes four ChaCha blocks at a time. This requires two sets of registers per state word (since a single 256-bit register only has room for two blocks in parallel), but I guess on modern CPUs there are enough registers that it can handle the increased number of temporaries, and the resulting interleaved instructions seem to parallelise well.

Poly1305

Seems like we have fairly reasonable ChaCha20 crates and Salsa20 crates now, and I see newpavlov snagged https://crates.io/crates/poly1305

A poly1305 crate seems like the next logical step, but where should it go? Right now I think the closest fit is https://github.com/RustCrypto/hashes but that seems a little weird

Should we stick it under hashes, or do we need a new toplevel project like universal-hashes or one-time-authenticators?

As it were, I have a mostly complete (but completely untested) Rust implementation of POLYVAL that needs a home and could be located in the same place: https://github.com/miscreant/miscreant.rs/blob/047ae8b3fd68d62eeb1e8510110439ba24473df3/src/polyval.rs

why chacha20 seek only works up to 2^37 while xchacha20 seek works up to 2^62?

Interestingly, while chacha20 seek fails at values > 1<<38, x chacha20 works for the entire range of u64.

use chacha20::cipher::{NewCipher, StreamCipher, StreamCipherSeek};

fn chacha20_seek() {
    let key: chacha20::Key = [0u8; 32].into();
    let nonce: chacha20::Nonce = [0u8; 12].into();
    let mut cipher = chacha20::ChaCha20::new(&key, &nonce);
    cipher.seek(1u64<<37); // 38 fails
    let mut data = [1u8; 1024];
    cipher.apply_keystream(&mut data);
}

fn xchacha20_seek() {
    let key: chacha20::Key = [0u8; 32].into();
    let nonce: chacha20::XNonce = [0u8; 24].into();
    let mut cipher = chacha20::XChaCha20::new(&key, &nonce);
    cipher.seek(1u64<<62);
    let mut data = [1u8; 1024];
    cipher.apply_keystream(&mut data);
}

Why `aes-ctr` crate?

I may be missing something obvious but why does the aes-ctr crate exist? Is there a reason to use aes_ctr::Aes128Ctr over ctr::Ctr128<aes::Aes128>?

The docs state:

This crate will select appropriate implementation at compile time depending on target architecture and enabled target features.

but I though that was already handled by the aes crate.

8-bit cfb-mode support (CFB8), versus only 128-bit (CFB128)

Hi thanks for making the cfb-mode crate, think it will work well for my purposes, so I started converting from openssl, however, I'm seeing different decryption output after the first call as compared to openssl. Reduced to this example:

extern crate aes;
extern crate cfb_mode;

use aes::Aes128;
use cfb_mode::Cfb; 

type Aes128Cfb = Cfb<Aes128>;

fn main() {
    let key = &[17, 72, 215, 19, 142, 61, 79, 230, 54, 89, 66, 160, 184, 156, 232, 31];

    let mut cipher = Aes128Cfb::new_var(key, key).unwrap();
    let mut data = [130];

    cipher.decrypt(&mut data);
    println!("decrypted = {:?}", data);

    let mut data2 = [238, 158, 146];
    cipher.decrypt(&mut data2);
    println!("decrypted2 = {:?}", data2);
}

and for ease of comparison (although I also see the correct output with the openssl 0.7.8 crate), this Python script using PyCrypto decrypting the same data:

from Crypto.Cipher import AES

key=b'\x11H\xd7\x13\x8e=O\xe66YB\xa0\xb8\x9c\xe8\x1f'
iv=key

cipher=AES.new(key, AES.MODE_CFB, iv, segment_size=8)
print "decrypted =",map(ord, cipher.decrypt("\x82")) # expect [3]
print "decrypted2 =",map(ord, cipher.decrypt("\xee\x9e\x92")) # expect [3, 128, 2]

Python (and OpenSSL) decrypts to what I expect:

decrypted = [3]
decrypted2 = [3, 128, 2]

Rust with cfb-mode decrypts the first time ok, but then the second decrypted2 result is different:

decrypted = [3]
decrypted2 = [210, 218, 215]

ctr: block size vs counter size naming

There's an open PR to add support for CTR mode with a 128-bit block size and 32-bit counter: #170.

This PR uses the name Ctr32 but this does not reflect the hardcoded 128-bit block size.

Additionally #75 adds support for natively 128-bit counters, versus the 64-bit counter currently used by the Ctr128 type.

How should we handle these discrepancies? Some suggestions:

  1. Make all implementations completely generic over the block size
  2. Introduce some way of incorporating the hardcoded block size into the name, e.g. Ctr128x32
  3. Give up on incorporating the block size into the name and say all implementations assume a 128-bit block size

out of range for slice of length 16

aes-256-cfb, after run a period of time, got error:
thread 'main' panicked at 'range end index 8444544247700826640 out of range for slice of length 16', /root/.cargo/registry/src/github.com-1ecc6299db9ec823/cfb-mode-0.7.1/src/lib.rs:85:33

New crate: RC6

We can probably add an implementation of the RC6 cipher. Coincidentally their patents expire today (11/28/2019; source, source).

EDIT: My bad... RC6 is actually block cipher but I think it's nice to have an implementation since no vulnerabilities have been discovered is the past...

Make the neon feature available for ChaCha20

Hello,

Today ChaCha20 (and by extension (X)ChaCha20-Poly1305) is painfully slow on arm64 devices.

NEON support was merged last year (#310) but is still not available for use.

Is it possible to publish a new version and update the docs so we can use the NEON version?

I can create a PR for the doc (adding a few explanation on how to enable NEON support) if necessary.

Many thanks!

Can the salsa20 family be pushed to crates.io?

Similar to #2, I am migrating away from rust-crypto and would like to use the Salsa20 and ChaCha20 implementations contained in stream-ciphers. Would it be possible to push them to crates.io?

UB error when running on aarch64

Follow up from librespot-org/librespot#239
Seem to be having Bus errors running on aarch64 (32bit kernel).

Tested with this snippet.

extern crate aes_ctr;

use aes_ctr::stream_cipher::generic_array::GenericArray;
use aes_ctr::stream_cipher::{NewFixStreamCipher, StreamCipherCore};
use aes_ctr::Aes128Ctr;

const AUDIO_AESIV: [u8; 16] = [
    0x72, 0xe0, 0x67, 0xfb, 0xdd, 0xcb, 0xcf, 0x77, 0xeb, 0xe8, 0xbc, 0x64, 0x3f, 0x63, 0x0d, 0x93,
];

#[inline(never)]
fn new_cipher(key: &[u8]) -> Aes128Ctr {
    // println!("key {:?}", key);
    // Will not error if this prints
    Aes128Ctr::new(
        GenericArray::from_slice(key),
        GenericArray::from_slice(&AUDIO_AESIV),
    )
}

#[inline(never)]
fn encrypt(cipher: &mut Aes128Ctr) -> [u8; 10] {
    let mut data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    cipher.apply_keystream(&mut data);
    data
}

fn main() {
    let mut cipher = new_cipher(b"0123456789abcdef");
    let data = encrypt(&mut cipher);
    println!("{:?}", data);
}

Starting program: /home/ash/test_stream_ciphers
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/arm-linux-gnueabihf/libthread_db.so.1".

Program received signal SIGBUS, Bus error.
0xaaab1d64 in _$LT$ctr..Ctr128$LT$C$GT$$u20$as$u20$stream_cipher..NewFixStreamCipher$GT$::new::h1cd20b0be966ea7c ()
(gdb) bt
#0  0xaaab1d64 in _$LT$ctr..Ctr128$LT$C$GT$$u20$as$u20$stream_cipher..NewFixStreamCipher$GT$::new::h1cd20b0be966ea7c ()
#1  0xaaab224c in test_stream_ciphers::new_cipher::h315560409baa366e ()
#2  0xaaab22e4 in test_stream_ciphers::main::h5cdcb843d2f82ea6 ()
#3  0xaaab1610 in std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hb4152d57b6ff1750 ()
#4  0xaaab7984 in {{closure}} () at libstd/rt.rs:59
#5  std::panicking::try::do_call::h97d304993e5c755b () at libstd/panicking.rs:310
#6  0xaaac8ba0 in __rust_maybe_catch_panic () at libpanic_unwind/lib.rs:105
#7  0xaaab6bc4 in try<i32,closure> () at libstd/panicking.rs:289
#8  catch_unwind<closure,i32> () at libstd/panic.rs:392
#9  std::rt::lang_start_internal::h025c75f9b8aa9041 () at libstd/rt.rs:58
#10 0xaaab2388 in main ()
(gdb)

Cross compiled with:

/src# rustup show
Default host: x86_64-unknown-linux-gnu

installed targets for active toolchain
--------------------------------------

aarch64-unknown-linux-gnu
arm-unknown-linux-gnueabi
arm-unknown-linux-gnueabihf
i686-unknown-linux-gnu
x86_64-unknown-linux-gnu

active toolchain
----------------

stable-x86_64-unknown-linux-gnu (default)
rustc 1.29.2 (17a9dc751 2018-10-05)

root@3cd916fde064:/src# arm-linux-gnueabihf-gcc --version
arm-linux-gnueabihf-gcc (Debian 6.3.0-18) 6.3.0 20170516
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Ctr32

There are several constructions based on stream ciphers that use a 32-bit counter:

  • AES-GCM
  • AES-GCM-SIV
  • ChaCha20Poly1305 (IETF version, but we can implement the "legacy" version with one too)

I was thinking it would be interesting to have a Ctr32 type which is generic around the block size. If so, I could impl the ChaCha20 and Salsa20 core functions as a sort of 512-bit wide pseudo-BlockCipher, which would let us have reusable stream cipher buffer management and seeking across all three of the aforementioned ciphers. Note that pulling this off would also need for it to be generic around endianness, as I believe AES-GCM needs a big endian counter and AES-GCM-SIV and ChaCha20Poly1305 need a little endian counter.

If we had that, it would also eliminate the need for the salsa20-core crate, or rather, we could merge it into the salsa20 crate.

Notably right now the only other ctr type, Ctr128, is specialized to a 128-bit block size. This actually seems ok to me, as it seems rather unusual to use a 128-bit counter with anything other than a 128-bit block size.

chacha20: avoid panic on counter overflow

To avoid repeating the keystream on counter overflow, #68 added an assertion that the counter value is less than chacha20::MAX_BLOCKS.

Ideally SalsaFamilyCipher::block can be changed to use a fallible API, so instead of panicking it returns an error when the counter overflows.

`chacha20` is missing `.zeroize()` for the SIMD backends

I've noticed that #333 is missing zeroize for the SIMD backends, and that the zeroize crate seems to support SIMD registers. There are 2 ways that I can identify for incorporating zeroize. Both methods, however, would require the MSRV to be increased to 1.60.

Method 1

The first method is kind of easy, as it requires a relatively small amount of code, but it is a little inefficient. Basically, .zeroize() could be called on the SIMD results arrays, as well as the state arrays after generating results.

Pros:

  • it should successfully zeroize the SIMD registers

Cons:

  • every time the SIMD backend generates either a block or PAR_BLOCKS blocks of output, it will need to zeroize the SIMD registers

Method 2

This would involve a little bit of a reimplementation of some features that chacha20 previously had (persisting Core structs via autodetect.rs and backend.rs). The persisting Core structs can provide a few benefits:

  • they should only be initialized once
  • .zeroize() could only be applied once to the SIMD registers, instead of every time the Core generates results
  • the RNG shouldn't need unsafe fn generate(&mut self, dest_ptr: *mut u8, num_blocks: usize) to achieve a performance that is comparable with .apply_keystream() on AVX2... unless .apply_keystream()'s performance also increases by 5-7%. The RNG could still benefit from using a pointer though.

Cons:

  • a little more code would be required

Here's a link to v0.8.1 for reference. I will need it if I will be adding the functionality back:
https://github.com/RustCrypto/stream-ciphers/blob/338c078d731692fba3b8256e45de2c3e334d46d8/chacha20/src/backend.rs

ChaCha20 counter overflow leading to nonce reuse

Hi!

What's the best place to discuss possible security issues regarding the code in this repo?

(FWIW I'm not sure it's a big issue, but I want to be sure to go through the proper channels :))

Remove circular dependencies on `aes` crate

Several crates in this repo use the aes crate as a dev-dependency.

The aes crate lists ctr in its (hard) dependencies section now.

This means that upgrading the cipher crate right now involves at least a temporary breakage. Here are some example PRs where this has happened:

#224 #225 #226 #227

There are at least two different ways this could be addressed, I think:

  1. Migrate the SIMD CTR implementation from the aes crate into the ctr crate, since it's not ctr-specific
  2. Use a different "example" block cipher as a dev-dependency

Aes-ctr yields different result openssl

When I provide a certain combination of key, iv and data, I get different results from the openssl and the aes-ctr encryption.

In particular, I used this wrapper:

pub extern crate generic_array;
extern crate crypto;
use aes_ctr::Aes128Ctr;
use aes_ctr::Aes192Ctr;
use aes_ctr::Aes256Ctr;
use aes_ctr::stream_cipher::generic_array::GenericArray;
use aes_ctr::stream_cipher::{
    NewStreamCipher, SyncStreamCipher, SyncStreamCipherSeek
};

use openssl::symm;

use std::fs;

use std::env;

//use crypto::aes::{ctr, KeySize};
//use crypto::symmetriccipher::SynchronousStreamCipher;
use crypto::aes;

use std::vec::from_elem;

fn transform_data(key_size: usize,nonce_size: usize, data: &[u8])
-> Result<(Vec<u8>,Vec<u8>, Vec<u8>),&'static str>
{
    if data.len() < key_size+nonce_size+1 {
        return Err("Data too short");
    }
    let key = data[0..key_size].to_owned();
    let nonce = data[key_size..key_size+nonce_size].to_owned();
    let mut crypto_data = data[key_size+nonce_size..].to_owned();
    Ok((key,nonce,crypto_data))
}

macro_rules! generate_aes_call {
    (128,$key_generic:expr,$nonce_generic:expr) => {
        Aes128Ctr::new(&$key_generic, &$nonce_generic);
    };
    (256,$key_generic:expr,$nonce_generic:expr) => {
        Aes256Ctr::new(&$key_generic, &$nonce_generic);
    }
}

macro_rules! generate_aes_openssl {
    (128) => {
        openssl::symm::Cipher::aes_128_ctr();
    };
    (256) => {
        openssl::symm::Cipher::aes_256_ctr();
    }
}

macro_rules! generate_crypto_aes_call {
    (128,$key:expr,$nonce:expr) => {
        crypto::aes::ctr(crypto::aes::KeySize::KeySize128, $key.as_slice(), $nonce.as_slice());
    };
    (256,$key:expr,$nonce:expr) => {
        crypto::aes::ctr(crypto::aes::KeySize::KeySize256, $key.as_slice(), $nonce.as_slice());
    };
}

fn main(){
    let args: Vec<String> = env::args().collect();
    let data = &fs::read(&args[1]).unwrap();
    let (key, nonce, crypto_data) = match(transform_data((128 / 8), 16, data)){
                Ok((key,nonce,crypto_data)) => (key,nonce,crypto_data),
                Err(err_str) => {println!("Err: {:?}", err_str); return}
            };
    let original_data = crypto_data.to_owned();
    let mut aes_ctr_crypto_data = crypto_data.to_owned();
    let key_generic = GenericArray::from_slice(&key);
    let nonce_generic = GenericArray::from_slice(&nonce);

    let mut cipher = Aes128Ctr::new(&key_generic, &nonce_generic);
    // apply keystream (encrypt)
    cipher.apply_keystream(&mut aes_ctr_crypto_data);
    println!("Keysize: {:?}", 128);
    let openssl_cipher = generate_aes_openssl!(128);
    let openssl_ciphertext = openssl::symm::encrypt(
                        openssl_cipher,
                        &key,
                        Some(&nonce),
                        &original_data).unwrap();
    let mut cipher_crypto_aes = generate_crypto_aes_call!(128,key,nonce);
    let mut output_crypto_aes: Vec<u8> = vec![0; original_data.len()];
    cipher_crypto_aes.process(&original_data, output_crypto_aes.as_mut_slice());
    println!("Key: {:?}",key);
    println!("Nonce: {:?}", nonce);
    println!("Key generic array: {:?}", key_generic);
    println!("Nonce generic array: {:?}", nonce_generic);
    println!("Data:\naes-ctr: {:?}\nopenssl: {:?}\ncrypto::aes: {:?}\noriginal_text: {:?}",aes_ctr_crypto_data,openssl_ciphertext,output_crypto_aes,original_data);
    assert_eq!(output_crypto_aes,openssl_ciphertext,"Opensll and rust::crypto::aes not equal!");
    assert_eq!(crypto_data,openssl_ciphertext, "Openssl and aes_ctr not equal");
    println!("All equal\n");
    // seek to the keystream beginning and apply it again to the `data` (decrypt)
    cipher.seek(0);
    cipher.apply_keystream(&mut aes_ctr_crypto_data);
    assert_eq!(aes_ctr_crypto_data, original_data, "Decrypted data not equal");
}

And caledl it like so:
cargo run debug.crash
(file is attached), which reveals the following difference in encryption results between openssl and aes-ctr is revealed:

aes-ctr: [108, 253, 73, 159, 41, 43, 94, 79, 15, 121, 128, 186, 135, 246, 194, 87, 210, 245, 143, 26, 252, 148, 40, 251, 221, 123, 151, 112, 198, 148, 194, 86, 112, 124, 212, 82, 16, 202, 32, 36, 21, 69, 127, 56, 201, 111, 252, 108, 123, 166, 116, 191, 155, 79, 254, 41, 214, 68, 210, 96, 235, 239, 143, 101, 236, 141, 110, 227, 88, 157, 94, 39, 237, 104, 244, 167, 255, 124, 114, 238, 9, 185, 155, 13, 123, 34, 248, 104, 110, 165, 81, 34, 14, 84, 153, 97, 166, 34, 52, 106, 75, 253]
openssl: [108, 253, 73, 159, 41, 43, 94, 79, 15, 121, 128, 186, 135, 246, 194, 87, 27, 222, 233, 216, 2, 74, 106, 79, 70, 239, 105, 93, 125, 169, 59, 243, 171, 225, 15, 165, 102, 87, 79, 1, 31, 125, 151, 72, 199, 184, 71, 14, 69, 200, 13, 5, 171, 26, 106, 86, 129, 55, 254, 219, 166, 51, 34, 105, 154, 166, 12, 108, 239, 100, 153, 125, 229, 136, 86, 30, 233, 149, 169, 77, 154, 25, 226, 107, 205, 53, 144, 233, 62, 225, 237, 218, 7, 246, 61, 146, 31, 189, 212, 178, 104, 88]

Oddly enough, if I change the nonce in the file, openssl and aes-ctr produce the same result. Is this a bug or am I misusing the library?

Attached is a zip to easily reproduce this and the input the triggers the difference:
poc.zip
Run like so:

cd poc/
cargo run debug.crash

Publish on crates.io?

Hello, we're currently migrating from rust-crypto crate because of wasm-build related problems (see issue emeraldpay/emerald-vault#286) and the decomposition you've done looks very promising in terms of integration into wasm-capable project.

What's the current state of stream-ciphers and when do you expect it to be possible to post it on crates.io?

Add more test vectors to salsa20 ?

The salsa20 implementation has a few test vectors here, some of them seems to be from here.

I was wondering if this implementation should add some more test vectors in order to lock the functionality against future changes and have more coverage.

I am pretty sure this implementation will pass all these test vectors but will be nice to confirm it:

These are the only test vectors from some sort of reliable source that i was able to find online for salsa20.

This is a lot of vectors, an option will be to just implement some here instead. Another approach taken here is a shell script that generate the tests. The simpler one will be to just add an ecrypt module inside the tests, hardcode the vectors and run them.

I could create a PR for this if there is some interest.

SyncStreamCipherSeek::seek overflow behavior not documented

SyncStreamCipherSeek::seek accepts a u64 and doesn't return a result. API docs should mention that ciphers with periods shorter than 2^64 bytes (e.g. Ietf ChaCha) will panic on overflow. An alternative Result<> interface may also be useful.

salsa20-core: warnings for `word_idx`

cc @emc2 @sseemayer

There's presently a warning for salsa20-core:

https://github.com/RustCrypto/stream-ciphers/blob/1dc6af/salsa20-core/src/salsa_family_state.rs#L96

Warning from CI:

https://travis-ci.org/RustCrypto/stream-ciphers/jobs/571061677#L202

warning: value assigned to `word_idx` is never read
  --> salsa20-core/src/salsa_family_state.rs:96:25
   |
96 |                         word_idx = 0;
   |                         ^^^^^^^^
   |
   = note: #[warn(unused_assignments)] on by default
   = help: maybe it is overwritten before being read?

It's unclear to me what the intention was here, or if it can simply be removed. The "maybe it is overwritten before being read" help text has me curious if in the refactor it isn't being preserved somewhere it needed to be read, or if it's now being unconditionally overwritten in a way it shouldn't be.

2018 edition

The minimum Rust version for this repo is presently 1.27.0.

I'd be interested in bumping that up to 1.31.0 and doing a 2018 edition upgrade on all crates.

`current_pos` wrong value on +aes,+ssse3

Hello,

I got an issue with current_pos on Aes256Ctr while compiling with the recommended flags from the README.

To reproduce:

use aes_ctr;
use aes_ctr::stream_cipher::{NewStreamCipher, SyncStreamCipherSeek};

fn main() {
    let key = [0u8; 32];
    let counter_block = [0u8; 16];
    // Prepare the cipher for further operations
    let mut cipher = aes_ctr::Aes256Ctr::new_var(&key, &counter_block).unwrap();
    cipher.seek(16);
    println!("{}", cipher.current_pos());
}
[dependencies]
aes-ctr = "0"
$ cargo version
cargo 1.42.0 (86334295e 2020-01-31)

Here's what I obtain:

$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/test_aes`
16
$ cargo run --release
    Finished release [optimized] target(s) in 0.01s
     Running `target/release/test_aes`
16
$ RUSTFLAGS="-C target-feature=+aes,+ssse3" cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/test_aes`
0
$ RUSTFLAGS="-C target-feature=+aes,+ssse3" cargo run --release
    Finished release [optimized] target(s) in 0.01s
     Running `target/release/test_aes`
0

Am I doing something wrong?

Instead of .seek, I've also tried with:

    let mut temp = [0u8; 0x1000];
    cipher.encrypt(&mut temp);
    println!("{}", cipher.current_pos());

Leading to the same incoherent result.

Regarding rustc flags:

  • +aes,+sse2, +aes, +ssse3 lead to correct results
  • +aes,+ssse3 leads to the result above

version 0.9.0 does not compile on Arduino architecture

Rust support for arduino is lagging and at the moment a number of bugs in the toolchain prevent the use of any rust newer than nightly-2021-01-07.

When I try to build I get the following error:

error: failed to download `inout v0.1.2`

Caused by:
  unable to get packages from source

Caused by:
  failed to parse manifest at `/home/thoth/.cargo/registry/src/github.com-1ecc6299db9ec823/inout-0.1.2/Cargo.toml`

Caused by:
  failed to parse the `edition` key

Caused by:
  this version of Cargo is older than the `2021` edition, and only supports `2015` and `2018` editions.

There are a number of solutions, most of which are out of your hands:

  • use chacha20 version 0.8.1
  • stop using inout or put it behind a feature flag
  • change inout to not use edition 2021
  • fix the various bugs modern in Rust that prevent it from correctly generating code for the Arduino

Aes256Ctr does not seem to actually implement NewFixStreamCipher

While the example from the documentation works for Aes128Ctr, it does not seem to work for Aes256Ctr.

error[E0308]: mismatched types
   --> quinn-proto/src/crypto.rs:467:41
    |
467 |             AesCtr256 => Aes256Ctr::new(key, nonce).apply_keystream(in_out),
    |                                         ^^^ expected struct `aes_ctr::stream_cipher::generic_array::typenum::UInt`, found struct `aes_ctr::stream_cipher::generic_array::typenum::UTerm`
    |
    = note: expected type `&aes_ctr::stream_cipher::generic_array::GenericArray<u8, aes_ctr::stream_cipher::generic_array::typenum::UInt<aes_ctr::stream_cipher::generic_array::typenum::UInt<aes_ctr::stream_cipher::generic_array::typenum::UInt<aes_ctr::stream_cipher::generic_array::typenum::UInt<aes_ctr::stream_cipher::generic_array::typenum::UInt<aes_ctr::stream_cipher::generic_array::typenum::UInt<aes_ctr::stream_cipher::generic_array::typenum::UTerm, aes_ctr::stream_cipher::generic_array::typenum::B1>, aes_ctr::stream_cipher::generic_array::typenum::B0>, aes_ctr::stream_cipher::generic_array::typenum::B0>, aes_ctr::stream_cipher::generic_array::typenum::B0>, aes_ctr::stream_cipher::generic_array::typenum::B0>, aes_ctr::stream_cipher::generic_array::typenum::B0>>`
               found type `&aes_ctr::stream_cipher::generic_array::GenericArray<u8, aes_ctr::stream_cipher::generic_array::typenum::UInt<aes_ctr::stream_cipher::generic_array::typenum::UInt<aes_ctr::stream_cipher::generic_array::typenum::UInt<aes_ctr::stream_cipher::generic_array::typenum::UInt<aes_ctr::stream_cipher::generic_array::typenum::UInt<aes_ctr::stream_cipher::generic_array::typenum::UTerm, aes_ctr::stream_cipher::generic_array::typenum::B1>, aes_ctr::stream_cipher::generic_array::typenum::B0>, aes_ctr::stream_cipher::generic_array::typenum::B0>, aes_ctr::stream_cipher::generic_array::typenum::B0>, aes_ctr::stream_cipher::generic_array::typenum::B0>>`

request for rabbit cipher

Hi, can you add the rabbit encryption method? I am using rabbit in my c++ project using cryptopp, the reason is it is said rabbit is the fastest stream cipher. Thank you for awesome job!

`cargo +nightly bench` doesn't work

Running it locally for me gives:

   Compiling aes v0.3.2
error: cannot find macro `vec!` in this scope
 --> aes-ctr/benches/aes128_ctr.rs:7:1
  |
7 | bench_sync!(aes_ctr::Aes128Ctr);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: cannot find macro `vec!` in this scope
 --> aes-ctr/benches/aes256_ctr.rs:7:1
  |
7 | bench_sync!(aes_ctr::Aes128Ctr);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: cannot find macro `vec!` in this scope
 --> aes-ctr/benches/aes192_ctr.rs:7:1
  |
7 | bench_sync!(aes_ctr::Aes192Ctr);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error[E0412]: cannot find type `Vec` in this scope
 --> aes-ctr/benches/aes256_ctr.rs:7:1
  |
7 | bench_sync!(aes_ctr::Aes128Ctr);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
  |
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error[E0412]: cannot find type `Vec` in this scope
 --> aes-ctr/benches/aes128_ctr.rs:7:1
  |
7 | bench_sync!(aes_ctr::Aes128Ctr);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
  |
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error[E0412]: cannot find type `Vec` in this scope
 --> aes-ctr/benches/aes192_ctr.rs:7:1
  |
7 | bench_sync!(aes_ctr::Aes192Ctr);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
  |
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
 --> aes-ctr/benches/aes256_ctr.rs:7:1
  |
7 | bench_sync!(aes_ctr::Aes128Ctr);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `core::marker::Sized` is not implemented for `[u8]`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: all local variables must have a statically known size
  = help: unsized locals are gated as an unstable feature
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
 --> aes-ctr/benches/aes256_ctr.rs:7:1
  |
7 | bench_sync!(aes_ctr::Aes128Ctr);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `core::marker::Sized` is not implemented for `[u8]`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: all local variables must have a statically known size
  = help: unsized locals are gated as an unstable feature
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
 --> aes-ctr/benches/aes256_ctr.rs:7:1
  |
7 | bench_sync!(aes_ctr::Aes128Ctr);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `core::marker::Sized` is not implemented for `[u8]`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: all local variables must have a statically known size
  = help: unsized locals are gated as an unstable feature
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
 --> aes-ctr/benches/aes256_ctr.rs:7:1
  |
7 | bench_sync!(aes_ctr::Aes128Ctr);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `core::marker::Sized` is not implemented for `[u8]`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: all local variables must have a statically known size
  = help: unsized locals are gated as an unstable feature
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
 --> aes-ctr/benches/aes256_ctr.rs:7:1
  |
7 | bench_sync!(aes_ctr::Aes128Ctr);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `core::marker::Sized` is not implemented for `[u8]`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: all local variables must have a statically known size
  = help: unsized locals are gated as an unstable feature
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: aborting due to 7 previous errors

Some errors have detailed explanations: E0277, E0412.
For more information about an error, try `rustc --explain E0277`.
error: Could not compile `aes-ctr`.
warning: build failed, waiting for other jobs to finish...
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
 --> aes-ctr/benches/aes192_ctr.rs:7:1
  |
7 | bench_sync!(aes_ctr::Aes192Ctr);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `core::marker::Sized` is not implemented for `[u8]`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: all local variables must have a statically known size
  = help: unsized locals are gated as an unstable feature
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
 --> aes-ctr/benches/aes128_ctr.rs:7:1
  |
7 | bench_sync!(aes_ctr::Aes128Ctr);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `core::marker::Sized` is not implemented for `[u8]`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: all local variables must have a statically known size
  = help: unsized locals are gated as an unstable feature
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
 --> aes-ctr/benches/aes192_ctr.rs:7:1
  |
7 | bench_sync!(aes_ctr::Aes192Ctr);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `core::marker::Sized` is not implemented for `[u8]`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: all local variables must have a statically known size
  = help: unsized locals are gated as an unstable feature
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
 --> aes-ctr/benches/aes192_ctr.rs:7:1
  |
7 | bench_sync!(aes_ctr::Aes192Ctr);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `core::marker::Sized` is not implemented for `[u8]`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: all local variables must have a statically known size
  = help: unsized locals are gated as an unstable feature
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
 --> aes-ctr/benches/aes128_ctr.rs:7:1
  |
7 | bench_sync!(aes_ctr::Aes128Ctr);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `core::marker::Sized` is not implemented for `[u8]`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: all local variables must have a statically known size
  = help: unsized locals are gated as an unstable feature
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
 --> aes-ctr/benches/aes128_ctr.rs:7:1
  |
7 | bench_sync!(aes_ctr::Aes128Ctr);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `core::marker::Sized` is not implemented for `[u8]`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: all local variables must have a statically known size
  = help: unsized locals are gated as an unstable feature
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
 --> aes-ctr/benches/aes192_ctr.rs:7:1
  |
7 | bench_sync!(aes_ctr::Aes192Ctr);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time

  |
  = help: the trait `core::marker::Sized` is not implemented for `[u8]`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: all local variables must have a statically known size
  = help: unsized locals are gated as an unstable feature
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
 --> aes-ctr/benches/aes192_ctr.rs:7:1
  |
7 | bench_sync!(aes_ctr::Aes192Ctr);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `core::marker::Sized` is not implemented for `[u8]`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: all local variables must have a statically known size
  = help: unsized locals are gated as an unstable feature
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
 --> aes-ctr/benches/aes128_ctr.rs:7:1
  |
7 | bench_sync!(aes_ctr::Aes128Ctr);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `core::marker::Sized` is not implemented for `[u8]`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: all local variables must have a statically known size
  = help: unsized locals are gated as an unstable feature
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: aborting due to 7 previous errors

Some errors have detailed explanations: E0277, E0412.
For more information about an error, try `rustc --explain E0277`.
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
 --> aes-ctr/benches/aes128_ctr.rs:7:1
  |
7 | bench_sync!(aes_ctr::Aes128Ctr);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `core::marker::Sized` is not implemented for `[u8]`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: all local variables must have a statically known size
  = help: unsized locals are gated as an unstable feature
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: aborting due to 7 previous errors

Unify buffering logic between chacha20, salsa20, and ctr

All three of these crates use highly similar (copypasta) buffering logic:

Original ctr code:

Derived chacha20 and salsa20 code:

The main problem is the ctr is presently specialized to Ctr128 and intended to operate in conjunction with a block cipher, whereas it'd be nice if ChaCha20 and Salsa20 took an integer (32-bit and 64-bit respectively) used to compute the block, but reused the same buffering logic as Ctr128.

ChaCha20 could also benefit from parallel block computation via its AVX2 backend.

chacha20: 64-bit counter support

The ChaCha20Legacy construction, i.e. the djb variant, is supposed to use a 64-bit counter but currently uses a 32-bit counter because it shares its core implementation with the IETF construction which uses a 32-bit counter.

This results in a counter overflow after generating 256 GiB of keystream. Compatible implementations are able to generate larger keystreams.

I'm not sure how much of a practical concern this actually is, but it did come up in discussions here: rust-random/rand#934 (comment)

We can probably make the counter type generic between u32/u64 in the core implementation if need be.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.