Skip to main content

extrapaytr_crypto/
encoding.rs

1use base64::Engine as _;
2use base64::engine::general_purpose::STANDARD as BASE64_STANDARD;
3
4pub fn base64_encode(input: impl AsRef<[u8]>) -> String {
5    BASE64_STANDARD.encode(input)
6}
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
9#[error("invalid base64 input")]
10pub struct Base64DecodeError;
11
12pub fn base64_decode(input: impl AsRef<[u8]>) -> Result<Vec<u8>, Base64DecodeError> {
13    BASE64_STANDARD.decode(input).map_err(|_| Base64DecodeError)
14}
15
16pub fn hex_lower(input: impl AsRef<[u8]>) -> String {
17    hex::encode(input)
18}
19
20pub fn hex_upper(input: impl AsRef<[u8]>) -> String {
21    hex::encode_upper(input)
22}
23
24#[cfg(test)]
25mod tests {
26    use super::*;
27
28    #[test]
29    fn base64_round_trips() {
30        let original = b"apiKey:abc&randomKey:123&signature:deadbeef";
31        let encoded = base64_encode(original);
32        let decoded = base64_decode(&encoded).unwrap();
33        assert_eq!(decoded, original);
34    }
35
36    #[test]
37    fn base64_decode_rejects_garbage() {
38        assert!(base64_decode("not valid base64!!").is_err());
39    }
40
41    #[test]
42    fn hex_case_variants() {
43        let bytes = [0xdeu8, 0xad, 0xbe, 0xef];
44        assert_eq!(hex_lower(bytes), "deadbeef");
45        assert_eq!(hex_upper(bytes), "DEADBEEF");
46    }
47}