1use crate::error::Result;
6use zeroize::{Zeroize, ZeroizeOnDrop};
7
8pub trait Kem {
10 fn generate_keypair(&self) -> Result<KemKeypair>;
12
13 fn encapsulate(&self, public_key: &KemPublicKey) -> Result<(Vec<u8>, Vec<u8>)>;
15
16 fn decapsulate(&self, secret_key: &KemSecretKey, ciphertext: &[u8]) -> Result<Vec<u8>>;
18}
19
20pub struct KemKeypair {
22 pub public_key: KemPublicKey,
23 pub secret_key: KemSecretKey,
24}
25
26#[derive(Clone, Debug, PartialEq, Eq)]
28pub struct KemPublicKey {
29 pub data: Vec<u8>,
30}
31
32#[derive(Zeroize, ZeroizeOnDrop)]
34pub struct KemSecretKey {
35 pub data: Vec<u8>,
36}
37
38impl KemKeypair {
39 pub fn new(public_key: Vec<u8>, secret_key: Vec<u8>) -> Self {
50 Self {
51 public_key: KemPublicKey { data: public_key },
52 secret_key: KemSecretKey { data: secret_key },
53 }
54 }
55
56 pub fn public_key(&self) -> &KemPublicKey {
58 &self.public_key
59 }
60
61 pub fn secret_key(&self) -> &KemSecretKey {
63 &self.secret_key
64 }
65}
66
67impl KemPublicKey {
68 pub fn new(data: Vec<u8>) -> Self {
70 Self { data }
71 }
72
73 pub fn data(&self) -> &[u8] {
75 &self.data
76 }
77
78 pub fn size(&self) -> usize {
80 self.data.len()
81 }
82}
83
84impl KemSecretKey {
85 pub fn new(data: Vec<u8>) -> Self {
87 Self { data }
88 }
89
90 pub fn data(&self) -> &[u8] {
92 &self.data
93 }
94
95 pub fn size(&self) -> usize {
97 self.data.len()
98 }
99}
100
101impl std::fmt::Debug for KemSecretKey {
103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104 f.debug_struct("KemSecretKey")
105 .field("data", &"[REDACTED]")
106 .field("size", &self.data.len())
107 .finish()
108 }
109}
110
111impl PartialEq for KemSecretKey {
113 fn eq(&self, other: &Self) -> bool {
114 if self.data.len() != other.data.len() {
115 return false;
116 }
117
118 let mut result = 0u8;
120 for (a, b) in self.data.iter().zip(other.data.iter()) {
121 result |= a ^ b;
122 }
123 result == 0
124 }
125}
126
127impl Eq for KemSecretKey {}
128
129impl Zeroize for KemKeypair {
131 fn zeroize(&mut self) {
132 self.secret_key.zeroize();
133 }
134}
135
136impl Drop for KemKeypair {
138 fn drop(&mut self) {
139 self.zeroize();
140 }
141}
142
143#[cfg(test)]
144mod tests {
145 use super::*;
146
147 #[test]
148 fn test_kem_keypair_creation() {
149 let public_key = vec![1, 2, 3, 4];
150 let secret_key = vec![5, 6, 7, 8];
151
152 let keypair = KemKeypair::new(public_key.clone(), secret_key.clone());
153
154 assert_eq!(keypair.public_key.data, public_key);
155 assert_eq!(keypair.secret_key.data, secret_key);
156 }
157
158 #[test]
159 fn test_kem_public_key() {
160 let data = vec![1, 2, 3, 4];
161 let public_key = KemPublicKey::new(data.clone());
162
163 assert_eq!(public_key.data(), &data);
164 assert_eq!(public_key.size(), 4);
165 }
166
167 #[test]
168 fn test_kem_secret_key() {
169 let data = vec![1, 2, 3, 4];
170 let secret_key = KemSecretKey::new(data.clone());
171
172 assert_eq!(secret_key.data(), &data);
173 assert_eq!(secret_key.size(), 4);
174 }
175
176 #[test]
177 fn test_secret_key_constant_time_comparison() {
178 let key1 = KemSecretKey::new(vec![1, 2, 3, 4]);
179 let key2 = KemSecretKey::new(vec![1, 2, 3, 4]);
180 let key3 = KemSecretKey::new(vec![1, 2, 3, 5]);
181
182 assert_eq!(key1, key2);
183 assert_ne!(key1, key3);
184 }
185}