integrationos_domain/algebra/
hash.rs1use crate::{hashed_secret::HashedSecret, IntegrationOSError, InternalError};
2use serde_json::Value;
3use sha3::{Digest, Keccak256};
4
5pub trait HashExt {
6 fn hash(&self, value: &str) -> Result<String, IntegrationOSError>;
7 fn verify(&self, value: &str, hash: &str) -> bool;
8}
9
10pub struct HashKecAlg;
11
12impl HashKecAlg {
13 pub fn new() -> Self {
14 HashKecAlg
15 }
16}
17
18impl Default for HashKecAlg {
19 fn default() -> Self {
20 Self::new()
21 }
22}
23
24impl HashExt for HashKecAlg {
25 fn hash(&self, value: &str) -> Result<String, IntegrationOSError> {
26 let mut hasher = Keccak256::new();
27 hasher.update(value);
28 Ok(format!("{:x}", hasher.finalize()))
29 }
30
31 fn verify(&self, value: &str, hash: &str) -> bool {
32 self.hash(value).ok().map_or(false, |h| h == hash)
33 }
34}
35
36impl TryFrom<Value> for HashedSecret {
37 type Error = IntegrationOSError;
38
39 fn try_from(value: Value) -> Result<Self, Self::Error> {
40 let value_str = serde_json::to_string(&value).map_err(|err| {
41 InternalError::serialize_error(&format!("Failed to serialize value: {err}"), None)
42 })?;
43 let hash = HashKecAlg::new().hash(&value_str)?;
44 Ok(HashedSecret::new(hash))
45 }
46}
47
48#[cfg(test)]
49mod test {
50 use super::*;
51 use serde_json::json;
52
53 #[test]
54 fn test_keccak256_hash() {
55 let value = json!({
56 "response": {
57 "user": {
58 "name": "Alice",
59 "age": 3
60 }
61 }
62 });
63
64 let hash = HashKecAlg::new().hash(&value.to_string()).unwrap();
65
66 assert_eq!(
67 hash,
68 "eb42c0c05a0ac6cd15e4cf907a6aa913ebfe6aea79ee7edd054b519435f827cb"
69 );
70 }
71
72 #[test]
73 fn test_keccak256_verify() {
74 let value = json!({
75 "response": {
76 "user": {
77 "name": "Alice",
78 "age": 3
79 }
80 }
81 });
82
83 let hash = HashKecAlg::new().hash(&value.to_string()).unwrap();
84
85 assert!(HashKecAlg::new().verify(&value.to_string(), &hash));
86 }
87
88 #[test]
89 fn test_hash_from_value() {
90 let value = json!({
91 "response": {
92 "user": {
93 "name": "Alice",
94 "age": 3
95 }
96 }
97 });
98
99 let hash = HashedSecret::try_from(value).unwrap();
100
101 assert_eq!(
102 hash.inner(),
103 "eb42c0c05a0ac6cd15e4cf907a6aa913ebfe6aea79ee7edd054b519435f827cb"
104 );
105 }
106}