sentinel_modsec/transformations/
encode.rs

1//! Encoding transformations.
2
3use super::Transformation;
4use std::borrow::Cow;
5
6/// Base64 encode transformation.
7pub struct Base64Encode;
8
9impl Transformation for Base64Encode {
10    fn transform<'a>(&self, input: &'a str) -> Cow<'a, str> {
11        use base64::Engine;
12        Cow::Owned(base64::engine::general_purpose::STANDARD.encode(input))
13    }
14
15    fn name(&self) -> &'static str {
16        "base64Encode"
17    }
18}
19
20/// Hex encode transformation.
21pub struct HexEncode;
22
23impl Transformation for HexEncode {
24    fn transform<'a>(&self, input: &'a str) -> Cow<'a, str> {
25        let encoded: String = input.bytes().map(|b| format!("{:02x}", b)).collect();
26        Cow::Owned(encoded)
27    }
28
29    fn name(&self) -> &'static str {
30        "hexEncode"
31    }
32}
33
34/// URL encode transformation.
35pub struct UrlEncode;
36
37impl Transformation for UrlEncode {
38    fn transform<'a>(&self, input: &'a str) -> Cow<'a, str> {
39        use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
40        let encoded = utf8_percent_encode(input, NON_ALPHANUMERIC).to_string();
41        if encoded == input {
42            Cow::Borrowed(input)
43        } else {
44            Cow::Owned(encoded)
45        }
46    }
47
48    fn name(&self) -> &'static str {
49        "urlEncode"
50    }
51}
52
53/// MD5 hash transformation.
54pub struct Md5;
55
56impl Transformation for Md5 {
57    fn transform<'a>(&self, input: &'a str) -> Cow<'a, str> {
58        use md5::{Digest, Md5 as Md5Hasher};
59        let mut hasher = Md5Hasher::new();
60        hasher.update(input.as_bytes());
61        let result = hasher.finalize();
62        Cow::Owned(format!("{:x}", result))
63    }
64
65    fn name(&self) -> &'static str {
66        "md5"
67    }
68}
69
70/// SHA1 hash transformation.
71pub struct Sha1;
72
73impl Transformation for Sha1 {
74    fn transform<'a>(&self, input: &'a str) -> Cow<'a, str> {
75        use sha1::{Digest, Sha1 as Sha1Hasher};
76        let mut hasher = Sha1Hasher::new();
77        hasher.update(input.as_bytes());
78        let result = hasher.finalize();
79        Cow::Owned(format!("{:x}", result))
80    }
81
82    fn name(&self) -> &'static str {
83        "sha1"
84    }
85}
86
87#[cfg(test)]
88mod tests {
89    use super::*;
90
91    #[test]
92    fn test_base64_encode() {
93        let t = Base64Encode;
94        assert_eq!(t.transform("hello"), "aGVsbG8=");
95    }
96
97    #[test]
98    fn test_hex_encode() {
99        let t = HexEncode;
100        assert_eq!(t.transform("AB"), "4142");
101    }
102
103    #[test]
104    fn test_md5() {
105        let t = Md5;
106        // MD5 of "hello"
107        assert_eq!(t.transform("hello"), "5d41402abc4b2a76b9719d911017c592");
108    }
109
110    #[test]
111    fn test_sha1() {
112        let t = Sha1;
113        // SHA1 of "hello"
114        assert_eq!(t.transform("hello"), "aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d");
115    }
116}