Rust-crypto and Tiny-Keccak, two common cryptography libraries implemented by Rust, are introduced.

rust-crypto

The cryptography library implemented by Rust contains algorithms commonly used in cryptography, such as symmetric cryptography, public key cryptography, one-way hash function, message authentication code, digital signature, and random number generator. Currently, the following algorithms are supported:

Name Description
AES Advanced Encryption Standard is the most common symmetric Encryption algorithm
Bcrypt An algorithm specifically designed for password storage, based on Blowfish encryption algorithm, is a cross-platform file encryption tool
BLAKE2b The 64-bit version of BLAKE, which can generate arbitrarily long hashes of up to 512 bits
BLAKE2s The 32-bit version of BLAKE, which can generate arbitrary length hashes of up to 256 bits
Blowfish Blowfish is a 64-bit grouping and variable key length symmetric key block cipher algorithm
ChaCha20 ChaCha stream ciphers, improved versions of Salsa ciphers, are more resistant to cryptanalysis attacks. “20” indicates that the algorithm has 20 rounds of encryption
Curve25519 Curve25519 is the highest level of Diffie-Hellman function available for a wide range of scenarios, designed by Professor Daniel J. Bernstein
ECB, CBC, and CTR block cipher modes ECB mode, CBC mode, CTR mode (block cipher mode)
Ed25519 Ed25519 is a digital signature algorithm with high performance of signature and verification
Fortuna A cryptographically secure random number generator suitable for long life cycle tasks
Ghash An implementaiton of GHASH as used in GCM
HC128 Hc-128 algorithm is a simplified version of HC-256 algorithm, which is one of the 7 sequence cryptographic algorithms that were finally won by the European E STREAM project. Hc-128 consists of two parts: initialization algorithm and key stream generation algorithm. It is a table-driven algorithm suitable for software implementation.
HMAC Hashed Message Authentication Code
MD5 Message-digest Algorithm 5 (MESSage-digest Algorithm 5) is a hash function widely used in computer security field to protect Message integrity
PBKDF2 Password-Based Key Derivation Function 2
PKCS padding for CBC block cipher mode Block password CBC mode PKCS padded
Poly1305 A cryptographic message authentication code (MAC) created by Daniel J. Bernstein
RC4 A symmetric encryption algorithm, a cluster of variable key length stream encryption algorithms designed in 1987 by Ronald Rivest, the leading member of the RSA Trio
RIPEMD-160 Primitives Evaluation Message Digest RACE Integrity Primitives Evaluation Message Digest
Salsa20 and XSalsa20 Salsa20 is a stream cipher algorithm based on hash function proposed by Daniel J.Bernstein
Scrypt A Memory-dependent Hash algorithm (used in blockchain)
Sha1 Secure Hash Algorithm 1
Sha2 (All fixed output size variants) SHA-2 (Secure Hash Algorithm 2)
Sha3 SHA-3 (Secure Hash Algorithm 3)
Sosemanuk A software-based stream cryptography algorithm
Whirlpool A hash algorithm based on block cipher
Code Example 1
/ /! SHA3-256 sample
extern crate crypto;
extern crate rustc_hex;

use self::crypto::digest::Digest;
use self::crypto::sha3::Sha3;
use rustc_hex::{ToHex,FromHex};

fn main() {
    // create a SHA3-256 object
    let mut hasher = Sha3::sha3_256();

    // write input message
    hasher.input_str("hello world");

    // read hash digest
    let hex = hasher.result_str();
    let res=hex.from_hex().unwrap();
    let res=res.as_slice();

    let expected: &[u8] = & [0x64.0x4b.0xcc.0x7e.0x56.0x43.0x73.0x04.0x09.0x99.0xaa.0xc8.0x9e.0x76.0x22.0xf3.0xca.0x71.0xfb.0xa1.0xd9.0x72.0xfd.0x94.0xa3.0x1c.0x3b.0xfb.0xf2.0x4e.0x39.0x38
    ];

    assert_eq!(res,expected);
}

