Implement code generation
This commit is contained in:
parent
232ac3d35c
commit
85c4826782
6 changed files with 59 additions and 7 deletions
|
@ -11,3 +11,5 @@ publish = false
|
|||
anyhow = { version = "1.0.71", default-features = false, features = ["std"] }
|
||||
clap = { version = "4.3.11", default-features = false, features = ["derive", "std"] }
|
||||
data-encoding = { version = "2.4.0", default-features = false, features = ["std"] }
|
||||
hmac = { version = "0.12.1", default-features = false }
|
||||
sha2 = { version = "0.10.7", default-features = false, features = ["std", "asm"] }
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::code::generate_code;
|
||||
use anyhow::{ensure, Error, Result};
|
||||
use data_encoding::{BASE32_NOPAD, BASE64};
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
@ -9,6 +10,7 @@ pub struct CodedAddress {
|
|||
sub_addr: Option<String>,
|
||||
code: Vec<u8>,
|
||||
domain: Option<String>,
|
||||
separator: char,
|
||||
}
|
||||
|
||||
impl CodedAddress {
|
||||
|
@ -38,6 +40,7 @@ impl CodedAddress {
|
|||
sub_addr,
|
||||
code,
|
||||
domain,
|
||||
separator,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -51,8 +54,20 @@ pub struct KeyedAddress {
|
|||
|
||||
impl KeyedAddress {
|
||||
pub fn check_code(&self, addr: &CodedAddress) -> bool {
|
||||
// TODO
|
||||
false
|
||||
if addr.local_part.is_empty() || self.key.is_empty() {
|
||||
return false;
|
||||
}
|
||||
match &addr.sub_addr {
|
||||
Some(sub_addr) => {
|
||||
if !sub_addr.is_empty() {
|
||||
addr.code
|
||||
== generate_code(&addr.local_part, addr.separator, sub_addr, &self.key)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
32
src/code.rs
Normal file
32
src/code.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use hmac::{Hmac, Mac};
|
||||
use sha2::Sha256;
|
||||
|
||||
const NB_BYTES: usize = 5;
|
||||
|
||||
pub fn generate_code(local_part: &str, separator: char, sub_addr: &str, key: &[u8]) -> Vec<u8> {
|
||||
// Compute the HMAC-SHA-256
|
||||
let mut hmac = Hmac::<Sha256>::new_from_slice(key).unwrap();
|
||||
hmac.update(local_part.as_bytes());
|
||||
hmac.update(separator.to_string().as_bytes());
|
||||
hmac.update(sub_addr.as_bytes());
|
||||
let result = hmac.finalize().into_bytes();
|
||||
|
||||
// Reduce the result to NB_BYTES using a dynamic offset truncation
|
||||
let offset = (result[result.len() - 1] & 0xf) as usize;
|
||||
result[offset..offset + NB_BYTES].to_vec()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::generate_code;
|
||||
|
||||
#[test]
|
||||
fn code_generation() {
|
||||
let key: &[u8] = &[
|
||||
0xd7, 0x5b, 0xe8, 0x89, 0xe7, 0xca, 0xe4, 0xf8, 0x02, 0x5f, 0x91, 0x75, 0x4d, 0x37,
|
||||
0x2e, 0xa1,
|
||||
];
|
||||
let code = generate_code("a", '+', "test", key);
|
||||
assert_eq!(code, vec![0x7d, 0xd8, 0xd7, 0x1c, 0x8e]);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
use std::process::ExitCode;
|
||||
|
||||
mod address;
|
||||
mod code;
|
||||
mod config;
|
||||
mod input;
|
||||
mod service;
|
||||
|
|
|
@ -95,15 +95,13 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_valid_code_domain() {
|
||||
assert!(run_test_with_addr("a+test+TODO@example.org"));
|
||||
assert!(run_test_with_addr("a+test+pxmnoheo@example.org"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_valid_code_no_domain() {
|
||||
assert!(run_test_with_addr("b+test+TODO@example.org"));
|
||||
assert!(run_test_with_addr("b+test+uivojtoa@example.org"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -122,8 +122,12 @@ def get_maildir():
|
|||
def start_tests(test_dir, smtp_port):
|
||||
to_addrs = [
|
||||
("test@example.org", True),
|
||||
("test@nope.example.org", False),
|
||||
("a@example.com", True),
|
||||
("a+anything@example.com", True),
|
||||
("a+anything+test@example.com", True),
|
||||
("a+test+pxmnoheo@example.org", True),
|
||||
("b+test+uivojtoa@example.org", True),
|
||||
("test@nope.example.org", False),
|
||||
("a@example.org", False),
|
||||
("a+invalid@example.org", False),
|
||||
("a+invalid+input@example.org", False),
|
||||
|
|
Loading…
Reference in a new issue