dynomite/crypto/
base64.rs1use base64::engine::general_purpose::STANDARD;
11use base64::engine::general_purpose::STANDARD_NO_PAD;
12use base64::Engine;
13
14use crate::crypto::CryptoError;
15
16pub fn base64_encode(bytes: &[u8]) -> String {
28 STANDARD.encode(bytes)
29}
30
31pub fn base64_decode(s: &str) -> Result<Vec<u8>, CryptoError> {
43 if s.contains('=') {
44 STANDARD
45 .decode(s.as_bytes())
46 .map_err(|e| CryptoError::Base64(e.to_string()))
47 } else {
48 STANDARD_NO_PAD
49 .decode(s.as_bytes())
50 .map_err(|e| CryptoError::Base64(e.to_string()))
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57
58 #[test]
59 fn empty_round_trip() {
60 assert_eq!(base64_encode(b""), "");
61 assert_eq!(base64_decode("").unwrap(), Vec::<u8>::new());
62 }
63
64 #[test]
65 fn standard_vectors() {
66 assert_eq!(base64_encode(b"f"), "Zg==");
68 assert_eq!(base64_encode(b"fo"), "Zm8=");
69 assert_eq!(base64_encode(b"foo"), "Zm9v");
70 assert_eq!(base64_encode(b"foob"), "Zm9vYg==");
71 assert_eq!(base64_encode(b"fooba"), "Zm9vYmE=");
72 assert_eq!(base64_encode(b"foobar"), "Zm9vYmFy");
73 }
74
75 #[test]
76 fn unpadded_decodes_too() {
77 assert_eq!(base64_decode("Zg").unwrap(), b"f");
78 assert_eq!(base64_decode("Zm8").unwrap(), b"fo");
79 }
80
81 #[test]
82 fn invalid_input_errors() {
83 assert!(base64_decode("@@@").is_err());
84 assert!(base64_decode("####").is_err());
85 }
86}