Copy the code
Code Example 2
/ /! AES256 CBC, CTR Mode Encrypt Decrypt Demo
use std::str;
use crypto::{symmetriccipher,buffer,aes,blockmodes};
use crypto::buffer::{ReadBuffer,WriteBuffer,BufferResult};
use crypto::aessafe::*;
use crypto::blockmodes::*;
use crypto::symmetriccipher::*;
use rand::{Rng,OsRng};

pub fn aes_cbc_mode() {let message="Hello World!";

    let mut key:[u8;32] = [0;32];
    let mut iv:[u8;16] = [0;16];

    // In a real program, the key and iv may be determined
    // using some other mechanism. If a password is to be used
    // as a key, an algorithm like PBKDF2, Bcrypt, or Scrypt (all
    // supported by Rust-Crypto!) would be a good choice to derive
    // a password. For the purposes of this example, the key and
    // iv are just random values.
    let mut rng=OsRng::new().ok().unwrap();
    rng.fill_bytes(&mut key);
    rng.fill_bytes(&mut iv);

    let encrypted_data=aes256_cbc_encrypt(message.as_bytes(),&key,&iv).ok().unwrap();
    letdecrypted_data=aes256_cbc_decrypt(&encrypted_data[..] ,&key,&iv).ok().unwrap();let crypt_message=str::from_utf8(decrypted_data.as_slice()).unwrap();

    assert_eq!(message,crypt_message);
    println!("{}",crypt_message);
}

