1use std::time::SystemTime;
18
19use sp800_185::KMac;
20
21pub fn epoch_now_s() -> u64 {
22 SystemTime::now()
23 .duration_since(SystemTime::UNIX_EPOCH)
24 .expect("Unable to calculate epoch time")
25 .as_secs()
26}
27
28pub fn epoch_now_ms() -> u128 {
29 SystemTime::now()
30 .duration_since(SystemTime::UNIX_EPOCH)
31 .expect("Unable to calculate epoch time")
32 .as_millis()
33}
34
35pub struct SeqMac {
36 mac: KMac,
37 period: u64,
38}
39
40impl SeqMac {
41 pub fn new(psk: &str, port: u16, period: u64) -> Self {
42 let custom = format!("seqknock-v1-{port:05}");
44
45 SeqMac {
46 mac: KMac::new_kmac128(psk.as_bytes(), custom.as_bytes()),
47 period,
48 }
49 }
50
51 pub fn calc(&self, time: u64) -> u32 {
52 let mut mac = self.mac.clone();
53 mac.update(&(time / self.period).to_le_bytes());
54 let mut result: [u8; 4] = [0; 4];
55 mac.xof().squeeze(&mut result);
56 u32::from_le_bytes(result)
57 }
58}
59
60#[cfg(test)]
61mod tests {
62
63 use super::SeqMac;
64
65 #[test]
66 fn key_lengths() {
67 let time = 1672531200;
68
69 let mac_1 = SeqMac::new("a", 1, 1);
70 assert_eq!(mac_1.calc(time), 3568379456);
71 let mac_1025 = SeqMac::new(
73 "iemumahchua4waihauH4eChe7feonohHeimeubah0Hae1Weyaequiech5ohhufaeRahl9uz4shahv8eiceis5efah6iaw3oph6ievol9ohSeeXiocheishel5tuc4logaluoF7eeraetaiwoe3aih5eetee9hoo0iSh4phietha9aix7nohkaibohv6aesu9Dieviulu9Jeil3Ahmah9Aifohk4ahphae8eiKaechei1cie6aehoor9ofu1goo9ahfoo9shaa4aey2obaechai5oopeig6ailoovaeFouv3kihishaeChohPie8eigeeH2eod9ohvah6zue2ca4eGhaimiethiengoongeethemei9nee0IjieBahlik5riekiyaiphahb3lu0hee6otievie6go8Aijohng8ce5ooshophoda2Eunaepeethaecopae1Thuwaeyahpooz9ez7thi3lieL2Eope5air7iet2voh1lah9Oa5poo0eehohzai7rahPhaeghozaex6Eim4Soo7ChooceeNg8Gai6Air1wi5roogeeweic7ohngiewaiGohphoomee0ahdiree9Bedaibah4ook6sujae1oaxughei1quahphee6mohMeoP8hohaeng8niiXiethohchah1ootie4ibai4zaeceex8Iebaem1gu8keG7ing3rahchahHeihieteeQuohjeib1ia5Zie8so1pou2doohi9eelaejixoje2eegh1lee9ohdingaQueecai1aez0eexaez3el2ieB7ievooleefohg3Aidi4kieRoo9eicheiH0DoBohngaeshaigh6Biey8eecooyahchahgh9yoo8aiSho9Pho1aeWi0ohxohs1Kewah8aey2iho7oboh4jied1Ooquool0uel7eeg6roothai8Ahfoo8deh5ahqua7Zipaish7Rooxae7zeeGa6ja8iecoo4Goo8uequei7bohngiyohFoh2uCu8eingi",
74 1,
75 1,
76 );
77 assert_eq!(mac_1025.calc(time), 2346448994);
78 let mac_0 = SeqMac::new("", 1, 1);
80 assert_eq!(mac_0.calc(time), 4132275335);
81 }
82
83 #[test]
84 fn with_static_macs() {
85 let mac_asdf_29 = SeqMac::new("asdf", 22, 29);
86 let mac_asdf_30 = SeqMac::new("asdf", 22, 30);
87 let mac_asdf_31 = SeqMac::new("asdf", 22, 31);
88 let mac_asde_30 = SeqMac::new("asde", 22, 30);
89 let mac_asdf_23_30 = SeqMac::new("asdf", 23, 30);
90 let mac_asdf_30_2 = SeqMac::new("asdf", 22, 30);
91 let time = 1672531200;
92
93 assert_eq!(mac_asdf_29.calc(time), mac_asdf_29.calc(time));
95 assert_eq!(mac_asdf_30.calc(time), mac_asdf_30.calc(time));
96 assert_eq!(mac_asdf_31.calc(time), mac_asdf_31.calc(time));
97
98 assert_eq!(mac_asdf_30.calc(time), mac_asdf_30_2.calc(time));
100
101 assert_ne!(mac_asdf_30.calc(time), mac_asde_30.calc(time));
103
104 assert_ne!(mac_asdf_30.calc(time), mac_asdf_30.calc(time + 30));
106 assert_ne!(mac_asdf_30.calc(time), mac_asdf_30.calc(time - 30));
107
108 assert_ne!(mac_asdf_30.calc(time), mac_asdf_29.calc(time));
110 assert_ne!(mac_asdf_30.calc(time), mac_asdf_31.calc(time));
111
112 let result0 = mac_asdf_30.calc(time);
114 let mut offset1 = 1;
115 loop {
117 if result0 != mac_asdf_30.calc(time + offset1) {
118 break;
119 }
120 offset1 += 1;
121 }
122 let result1 = mac_asdf_30.calc(time + offset1);
123 let mut offset2 = 1;
124 loop {
126 if result1 != mac_asdf_30.calc(time + offset1 + offset2) {
127 break;
128 }
129 offset2 += 1;
130 }
131 assert_eq!(offset2, 30);
133
134 assert_ne!(mac_asdf_30.calc(time), mac_asdf_23_30.calc(time));
136
137 assert_eq!(mac_asdf_29.calc(time), 2407226594);
139 assert_eq!(mac_asdf_30.calc(time), 2237033466);
140 assert_eq!(mac_asdf_31.calc(time), 967110946);
141 }
142}