]> git.lizzy.rs Git - PAKEs.git/blob - srp/src/types.rs
2021 edition bump + doc improvements; MSRV 1.56 (#80)
[PAKEs.git] / srp / src / types.rs
1 //! Additional SRP types.
2 use digest::Digest;
3 use num_bigint::BigUint;
4 use std::{error, fmt};
5
6 /// SRP authentication error.
7 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
8 pub struct SrpAuthError {
9     pub(crate) description: &'static str,
10 }
11
12 impl fmt::Display for SrpAuthError {
13     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14         write!(f, "SRP authentication error")
15     }
16 }
17
18 impl error::Error for SrpAuthError {
19     fn description(&self) -> &str {
20         self.description
21     }
22 }
23
24 /// Group used for SRP computations
25 #[derive(Debug, Clone, Eq, PartialEq)]
26 pub struct SrpGroup {
27     /// A large safe prime (N = 2q+1, where q is prime)
28     pub n: BigUint,
29     /// A generator modulo N
30     pub g: BigUint,
31 }
32
33 impl SrpGroup {
34     pub(crate) fn modpow(&self, v: &BigUint) -> BigUint {
35         self.g.modpow(v, &self.n)
36     }
37
38     /// Compute `k` with given hash function and return SRP parameters
39     pub(crate) fn compute_k<D: Digest>(&self) -> BigUint {
40         let n = self.n.to_bytes_be();
41         let g_bytes = self.g.to_bytes_be();
42         let mut buf = vec![0u8; n.len()];
43         let l = n.len() - g_bytes.len();
44         buf[l..].copy_from_slice(&g_bytes);
45
46         let mut d = D::new();
47         d.update(&n);
48         d.update(&buf);
49         BigUint::from_bytes_be(d.finalize().as_slice())
50     }
51
52     /// Compute `Hash(N) xor Hash(g)` with given hash function and return SRP parameters
53     pub(crate) fn compute_hash_n_xor_hash_g<D: Digest>(&self) -> Vec<u8> {
54         let n = self.n.to_bytes_be();
55         let g_bytes = self.g.to_bytes_be();
56         let mut buf = vec![0u8; n.len()];
57         let l = n.len() - g_bytes.len();
58         buf[l..].copy_from_slice(&g_bytes);
59
60         let mut d = D::new();
61         d.update(&n);
62         let h = d.finalize_reset();
63         let h_n: &[u8] = h.as_slice();
64         d.update(&buf);
65         let h = d.finalize_reset();
66         let h_g: &[u8] = h.as_slice();
67
68         h_n.iter()
69             .zip(h_g.iter())
70             .map(|(&x1, &x2)| x1 ^ x2)
71             .collect()
72     }
73 }
74
75 #[cfg(test)]
76 mod tests {
77     use crate::groups::G_1024;
78     use sha1::Sha1;
79
80     #[test]
81     fn test_k_1024_sha1() {
82         let k = G_1024.compute_k::<Sha1>().to_bytes_be();
83         assert_eq!(&k, include_bytes!("k_sha1_1024.bin"));
84     }
85 }