mirrored from https://www.bouncycastle.org/repositories/bc-rust
-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathhkdf_cmd.rs
More file actions
96 lines (86 loc) · 3.12 KB
/
Copy pathhkdf_cmd.rs
File metadata and controls
96 lines (86 loc) · 3.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use std::io::Write;
use std::process::exit;
use std::{fs, io};
use bouncycastle::core::key_material::{KeyMaterial, KeyMaterialTrait, KeyType};
use bouncycastle::hex;
use bouncycastle::hkdf;
pub(crate) fn hkdf_cmd(
hkdfname: &str,
salt: &Option<String>,
salt_file: &Option<String>,
ikm: &Option<String>,
ikm_file: &Option<String>,
additional_input: &Option<String>,
additional_input_file: &Option<String>,
len: usize,
output_hex: bool,
) {
let salt_bytes: Vec<u8>;
let ikm_bytes: Vec<u8>;
let additional_input_bytes: Vec<u8>;
let mut out_key = KeyMaterial::<1024>::new();
if len > 1024 {
eprintln!("Error: The CLI only supports output lengths up to 128 bytes (1024 bits).");
exit(-1);
}
// load the values
salt_bytes = if salt.is_some() {
hex::decode(salt.as_ref().unwrap()).unwrap()
} else if salt_file.is_some() {
fs::read(salt_file.as_ref().unwrap()).unwrap()
} else {
eprintln!("Error: either `salt` or `salt-file` must be supplied.");
exit(-1)
};
if salt_bytes.len() > 128 {
eprintln!("Error: The CLI only supports HKDF salts up to 128 bytes (1024 bytes).");
exit(-1);
}
let mut salt_key = KeyMaterial::<1024>::from_bytes(&salt_bytes).unwrap();
// force it just so the CLI behaves properly even with all-zero or zero-length keys
salt_key.allow_hazardous_operations();
salt_key.convert_key_type(KeyType::MACKey).unwrap();
ikm_bytes = if ikm.is_some() {
hex::decode(ikm.as_ref().unwrap()).unwrap()
} else if ikm_file.is_some() {
fs::read(ikm_file.as_ref().unwrap()).unwrap()
} else {
eprintln!("Error: either `ikm` or `ikm_file` must be supplied.");
exit(-1)
};
additional_input_bytes = if additional_input.is_some() {
hex::decode(additional_input.as_ref().unwrap()).unwrap()
} else if additional_input.is_some() {
fs::read(additional_input_file.as_ref().unwrap()).unwrap()
} else {
eprintln!("Error: either `additional_input` or `additional_input_file` must be supplied.");
exit(-1)
};
// Do the HKDF
match hkdfname {
"HKDF-SHA256" => {
let mut h = hkdf::HKDF_SHA256::new();
h.do_extract_init(&salt_key).unwrap();
h.do_extract_update_bytes(ikm_bytes.as_slice()).unwrap();
h.do_extract_update_bytes(additional_input_bytes.as_slice()).unwrap();
h.do_extract_final_out(&mut out_key).unwrap();
}
"HKDF-SHA512" => {
let mut h = hkdf::HKDF_SHA512::new();
h.do_extract_init(&salt_key).unwrap();
h.do_extract_update_bytes(ikm_bytes.as_slice()).unwrap();
h.do_extract_update_bytes(additional_input_bytes.as_slice()).unwrap();
h.do_extract_final_out(&mut out_key).unwrap();
}
_ => {
panic!("{} is not a supported HKDF variant.", hkdfname);
}
}
if output_hex {
for b in out_key.ref_to_bytes().iter() {
print!("{b:02x}");
}
} else {
io::stdout().write(&out_key.ref_to_bytes()).unwrap();
}
}