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