claw_crypto/
key_service.rs1use crate::traits::KeyServiceTrait;
2pub use claw_crypto_interface::PrefixedKeySplits;
3use rand::{self, Rng};
4
5pub struct KeyService;
6
7impl KeyService {
8 fn join_digits(&self, digit_vec: &[u8]) -> String {
9 let vec: Vec<String> = digit_vec
10 .into_iter()
11 .map(|digit| digit.to_string())
12 .collect();
13 vec.join("")
14 }
15}
16
17impl KeyServiceTrait for KeyService {
18 fn digit_string(&self, length: usize) -> String {
19 let digit_vec = self.digit_vec(length);
20 let key = self.join_digits(&digit_vec);
21 key
22 }
23
24 fn digit_vec(&self, length: usize) -> Vec<u8> {
25 let mut digits = Vec::with_capacity(length);
26 for _ in 0..length {
27 let digit = rand::thread_rng().gen_range(0..=9);
28 let digit = digit as u8;
29 digits.push(digit);
30 }
31 digits
32 }
33
34 fn secure_string(&self, length: usize) -> String {
35 let random_bytes = rand::thread_rng().gen::<[u8; 32]>();
36 let random_slice = &random_bytes[0..length];
37 let string = self.join_digits(random_slice);
38 string
39 }
40
41 fn split_prefixed_key<'a>(
42 &self,
43 key: &'a str,
44 splitter: &str,
45 ) -> Result<PrefixedKeySplits<'a>, &'static str> {
46 let splits: Vec<&str> = key.split(splitter).collect();
47 let prefix = splits.get(0).ok_or("No prefix found in inputted &str")?;
48 let key = splits.get(1).ok_or("No key found in inputted &str")?;
49
50 Ok(PrefixedKeySplits::<'a> { prefix, key })
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57
58 #[test]
59 fn it_generates_vector_of_correct_length() {
60 let expected = 6usize;
61 let actual = KeyService.digit_vec(expected).len();
62 assert_eq!(actual, expected);
63 }
64
65 #[test]
66 fn it_generates_digit_string_of_correct_length() {
67 let expected = 16usize;
68 let actual = KeyService.digit_string(expected).len();
69 assert_eq!(actual, expected);
70 }
71
72 #[test]
74 fn it_generates_random_string() {
75 let strings: Vec<String> = (0..5).map(|_| KeyService.secure_string(32)).collect();
76
77 let first = &strings[0];
78 for (i, other) in strings.iter().skip(1).enumerate() {
79 assert_ne!(
80 first,
81 other,
82 "First string is identical to string at index {}",
83 i + 1
84 );
85 }
86 }
87
88 #[test]
89 fn it_generates_random_string_of_specified_length() {
90 let expected = 10usize;
91 let actual = KeyService.secure_string(expected).len();
92 assert_eq!(actual, expected)
93 }
94}