crypto_speed/
crypto_speed.rs1use std::env::args;
2use std::fs::File;
3use std::io::{Read, Seek, Write};
4use std::path::Path;
5use std::sync::Arc;
6use std::time::Instant;
7use std::{fs, io};
8
9use anyhow::Result;
10use rand_core::RngCore;
11use shush_rs::SecretVec;
12
13use rencfs::crypto;
14use rencfs::crypto::write::{CryptoInnerWriter, CryptoWrite};
15use rencfs::crypto::Cipher;
16
17#[tokio::main]
18async fn main() -> Result<()> {
19 tracing_subscriber::fmt().init();
20
21 let cipher = Cipher::ChaCha20Poly1305;
22 let key = Arc::new(get_key(cipher)?);
23
24 println!("chacha\n");
25
26 let mut args = args();
27 let _ = args.next(); let path_in = args.next().expect("path_in is missing");
29 let path_out = format!(
30 "/tmp/{}.enc",
31 Path::new(&path_in).file_name().unwrap().to_str().unwrap()
32 );
33 let out = Path::new(&path_out).to_path_buf();
34 if out.exists() {
35 fs::remove_file(&out)?;
36 }
37
38 stream_speed(&path_in, &path_out, cipher, &key)?;
39 println!();
40 file_speed(&path_in, &path_out, cipher, &key)?;
41
42 let cipher = Cipher::Aes256Gcm;
43 let key = Arc::new(get_key(cipher)?);
44
45 println!("\naesgcm\n");
46
47 stream_speed(&path_in, &path_out, cipher, &key)?;
48 println!();
49 file_speed(&path_in, &path_out, cipher, &key)?;
50
51 Ok(())
52}
53
54fn speed<F>(f: F, label: &str, size: u64) -> io::Result<()>
55where
56 F: FnOnce() -> io::Result<()>,
57{
58 let start = Instant::now();
59 f()?;
60 let duration = start.elapsed();
61 println!(
62 "{label} duration = {:?}, speed MB/s {:.2}",
63 duration,
64 (size as f64 / duration.as_secs_f64()) / 1024.0 / 1024.0
65 );
66 Ok(())
67}
68
69fn check_hash(r1: &mut impl Read, r2: &mut (impl Read + ?Sized)) -> Result<()> {
70 let hash1 = crypto::hash_reader(r1)?;
71 let hash2 = crypto::hash_reader(r2)?;
72 assert_eq!(hash1, hash2);
73 Ok(())
74}
75
76fn stream_speed(
77 path_in: &str,
78 path_out: &str,
79 cipher: Cipher,
80 key: &Arc<SecretVec<u8>>,
81) -> Result<()> {
82 println!("stream speed");
83 let _ = fs::remove_file(path_out);
84 let mut file_in = File::open(path_in)?;
85 let file_out = File::create(path_out)?;
86 let path_out2 = Path::new(&path_out).to_path_buf().with_extension("dec");
87 let _ = fs::remove_file(path_out2.clone());
88 let mut file_out2 = File::create(path_out2.clone())?;
89 let mut writer = crypto::create_write(file_out, cipher, key);
90 let size = file_in.metadata()?.len();
91 let f = || crypto::create_read(File::open(path_out).unwrap(), cipher, key);
92 test_speed(&mut file_in, &mut writer, &mut file_out2, size, f)?;
93 file_in.seek(io::SeekFrom::Start(0))?;
94 check_hash(&mut file_in, &mut f())?;
95 fs::remove_file(path_out)?;
96 fs::remove_file(path_out2)?;
97 Ok(())
98}
99
100fn file_speed(path_in: &str, path_out: &str, cipher: Cipher, key: &SecretVec<u8>) -> Result<()> {
101 println!("file speed");
102 let _ = fs::remove_file(path_out);
103 let mut file_in = File::open(path_in)?;
104 let mut writer = crypto::create_write(File::create(Path::new(path_out))?, cipher, key);
105 let path_out2 = Path::new(&path_out).to_path_buf().with_extension("dec");
106 let _ = fs::remove_file(path_out2.clone());
107 let mut file_out2 = File::create(path_out2.clone())?;
108 let size = file_in.metadata()?.len();
109 let f = || crypto::create_read(File::open(path_out).unwrap(), cipher, key);
110 test_speed(&mut file_in, &mut writer, &mut file_out2, size, f)?;
111 file_in.seek(io::SeekFrom::Start(0)).unwrap();
112 check_hash(&mut file_in, &mut f())?;
113 fs::remove_file(path_out)?;
114 fs::remove_file(path_out2)?;
115 Ok(())
116}
117
118fn test_speed<W: CryptoInnerWriter + Send + Sync, R: Read + Send + Sync, FR>(
119 r: &mut impl Read,
120 w: &mut (impl CryptoWrite<W> + ?Sized),
121 w2: &mut impl Write,
122 size: u64,
123 r2: FR,
124) -> io::Result<()>
125where
126 FR: FnOnce() -> R,
127{
128 let mut r = io::BufReader::new(r);
129 let mut w = io::BufWriter::new(w);
130 speed(
131 || {
132 io::copy(&mut r, &mut w)?;
133 w.into_inner()
134 .map_err(|err| {
135 let (err, _) = err.into_parts();
136 err
137 })?
138 .finish()?;
139 Ok(())
140 },
141 "write",
142 size,
143 )?;
144 speed(
145 || {
146 io::copy(&mut r2(), w2)?;
147 w2.flush()?;
148 Ok(())
149 },
150 "read",
151 size,
152 )?;
153 Ok(())
154}
155
156fn get_key(cipher: Cipher) -> io::Result<SecretVec<u8>> {
157 let mut key = vec![0; cipher.key_len()];
158 crypto::create_rng().fill_bytes(key.as_mut_slice());
159 Ok(SecretVec::from(key))
160}