Skip to content

Commit 0ed6249

Browse files
authored
Merge pull request #38 from goto-opensource/feature/cli-example
test: add a cli example
2 parents 3050eb5 + 7c70223 commit 0ed6249

File tree

2 files changed

+185
-0
lines changed

2 files changed

+185
-0
lines changed

Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ features = ["vendored"]
3636
optional = true
3737

3838
[dev-dependencies]
39+
clap = { version = "4.4.8", features = ["derive"] }
3940
criterion = { version = "0.5", features = ["html_reports"] }
4041
hex = "0.4"
4142
lazy_static = "1.4.0"
@@ -44,6 +45,7 @@ pretty_assertions = "1.3"
4445
rand = "0.8"
4546
serde = { version = "1.0", features = ["derive"] }
4647
serde_json = "1.0"
48+
simple_logger = "4.2.0"
4749
strum_macros = "0.25"
4850
test-case = "3.1.0"
4951

examples/encrypt_decrypt.rs

+183
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
// Copyright (c) 2023 GoTo Group, Inc
2+
// SPDX-License-Identifier: Apache-2.0 AND MIT
3+
4+
use std::{
5+
fmt::Write,
6+
io::{self, BufRead, Write as _},
7+
};
8+
9+
use clap::{Parser, ValueEnum};
10+
use sframe::{
11+
header::{Deserialization, Header, HeaderFields},
12+
receiver::Receiver,
13+
sender::Sender,
14+
CipherSuiteVariant,
15+
};
16+
17+
fn main() {
18+
let Args {
19+
cipher_suite,
20+
key_id,
21+
secret,
22+
log_level,
23+
} = Args::parse();
24+
25+
println!(
26+
"- Using cipher suite {:?}, key id {}, secret {}",
27+
cipher_suite, key_id, secret
28+
);
29+
30+
if let Some(log_level) = log_level {
31+
println!("- Using log level {}", log_level);
32+
simple_logger::init_with_level(log_level).unwrap();
33+
}
34+
35+
let mut sender = Sender::with_cipher_suite(key_id, cipher_suite.into());
36+
sender.set_encryption_key(&secret).unwrap();
37+
38+
let mut receiver = Receiver::with_cipher_suite(cipher_suite.into());
39+
receiver
40+
.set_encryption_key(key_id, secret.as_bytes())
41+
.unwrap();
42+
43+
let print_before_input = || {
44+
println!("--------------------------------------------------------------------------");
45+
println!("- Enter a phrase to be encrypted, confirm with [ENTER], abort with [CTRL+C]");
46+
print!("- To be encrypted: ");
47+
std::io::stdout().flush().unwrap();
48+
};
49+
50+
print_before_input();
51+
52+
let stdin = io::stdin();
53+
let lines = stdin
54+
.lock()
55+
.lines()
56+
.take_while(Result::is_ok)
57+
.map(Result::unwrap);
58+
59+
lines.for_each(|l| {
60+
println!("- Encrypting {}", bin2string(l.as_bytes()));
61+
let encrypted = sender.encrypt(l, 0).unwrap();
62+
display_encrypted(encrypted);
63+
64+
let decrypted = receiver.decrypt(encrypted, 0).unwrap();
65+
println!("- Decrypted {}", bin2string(decrypted));
66+
67+
print_before_input();
68+
});
69+
}
70+
71+
fn display_encrypted(encrypted: &[u8]) {
72+
let header = Header::deserialize(encrypted).unwrap();
73+
let header_len = header.size();
74+
let first_byte = bin2string(&encrypted[0..1]);
75+
76+
println!("- Sframe Header: ");
77+
match header {
78+
Header::Basic(_) => {
79+
let frame_count = bin2string(&encrypted[1..header_len]);
80+
let ctr_field_len = frame_count.len() + 1;
81+
82+
println!("+-+-+-+-+-+-+-+-+{:-^1$}+", "", ctr_field_len);
83+
println!("|R| LEN |0| KID |{:^1$}|", "CTR", ctr_field_len);
84+
println!(
85+
"|{}|{:^5}|{}|{:^5}| {:^}|",
86+
first_byte.get(0..1).unwrap(),
87+
first_byte.get(1..4).unwrap(),
88+
first_byte.get(4..5).unwrap(),
89+
first_byte.get(5..8).unwrap(),
90+
frame_count
91+
);
92+
println!("+-+-+-+-+-+-+-+-+{:-^1$}+", "", ctr_field_len);
93+
}
94+
95+
Header::Extended(_) => {
96+
let frame_count_len = header.frame_count().length_in_bytes() as usize;
97+
let frame_count = bin2string(&encrypted[header_len - frame_count_len..header_len]);
98+
let ctr_field_len = frame_count.len() + 1;
99+
100+
let key_id = bin2string(&encrypted[1..header_len - frame_count_len]);
101+
let kid_field_len = key_id.len() + 1;
102+
103+
println!(
104+
"+-+-+-+-+-+-+-+--+{:-^2$}+{:-^3$}+",
105+
"", "", kid_field_len, ctr_field_len
106+
);
107+
println!(
108+
"|R| LEN |1| KLEN |{:^2$}|{:^3$}|",
109+
"KID", "CTR", kid_field_len, ctr_field_len
110+
);
111+
println!(
112+
"|{}|{:^5}|{}|{:^6}| {:^}| {:^}|",
113+
first_byte.get(0..1).unwrap(),
114+
first_byte.get(1..4).unwrap(),
115+
first_byte.get(4..5).unwrap(),
116+
first_byte.get(5..8).unwrap(),
117+
key_id,
118+
frame_count
119+
);
120+
println!(
121+
"+-+-+-+-+-+-+-+--+{:-^2$}+{:-^3$}+",
122+
"", "", ctr_field_len, kid_field_len
123+
);
124+
}
125+
}
126+
127+
let payload = bin2string(&encrypted[header_len..]);
128+
println!("- Encrypted Payload: {}", payload)
129+
}
130+
131+
fn bin2string(bin: &[u8]) -> String {
132+
bin.iter().fold(String::new(), |mut output, x| {
133+
let _ = write!(output, "{x:08b} ");
134+
output
135+
})
136+
}
137+
138+
#[derive(Parser, Debug)]
139+
#[command(author, version, about, long_about = None)]
140+
struct Args {
141+
#[arg(value_enum, short, long, default_value_t = ArgCipherSuiteVariant::AesGcm128Sha256)]
142+
cipher_suite: ArgCipherSuiteVariant,
143+
#[arg(short, long, default_value_t = 3)]
144+
key_id: u64,
145+
#[arg(short, long, default_value = "SUPER_SECRET")]
146+
secret: String,
147+
#[arg(short, long)]
148+
log_level: Option<log::Level>,
149+
}
150+
151+
// We need to redeclare here, as we need to derive ValueEnum to use it with clap...
152+
#[derive(ValueEnum, Clone, Copy, Debug)]
153+
pub enum ArgCipherSuiteVariant {
154+
#[cfg(feature = "openssl")]
155+
AesCtr128HmacSha256_80,
156+
#[cfg(feature = "openssl")]
157+
AesCtr128HmacSha256_64,
158+
#[cfg(feature = "openssl")]
159+
AesCtr128HmacSha256_32,
160+
AesGcm128Sha256,
161+
AesGcm256Sha512,
162+
}
163+
164+
impl From<ArgCipherSuiteVariant> for CipherSuiteVariant {
165+
fn from(val: ArgCipherSuiteVariant) -> Self {
166+
match val {
167+
#[cfg(feature = "openssl")]
168+
ArgCipherSuiteVariant::AesCtr128HmacSha256_80 => {
169+
CipherSuiteVariant::AesCtr128HmacSha256_80
170+
}
171+
#[cfg(feature = "openssl")]
172+
ArgCipherSuiteVariant::AesCtr128HmacSha256_64 => {
173+
CipherSuiteVariant::AesCtr128HmacSha256_64
174+
}
175+
#[cfg(feature = "openssl")]
176+
ArgCipherSuiteVariant::AesCtr128HmacSha256_32 => {
177+
CipherSuiteVariant::AesCtr128HmacSha256_32
178+
}
179+
ArgCipherSuiteVariant::AesGcm128Sha256 => CipherSuiteVariant::AesGcm128Sha256,
180+
ArgCipherSuiteVariant::AesGcm256Sha512 => CipherSuiteVariant::AesGcm256Sha512,
181+
}
182+
}
183+
}

0 commit comments

Comments
 (0)