Collection of stream cipher algorithms

Overview

RustCrypto: stream ciphers Project Chat dependency status HAZMAT

Collection of stream cipher algorithms 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 Crates.io Documentation MSRV
cfb-mode crates.io Documentation 1.41
cfb8 crates.io Documentation 1.41
chacha20 crates.io Documentation 1.51
ctr crates.io Documentation 1.41
hc-256 crates.io Documentation 1.41
ofb crates.io Documentation 1.41
rabbit crates.io Documentation 1.41
salsa20 crates.io Documentation 1.41

MSRV Policy

Minimum Supported Rust Version (MSRV) can be changed in the future, but it will be done with a minor version bump.

Usage

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

Let's use AES-128-OFB to demonstrate usage of synchronous stream cipher:

use aes::Aes128;
use ofb::Ofb;

// import relevant traits
use ofb::cipher::{NewStreamCipher, SyncStreamCipher};

// OFB mode implementation is generic over block ciphers
// we will create a type alias for convenience
type AesOfb = Ofb<Aes128>;

let key = b"very secret key.";
let iv = b"unique init vect";
let plaintext = b"The quick brown fox jumps over the lazy dog.";

let mut buffer = plaintext.to_vec();

// create cipher instance
let mut cipher = AesOfb::new_var(key, iv)?;

// apply keystream (encrypt)
cipher.apply_keystream(&mut buffer);

// and decrypt it back
AesOfb::new_var(key, iv)?.apply_keystream(&mut buffer);

// stream ciphers can be used with streaming messages
let mut cipher = AesOfb::new_var(key, iv).unwrap();
for chunk in buffer.chunks_mut(3) {
    cipher.apply_keystream(chunk);
}

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.

