bitwarden_crypto/enc_string/
mod.rs1mod asymmetric;
10mod symmetric;
11
12use std::str::FromStr;
13
14pub use asymmetric::UnsignedSharedKey;
15use base64::{engine::general_purpose::STANDARD, Engine};
16pub use symmetric::EncString;
17
18use crate::error::{EncStringParseError, Result};
19
20fn check_length(buf: &[u8], expected: usize) -> Result<()> {
21 if buf.len() < expected {
22 return Err(EncStringParseError::InvalidLength {
23 expected,
24 got: buf.len(),
25 }
26 .into());
27 }
28 Ok(())
29}
30
31fn from_b64_vec(s: &str) -> Result<Vec<u8>> {
32 Ok(STANDARD
33 .decode(s)
34 .map_err(EncStringParseError::InvalidBase64)?)
35}
36
37fn from_b64<const N: usize>(s: &str) -> Result<[u8; N]> {
38 Ok(from_b64_vec(s)?
39 .try_into()
40 .map_err(|e: Vec<_>| EncStringParseError::InvalidLength {
41 expected: N,
42 got: e.len(),
43 })?)
44}
45
46fn split_enc_string(s: &str) -> (&str, Vec<&str>) {
47 let header_parts: Vec<_> = s.split('.').collect();
48
49 if header_parts.len() == 2 {
50 (header_parts[0], header_parts[1].split('|').collect())
51 } else {
52 let parts: Vec<_> = s.split('|').collect();
54 if parts.len() == 3 {
55 ("1", parts) } else {
57 ("0", parts) }
59 }
60}
61
62struct FromStrVisitor<T>(std::marker::PhantomData<T>);
63impl<T> FromStrVisitor<T> {
64 fn new() -> Self {
65 Self(Default::default())
66 }
67}
68impl<T: FromStr> serde::de::Visitor<'_> for FromStrVisitor<T>
69where
70 T::Err: std::fmt::Debug,
71{
72 type Value = T;
73
74 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
75 write!(f, "a valid string")
76 }
77
78 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
79 where
80 E: serde::de::Error,
81 {
82 T::from_str(v).map_err(|e| E::custom(format!("{:?}", e)))
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
91 fn test_check_length_less_than_expected() {
92 let buf = [1, 2, 3];
93 let expected = 5;
94 let result = check_length(&buf, expected);
95 assert!(result.is_err());
96 }
97
98 #[test]
99 fn test_check_length_equal_to_expected() {
100 let buf = [1, 2, 3, 4, 5];
101 let expected = 5;
102 let result = check_length(&buf, expected);
103 assert!(result.is_ok());
104 }
105
106 #[test]
107 fn test_check_length_greater_than_expected() {
108 let buf = [1, 2, 3, 4, 5, 6];
109 let expected = 5;
110 let result = check_length(&buf, expected);
111 assert!(result.is_ok());
112 }
113
114 #[test]
115 fn test_split_enc_string_new_format() {
116 let s = "2.abc|def|ghi";
117 let (header, parts) = split_enc_string(s);
118 assert_eq!(header, "2");
119 assert_eq!(parts, vec!["abc", "def", "ghi"]);
120 }
121
122 #[test]
123 fn test_split_enc_string_old_format_three_parts() {
124 let s = "abc|def|ghi";
125 let (header, parts) = split_enc_string(s);
126 assert_eq!(header, "1");
127 assert_eq!(parts, vec!["abc", "def", "ghi"]);
128 }
129
130 #[test]
131 fn test_split_enc_string_old_format_fewer_parts() {
132 let s = "abc|def";
133 let (header, parts) = split_enc_string(s);
134 assert_eq!(header, "0");
135 assert_eq!(parts, vec!["abc", "def"]);
136 }
137}