feat: add example
This commit is contained in:
@@ -12,3 +12,4 @@ zeroize = { version = "1.6.0", features = ["zeroize_derive"] }
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
aes-gcm = { version = "0.10.2", features = ["zeroize"] }
|
aes-gcm = { version = "0.10.2", features = ["zeroize"] }
|
||||||
|
benchmark-simple = "0.1.8"
|
||||||
|
|||||||
29
README.md
29
README.md
@@ -1,5 +1,34 @@
|
|||||||
# aes-gcm-stream
|
# aes-gcm-stream
|
||||||
|
|
||||||
|
## Encrypt
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// IMPORTANT! key and nonce SHOULD generate by random
|
||||||
|
let mut key = [0u8; 32];
|
||||||
|
let mut nonce = [0; 12];
|
||||||
|
|
||||||
|
let mut encryptor = Aes256GcmStreamEncryptor::new(key.clone(), &nonce);
|
||||||
|
|
||||||
|
let mut ciphertext = vec![];
|
||||||
|
ciphertext.extend_from_slice(&encryptor.update(b"Hello "));
|
||||||
|
ciphertext.extend_from_slice(&encryptor.update(b" World"));
|
||||||
|
ciphertext.extend_from_slice(&encryptor.update(b"!"));
|
||||||
|
let (last_block, tag) = encryptor.finalize();
|
||||||
|
ciphertext.extend_from_slice(&last_block);
|
||||||
|
ciphertext.extend_from_slice(&tag);
|
||||||
|
|
||||||
|
println!("Ciphertext: {}", hex::encode(&ciphertext));
|
||||||
|
```
|
||||||
|
|
||||||
|
## Run Example
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ cargo run --example encrypt_and_decrypt
|
||||||
|
Finished dev [unoptimized + debuginfo] target(s) in 0.10s
|
||||||
|
Running `target/debug/examples/encrypt_and_decrypt`
|
||||||
|
Ciphertext: 86c22c5122404b39683ca9b79b889fd00a6212d1be2ebc3f4f8f22f90b
|
||||||
|
Plaintext: Hello World!
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
> Thanks: https://developer.aliyun.com/article/952809
|
> Thanks: https://developer.aliyun.com/article/952809
|
||||||
|
|||||||
53
examples/bench.rs
Normal file
53
examples/bench.rs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
use benchmark_simple::{Bench, Options};
|
||||||
|
|
||||||
|
use aes_gcm_stream::{Aes128GcmStreamEncryptor, Aes192GcmStreamEncryptor, Aes256GcmStreamEncryptor};
|
||||||
|
|
||||||
|
fn test_aes128_encrypt(m: &mut [u8]) {
|
||||||
|
let key = [0u8; 16];
|
||||||
|
let nonce = [0u8; 12];
|
||||||
|
let mut encryptor = Aes128GcmStreamEncryptor::new(key, &nonce);
|
||||||
|
|
||||||
|
encryptor.update(m);
|
||||||
|
encryptor.finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_aes192_encrypt(m: &mut [u8]) {
|
||||||
|
let key = [0u8; 24];
|
||||||
|
let nonce = [0u8; 12];
|
||||||
|
let mut encryptor = Aes192GcmStreamEncryptor::new(key, &nonce);
|
||||||
|
|
||||||
|
encryptor.update(m);
|
||||||
|
encryptor.finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_aes256_encrypt(m: &mut [u8]) {
|
||||||
|
let key = [0u8; 32];
|
||||||
|
let nonce = [0u8; 12];
|
||||||
|
let mut encryptor = Aes256GcmStreamEncryptor::new(key, &nonce);
|
||||||
|
|
||||||
|
encryptor.update(m);
|
||||||
|
encryptor.finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let bench = Bench::new();
|
||||||
|
let mut m = vec![0xd0u8; 16384];
|
||||||
|
|
||||||
|
let options = &Options {
|
||||||
|
iterations: 1_000,
|
||||||
|
warmup_iterations: 1_00,
|
||||||
|
min_samples: 5,
|
||||||
|
max_samples: 10,
|
||||||
|
max_rsd: 1.0,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let res = bench.run(options, || test_aes128_encrypt(&mut m));
|
||||||
|
println!("AES128 encrypt : {}", res.throughput(m.len() as _));
|
||||||
|
|
||||||
|
let res = bench.run(options, || test_aes192_encrypt(&mut m));
|
||||||
|
println!("AES192 encrypt : {}", res.throughput(m.len() as _));
|
||||||
|
|
||||||
|
let res = bench.run(options, || test_aes256_encrypt(&mut m));
|
||||||
|
println!("AES256 encrypt : {}", res.throughput(m.len() as _));
|
||||||
|
}
|
||||||
30
examples/encrypt_and_decrypt.rs
Normal file
30
examples/encrypt_and_decrypt.rs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
use aes_gcm_stream::{Aes256GcmStreamDecryptor, Aes256GcmStreamEncryptor};
|
||||||
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// IMPORTANT! key and nonce SHOULD generate by random
|
||||||
|
let mut key = [0u8; 32];
|
||||||
|
let mut nonce = [0; 12];
|
||||||
|
|
||||||
|
let mut encryptor = Aes256GcmStreamEncryptor::new(key.clone(), &nonce);
|
||||||
|
|
||||||
|
let mut ciphertext = vec![];
|
||||||
|
ciphertext.extend_from_slice(&encryptor.update(b"Hello "));
|
||||||
|
ciphertext.extend_from_slice(&encryptor.update(b" World"));
|
||||||
|
ciphertext.extend_from_slice(&encryptor.update(b"!"));
|
||||||
|
let (last_block, tag) = encryptor.finalize();
|
||||||
|
ciphertext.extend_from_slice(&last_block);
|
||||||
|
ciphertext.extend_from_slice(&tag);
|
||||||
|
|
||||||
|
println!("Ciphertext: {}", hex::encode(&ciphertext));
|
||||||
|
|
||||||
|
let mut decryptor = Aes256GcmStreamDecryptor::new(key.clone(), &nonce);
|
||||||
|
|
||||||
|
let mut plaintext = vec![];
|
||||||
|
plaintext.extend_from_slice(decryptor.update(&ciphertext).as_slice());
|
||||||
|
plaintext.extend_from_slice(&decryptor.finalize().expect("decrypt error"));
|
||||||
|
|
||||||
|
println!("Plaintext: {}", String::from_utf8_lossy(&plaintext));
|
||||||
|
key.zeroize();
|
||||||
|
nonce.zeroize();
|
||||||
|
}
|
||||||
@@ -62,7 +62,7 @@ impl $module {
|
|||||||
let message_buffer_slice = self.message_buffer.as_slice();
|
let message_buffer_slice = self.message_buffer.as_slice();
|
||||||
let message_buffer_len = message_buffer_slice.len();
|
let message_buffer_len = message_buffer_slice.len();
|
||||||
if message_buffer_len < 32 {
|
if message_buffer_len < 32 {
|
||||||
return vec![];
|
return Vec::with_capacity(0);
|
||||||
}
|
}
|
||||||
let blocks_count = (message_buffer_len / 16) - 1;
|
let blocks_count = (message_buffer_len / 16) - 1;
|
||||||
let mut plaintext_message = Vec::with_capacity(blocks_count * 16);
|
let mut plaintext_message = Vec::with_capacity(blocks_count * 16);
|
||||||
@@ -91,7 +91,7 @@ impl $module {
|
|||||||
// last block and this block len is less than 128 bits
|
// last block and this block len is less than 128 bits
|
||||||
self.encryption_nonce = inc_32(self.encryption_nonce);
|
self.encryption_nonce = inc_32(self.encryption_nonce);
|
||||||
let mut ctr = self.encryption_nonce.to_be_bytes();
|
let mut ctr = self.encryption_nonce.to_be_bytes();
|
||||||
let block = Block::<Aes128>::from_mut_slice(&mut ctr);
|
let block = Block::<$aesn>::from_mut_slice(&mut ctr);
|
||||||
self.crypto.encrypt_block(block);
|
self.crypto.encrypt_block(block);
|
||||||
|
|
||||||
let chunk = &self.message_buffer[0..message_buffer_len - 16];
|
let chunk = &self.message_buffer[0..message_buffer_len - 16];
|
||||||
|
|||||||
@@ -62,14 +62,14 @@ impl $module {
|
|||||||
let message_buffer_slice = self.message_buffer.as_slice();
|
let message_buffer_slice = self.message_buffer.as_slice();
|
||||||
let message_buffer_len = message_buffer_slice.len();
|
let message_buffer_len = message_buffer_slice.len();
|
||||||
if message_buffer_len < 16 {
|
if message_buffer_len < 16 {
|
||||||
return vec![];
|
return Vec::with_capacity(0);
|
||||||
}
|
}
|
||||||
let blocks_count = message_buffer_len / 16;
|
let blocks_count = message_buffer_len / 16;
|
||||||
let mut encrypted_message = Vec::with_capacity(blocks_count * 16);
|
let mut encrypted_message = Vec::with_capacity(blocks_count * 16);
|
||||||
for i in 0..blocks_count {
|
for i in 0..blocks_count {
|
||||||
self.encryption_nonce = inc_32(self.encryption_nonce);
|
self.encryption_nonce = inc_32(self.encryption_nonce);
|
||||||
let mut ctr = self.encryption_nonce.to_be_bytes();
|
let mut ctr = self.encryption_nonce.to_be_bytes();
|
||||||
let block = Block::<Aes128>::from_mut_slice(&mut ctr);
|
let block = Block::<$aesn>::from_mut_slice(&mut ctr);
|
||||||
self.crypto.encrypt_block(block);
|
self.crypto.encrypt_block(block);
|
||||||
let chunk = &message_buffer_slice[i * 16..(i + 1) * 16];
|
let chunk = &message_buffer_slice[i * 16..(i + 1) * 16];
|
||||||
let y = u8to128(chunk) ^ u8to128(&block.as_slice());
|
let y = u8to128(chunk) ^ u8to128(&block.as_slice());
|
||||||
@@ -90,7 +90,7 @@ impl $module {
|
|||||||
// last block and this block len is less than 128 bits
|
// last block and this block len is less than 128 bits
|
||||||
self.encryption_nonce = inc_32(self.encryption_nonce);
|
self.encryption_nonce = inc_32(self.encryption_nonce);
|
||||||
let mut ctr = self.encryption_nonce.to_be_bytes();
|
let mut ctr = self.encryption_nonce.to_be_bytes();
|
||||||
let block = Block::<Aes128>::from_mut_slice(&mut ctr);
|
let block = Block::<$aesn>::from_mut_slice(&mut ctr);
|
||||||
self.crypto.encrypt_block(block);
|
self.crypto.encrypt_block(block);
|
||||||
|
|
||||||
let chunk = self.message_buffer.as_slice();
|
let chunk = self.message_buffer.as_slice();
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ pub(crate) fn normalize_nonce(ghash_key: u128, nonce_bytes: &[u8]) -> (u128, u12
|
|||||||
(ghash_key, normalized_nonce)
|
(ghash_key, normalized_nonce)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub(crate) fn u8to128(bytes: &[u8]) -> u128 {
|
pub(crate) fn u8to128(bytes: &[u8]) -> u128 {
|
||||||
bytes.iter().rev().enumerate().fold(0, |acc, (i, &byte)| {
|
bytes.iter().rev().enumerate().fold(0, |acc, (i, &byte)| {
|
||||||
acc | (byte as u128) << (i * 8)
|
acc | (byte as u128) << (i * 8)
|
||||||
@@ -62,6 +63,7 @@ pub(crate) fn msb_s(s: usize, bytes: &[u8]) -> Vec<u8> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// incs(X)=MSBlen(X)-s(X) || [int(LSBs(X))+1 mod 2^s]s
|
// incs(X)=MSBlen(X)-s(X) || [int(LSBs(X))+1 mod 2^s]s
|
||||||
|
#[inline]
|
||||||
pub(crate) fn inc_32(bits: u128) -> u128 {
|
pub(crate) fn inc_32(bits: u128) -> u128 {
|
||||||
let msb = bits >> 32;
|
let msb = bits >> 32;
|
||||||
let mut lsb = (bits & 0xffffffff) as u32;
|
let mut lsb = (bits & 0xffffffff) as u32;
|
||||||
|
|||||||
Reference in New Issue
Block a user