// Encrypt a buffer with the given key and iv using AES-256/CBC/Pkcs encryption.
fn aes256_cbc_encrypt(data: &[u8],key: &[u8], iv: &[u8] - >Result<Vec<u8>,symmetriccipher::SymmetricCipherError>{
    let mut encryptor=aes::cbc_encryptor(
        aes::KeySize::KeySize256,
        key,
        iv,
        blockmodes::PkcsPadding);

    let mut final_result=Vec: : <u8>::new();
    let mut read_buffer=buffer::RefReadBuffer::new(data);
    let mut buffer=[0;4096];
    let mut write_buffer=buffer::RefWriteBuffer::new(&mut buffer);

    loop{
        let result=try!(encryptor.encrypt(&mut read_buffer,&mut write_buffer,true));

        final_result.extend(write_buffer.take_read_buffer().take_remaining().iter().map(|&i| i));

        match result {
            BufferResult::BufferUnderflow=>break,
            BufferResult::BufferOverflow=>{},
        }
    }

    Ok(final_result)
}

// Decrypts a buffer with the given key and iv using AES-256/CBC/Pkcs encryption.
fn aes256_cbc_decrypt(encrypted_data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>, symmetriccipher::SymmetricCipherError> {
    let mut decryptor = aes::cbc_decryptor(
        aes::KeySize::KeySize256,
        key,
        iv,
        blockmodes::PkcsPadding);

    let mut final_result = Vec: : <u8>::new();
    let mut read_buffer = buffer::RefReadBuffer::new(encrypted_data);
    let mut buffer = [0; 4096];
    let mut write_buffer = buffer::RefWriteBuffer::new(&mut buffer);

    loop {
        let result = try!(decryptor.decrypt(&mut read_buffer, &mut write_buffer, true));
        final_result.extend(write_buffer.take_read_buffer().take_remaining().iter().map(|&i| i));
        match result {
            BufferResult::BufferUnderflow => break,
            BufferResult::BufferOverflow => { }
        }
    }

    Ok(final_result)
}

pub fn aes_ctr_mode() {let message="Hello World! AES CTR MODE.";

    let mut key:[u8;32] = [0;32];
    let mut iv:[u8;16] = [0;16];

    let mut rng=OsRng::new().ok().unwrap();
    rng.fill_bytes(&mut key);
    rng.fill_bytes(&mut iv);

    let encrypted_data=aes256_ctr_encrypt(message.as_bytes(),&key,&iv).ok().unwrap();
    letdecrypted_data=aes256_ctr_decrypt(&encrypted_data[..] ,&key,&iv).ok().unwrap();let crypt_message=str::from_utf8(decrypted_data.as_slice()).unwrap();

    assert_eq!(message,crypt_message);
    println!("{}",crypt_message);
}

fn aes256_ctr_encrypt(data: &[u8],key: &[u8],iv: &[u8] - >Result<Vec<u8>,symmetriccipher::SymmetricCipherError>{
    let mut final_result=Vec: : <u8>::new();
    let mut read_buffer=buffer::RefReadBuffer::new(data);
    let mut buffer=[0;4096];
    let mut write_buffer=buffer::RefWriteBuffer::new(&mut buffer);

    let mut encoder=CtrMode::new(AesSafe256Encryptor::new(key),iv.to_vec());
    encoder.encrypt(&mut read_buffer,&mut write_buffer,true)? ; final_result.extend(write_buffer.take_read_buffer().take_remaining().iter().map(|&i| i));Ok(final_result)
}

fn aes256_ctr_decrypt(encrypted_data: &[u8],key: &[u8], iv: &[u8] - >Result<Vec<u8>,symmetriccipher::SymmetricCipherError>{
    let mut final_result = Vec: : <u8>::new();
    let mut read_buffer = buffer::RefReadBuffer::new(encrypted_data);
    let mut buffer = [0; 4096];
    let mut write_buffer = buffer::RefWriteBuffer::new(&mut buffer);

    let mut decoder=CtrMode::new(AesSafe256Encryptor::new(key),iv.to_vec());
    decoder.decrypt(&mut read_buffer,&mut write_buffer,true)? ; final_result.extend(write_buffer.take_read_buffer().take_remaining().iter().map(|&i| i));Ok(final_result)
}
Copy the code

tiny-keccak

SHA3, Keccak, SHAKE algorithm implementation, including the following algorithm:

  • shake128
  • shake256
  • keccak224
  • keccak256
  • keccak384
  • keccak512
  • sha3_224
  • sha3_256
  • sha3_384
  • sha3_512
About Keccak algorithm and SHA3

Keccak is a one-way hash function algorithm chosen as the SHA-3 standard. Keccak can generate hash values of any length. To match the hash length of SHA-2, SHA-3 defines sha3-224, SHA3-256, SHA3-384, and SHA3-512. In terms of the upper limit of the length of input data, SHA-1 isBit, SHA2 isBits, whereas SHA-3 has no length limit.

In addition, FIPS 202 specifies two extendable output functions (XOF) that can output arbitrary length hashes: SHAKE128 and SHAKE256.

Code examples:
extern crate rustc_hex;
extern crate tiny_keccak;

use rustc_hex::{FromHex,ToHex};
use tiny_keccak::Keccak;

fn main() {
    let hello_str = "hello world".as_bytes().to_hex();
    let data=hello_str.from_hex().unwrap();
    let mut res:[u8;32] = [0;32];
    let expected: &[u8] = & [0x64.0x4b.0xcc.0x7e.0x56.0x43.0x73.0x04.0x09.0x99.0xaa.0xc8.0x9e.0x76.0x22.0xf3.0xca.0x71.0xfb.0xa1.0xd9.0x72.0xfd.0x94.0xa3.0x1c.0x3b.0xfb.0xf2.0x4e.0x39.0x38
    ];

    let mut sha3=Keccak::new_sha3_256();
    sha3.update(&data);
    sha3.finalize(&mut res);
    assert_eq!(&res,expected);

    let mut keccak256=Keccak::new_keccak256();
    keccak256.update(&data);
    keccak256.finalize(&mut res);
    assert_ne!(&res,expected);
}

Copy the code
Standard document

NIST.FIPS.202

A state-of-art Diffie-Hellman function Curve25519: New Diffie-Hellman Speed Records Ed25519: high-speed high-security signatures High-speed high-security signatures HMAC: Keyed-Hashing for Message Authentication