Comments
  • Ctr128 switch counter u64 to u128

    Ctr128 switch counter u64 to u128

    Start fixing issue #12. Used the static data from issue to create a test case. Have done some randomized testing with original poc without any issues. At one point included wrap around tests to make sure aes-ctr matched output of openssl, see comment.

    opened by koivunej 23
  • Can the salsa20 family be pushed to crates.io?

    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?

    opened by sseemayer 13
  • chacha20: Add full NEON backend.

    chacha20: Add full NEON backend.

    I ported the NEON implementation of ChaCha from Crypto++ (public domain) to Rust with aarch64 intrinsics for a significant performance boost.

    Observed performance changes on an Apple M1 Air:

     name                   chacha-soft ns/iter  chacha-neon ns/iter  diff ns/iter   diff %  speedup
     chacha12_bench1_16b    34 (470 MB/s)        28 (571 MB/s)                  -6  -17.65%   x 1.21
     chacha12_bench2_256b   477 (536 MB/s)       132 (1939 MB/s)              -345  -72.33%   x 3.61
     chacha12_bench3_1kib   1,897 (539 MB/s)     503 (2035 MB/s)            -1,394  -73.48%   x 3.77
     chacha12_bench4_16kib  30,811 (531 MB/s)    7,914 (2070 MB/s)         -22,897  -74.31%   x 3.89
     chacha20_bench1_16b    51 (313 MB/s)        47 (340 MB/s)                  -4   -7.84%   x 1.09
     chacha20_bench2_256b   777 (329 MB/s)       212 (1207 MB/s)              -565  -72.72%   x 3.67
     chacha20_bench3_1kib   3,088 (331 MB/s)     821 (1247 MB/s)            -2,267  -73.41%   x 3.76
     chacha20_bench4_16kib  50,251 (326 MB/s)    13,001 (1260 MB/s)        -37,250  -74.13%   x 3.87
     chacha8_bench1_16b     26 (615 MB/s)        19 (842 MB/s)                  -7  -26.92%   x 1.37
     chacha8_bench2_256b    335 (764 MB/s)       92 (2782 MB/s)               -243  -72.54%   x 3.64
     chacha8_bench3_1kib    1,328 (771 MB/s)     344 (2976 MB/s)              -984  -74.10%   x 3.86
     chacha8_bench4_16kib   21,184 (773 MB/s)    5,371 (3050 MB/s)         -15,813  -74.65%   x 3.94
    

    Closes #287.

    I’m not entirely certain I’ve got the flag/feature/cpuid token stuff right, and would appreciate any guidance about that. At this point the best I’ve got is that it very definitely works on my machine, an M1 Air. Also, no idea how one runs GitHub Actions on a aarch64/NEON platform. QEMU?

    opened by codahale 12
  • chacha20: add SSE2 accelerated variant

    chacha20: add SSE2 accelerated variant

    This implements an SSE2-based variant of ChaCha20.

    I'd also be keen to help adding support for AVX2 and AVX512, but it looks like this may need larger changes (possibly in the salsa20_core crate) to allow for processing multiple blocks simultaneously?

    On my machine (early 2016 MacBook, 1.1GHz M3), the SSE2 variant shows a good improvement over the scalar code, speeding up the benchmarks from 260MB/s to 327MB/s.

    Aside from the core algorithm, here are some of the things I could use feedback on:

    • Gating: I've only implemented compile-time feature detection for now, as that seemed easier. I could potentially add runtime detection as well, if you think that is useful? Additionally, I was considering to pull in cfg-if to simplify the detection logic, but wasn't sure if you wanted to have an additional dependency. Lastly, do we need to be backwards compatible to Rust versions before core::arch got stabilized?

    • Facade: I'm currently switching between the two implementations inside the cipher module, but I wonder if there is a better way? Potentially, the block module could become a facade for block/scalar and block/sse2, which would abstract away the fact that there are multiple implementations?

    • Testing: I've opted to pregenerate random inputs that I use in the tests, which seemed like an okay approach. I was considering pulling in proptest to essentially randomly test the new variant against the scalar implementation, but I wasn't quite sure if you wanted to have it as a dependency.


    Before:

    test bench1_10     ... bench:          48 ns/iter (+/- 22) = 208 MB/s
    test bench2_100    ... bench:         392 ns/iter (+/- 15) = 255 MB/s
    test bench3_1000   ... bench:       4,043 ns/iter (+/- 642) = 247 MB/s
    test bench4_10000  ... bench:      38,370 ns/iter (+/- 1,619) = 260 MB/s
    test bench5_100000 ... bench:     383,558 ns/iter (+/- 9,745) = 260 MB/s
    

    After:

    test bench1_10     ... bench:          40 ns/iter (+/- 3) = 250 MB/s
    test bench2_100    ... bench:         317 ns/iter (+/- 20) = 315 MB/s
    test bench3_1000   ... bench:       3,082 ns/iter (+/- 117) = 324 MB/s
    test bench4_10000  ... bench:      30,681 ns/iter (+/- 808) = 325 MB/s
    test bench5_100000 ... bench:     305,280 ns/iter (+/- 14,035) = 327 MB/s
    
    opened by srijs 12
  • Aes-ctr yields different result openssl

    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
    
    opened by viniul 12
  • chacha20: Use criterion for benchmarking

    chacha20: Use criterion for benchmarking

    ...with the criterion-cycles-per-byte plugin

    This unfortunately means we can no-longer run tests for chacha20 against Rust 1.27.0, since it adds 2018 edition dev-dependencies. However, we can still confirm release builds against this version work.

    As we're starting to reach a microoptimization stage, I think criterion will be extremely helpful in determining if our microoptimizations are actually improving performance.

    Currently I'm getting between 5.1 - 5.8 cpb across the tests on a Kaby Lake i7. Curiously -Ctarget-cpu=native seems to negatively impact performance. I'm not seeing much difference between the software and SSE2 backends: +5% on the chacha20/apply_keystream/1024 benchmark, negligible on the others (i.e. +1-2%)

    opened by tarcieri 9
  • Ctr32

    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.

    opened by tarcieri 9
  • [WIP] Fix ChaCha20 seeking

    [WIP] Fix ChaCha20 seeking

    This migrates the tests used by the chacha20 crate to use the new_sync_test! macro.

    The "core" tests are now passing, however it appears the existing seeking implementation is broken:

        running 5 tests
        test chacha20_offsets ... ignored
        test chacha20_legacy_seek ... FAILED
        test chacha20_seek ... FAILED
        test chacha20_core ... ok
        test chacha20_legacy_core ... ok
    
        failures:
    
        ---- chacha20_legacy_seek stdout ----
        thread 'chacha20_legacy_seek' panicked at 'slice index starts at 65 but ends at 64', src/libcore/slice/mod.rs:2575:5
    

    Now that the bug is captured, I think I have an idea of an interesting way to fix it...

    opened by tarcieri 9
  • .travis.yml: Test no_std platform, WASM, all feature combos, --release

    .travis.yml: Test no_std platform, WASM, all feature combos, --release

    This uses a CI config more like the one at:

    https://github.com/RustCrypt/signatures

    It runs all tests with the --release flag to ensure that crates aren't broken by release-dependent functionality after being tested in debug mode (we can add back debug mode testing if it's helpful, but it doesn't look like we have anything presently gated on debug builds). I now see @newpavlov also requested it on #20.

    It also tests on a no_std platform (thumbv7) which @newpavlov requested in #18.

    Finally, it tests with --all-features. This should uncover some lingering breakages (it won't in this commit, but it appears some of the conditional compilation is incorrectly gated and I intend to fix it in a follow-up commit).

    opened by tarcieri 9
  • chacha20: SIGSEGV in CI

    chacha20: SIGSEGV in CI

    See: https://github.com/RustCrypto/stream-ciphers/runs/7970722385?check_suite_focus=true#step:8:28

    It occurred running the integration tests in the autodetect CI job for this dependabot PR to bump cpufeatures from 0.2.3 to 0.2.4, so that's possibly implicated: https://github.com/RustCrypto/stream-ciphers/pull/303

    cc @newpavlov @str4d

    security 
    opened by tarcieri 8
  • `chacha20`: Process 4 blocks at a time in AVX2 backend

    `chacha20`: Process 4 blocks at a time in AVX2 backend

    We switch to a 4-block buffer for the combined SSE2 / AVX2 backend, which allows the AVX2 backend to process them together, while the SSE2 backend continues to process one block at a time.

    The AVX2 backend is refactored to enable interleaving the instructions per pair of blocks, for better ILP.

    Closes #262.

    opened by str4d 7
  • Add HC-128 and Fix HC-256

    Add HC-128 and Fix HC-256

    #219 This implementation of HC-128 does not yet have the test vectors. HC-256 was using a table size of 2660 instead of 2560, this does not cause issue with the generated key stream, but slightly lengthens the initialization time. The function h2 in HC-256 used self.ptable instead of self.qtable, this means that it does not apply linear masking when the stream is using h2. For inputs that never get output from h2 it gives the correct results, but once h2 is in use the values are incorrect.

    opened by quentin-k 1
  • salsa20: performance optimizations (e.g. SIMD)

    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

    • [x] chacha20 crate
    • [x] 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
      • [x] SSE2 (#61)
      • [x] AVX2 (#83, #87)
    • [ ] salsa20
      • [ ] SSE2
      • [ ] AVX2

    Other CPU architectures

    • ARM?
    enhancement help wanted 
    opened by tarcieri 1
Owner
Rust Crypto
Cryptographic algorithms written in pure Rust
Rust Crypto
AEGIS cipher for Rust.

AEGIS for Rust This is a Rust implementation of the AEGIS authenticated cipher, ported from the Zig standard library. AEGIS is extremely fast on CPUs

Frank Denis 12 Nov 24, 2022
ROT Cipher implementation in rust, supports rot1 to rot25.

rotcipher-rs ROT Cipher implementation in rust, supports rot1 to rot25. Supported ROT ciphers ROT1 up to ROT25, it is also possible to make custom ROT

null 0 Sep 7, 2022
Bessie - an authenticated, chunked cipher based on BLAKE3

Bessie Bessie is an authenticated, chunked cipher based on BLAKE3. Right now it's in the early design stages. See design.md. Although the Bessie ciphe

Jack O'Connor 12 Dec 9, 2022
A collection of algorithms that can do join between two parties while preserving the privacy of keys on which the join happens

Private-ID Private-ID is a collection of algorithms to match records between two parties, while preserving the privacy of these records. We present tw

Meta Research 169 Dec 5, 2022
A general solution for commonly used crypt in rust, collection of cryptography-related traits and algorithms.

Crypto-rs A general solution for commonly used crypt in rust, collection of cryptography-related traits and algorithms. This is a Rust implementation

houseme 4 Nov 28, 2022
hello-world geyser plugin to stream accounts and transactions from a solana node

src/lib.rs: entrypoint src/plugin.rs: main plugin code to run: cargo build && solana-test-validator -r --geyser-plugin-config config.json note: make s

null 4 Nov 18, 2022
A vertically scalable stream processing framework focusing on low latency, helping you scale and consume financial data feeds.

DragonflyBot A vertically scalable stream processing framework focusing on low latency, helping you scale and consume financial data feeds. Design The

null 17 Jul 12, 2023
A (mostly) pure-Rust implementation of various cryptographic algorithms.

Rust-Crypto A (mostly) pure-Rust implementation of various common cryptographic algorithms. Rust-Crypto seeks to create practical, auditable, pure-Rus

null 1.2k Dec 27, 2022
Port path module (and tests) of nodejs to rust using the same algorithms.

rusty_nodejs_path Port path module (and tests) of nodejs to rust using the same algorithms. crates.io Documents Progress posix path.basename(path[, ex

Yunfei He 10 Sep 25, 2022
Cryptographic signature algorithms: ECDSA, Ed25519

RustCrypto: signatures Support for digital signatures, which provide authentication of data using public-key cryptography. All algorithms reside in th

Rust Crypto 300 Jan 8, 2023
Authenticated Encryption with Associated Data Algorithms: high-level encryption ciphers

RustCrypto: Authenticated Encryption with Associated Data (AEAD) Algorithms Collection of Authenticated Encryption with Associated Data (AEAD) algorit

Rust Crypto 457 Jan 4, 2023
Opendp - The core library of differential privacy algorithms powering the OpenDP Project.

OpenDP The OpenDP Library is a modular collection of statistical algorithms that adhere to the definition of differential privacy. It can be used to b

OpenDP 176 Dec 27, 2022
A Rust Library of China's Standards of Encryption Algorithms (SM2/3/4)

Libsm Libsm is an open source pure rust library of China Cryptographic Algorithm Standards. It is completed by a collaborative effort between the Cryp

CITAHub 149 Dec 23, 2022
Symmetric key-wrapping algorithms

RustCrypto: Key Wrapping Functions Collection of symmetric Key Wrapping Functions (KW) written in pure Rust. About "Key Wrapping" describes symmetric

Rust Crypto 5 Nov 28, 2022
A Rust Implementation of China's Standards of Encryption Algorithms(SM2/SM3/SM4)

gm-rs A Pure Rust High-Performance Implementation of China's Standards of Encryption Algorithms(SM2/SM3/SM4) Usage Add this to your Cargo.toml: [depen

null 2 Oct 27, 2022
Chargo is a tool for file encryption/decryption. It's based on Argon2 and ChaCha20Poly1305 algorithms.

| Documentation Chargo is a tool for file encryption/decryption with password. It's based on Argon2 and ChaCha20Poly1305 algorithms. From arg2u with ♥

Airat Galiullin 7 Jan 1, 2023
A template for writing CMSIS-Pack flash algorithms in Rust

Flash Algorithm Template This is a flash algorithm template for writing CMSIS-Pack flash algorithms in Rust. It can be used to generate new flash algo

probe.rs 5 Feb 11, 2023
🧩Creating a blockchain wallet and integrating a couple of cryptographic algorithms to securely save the secrets.🧩

Rust Library For Cryptocurrency Wallet Folder Structure src : contains the source code of the library examples : contains some examples of the library

rstkey 3 Aug 12, 2024
Collection of cryptographic hash functions written in pure Rust

RustCrypto: hashes Collection of cryptographic hash functions written in pure Rust. All algorithms reside in the separate crates and implemented using

Rust Crypto 1.2k Jan 8, 2023