1use crate::OqsError;
7use zeroize::Zeroize;
8
9#[cfg(not(feature = "liboqs"))]
10use rand_core::{OsRng, RngCore};
11
12#[cfg(feature = "serde")]
13use serde::{Deserialize, Serialize};
14
15#[derive(Clone, Debug)]
17#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
18pub struct PublicKey(pub(crate) Vec<u8>);
19
20#[derive(Clone, Debug, Zeroize)]
22#[zeroize(drop)]
23#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
24pub struct SecretKey(pub(crate) Vec<u8>);
25
26#[derive(Clone, Debug)]
28#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
29pub struct Ciphertext(pub(crate) Vec<u8>);
30
31#[derive(Clone, Debug)]
33#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
34pub struct SharedSecret(pub(crate) Vec<u8>);
35
36impl PublicKey {
37 #[inline]
38 pub fn as_bytes(&self) -> &[u8] {
39 &self.0
40 }
41 #[inline]
42 pub fn len(&self) -> usize {
43 self.0.len()
44 }
45 #[inline]
46 pub fn is_empty(&self) -> bool {
47 self.0.is_empty()
48 }
49}
50impl SecretKey {
51 #[inline]
52 pub fn as_bytes(&self) -> &[u8] {
53 &self.0
54 }
55 #[inline]
56 pub fn len(&self) -> usize {
57 self.0.len()
58 }
59 #[inline]
60 pub fn is_empty(&self) -> bool {
61 self.0.is_empty()
62 }
63}
64impl Ciphertext {
65 #[inline]
66 pub fn as_bytes(&self) -> &[u8] {
67 &self.0
68 }
69 #[inline]
70 pub fn len(&self) -> usize {
71 self.0.len()
72 }
73 #[inline]
74 pub fn is_empty(&self) -> bool {
75 self.0.is_empty()
76 }
77}
78impl SharedSecret {
79 #[inline]
80 pub fn as_bytes(&self) -> &[u8] {
81 &self.0
82 }
83 #[inline]
84 pub fn len(&self) -> usize {
85 self.0.len()
86 }
87 #[inline]
88 pub fn is_empty(&self) -> bool {
89 self.0.is_empty()
90 }
91}
92
93pub trait Kem {
95 fn keypair() -> Result<(PublicKey, SecretKey), OqsError>;
96 fn encapsulate(pk: &PublicKey) -> Result<(Ciphertext, SharedSecret), OqsError>;
97 fn decapsulate(ct: &Ciphertext, sk: &SecretKey) -> Result<SharedSecret, OqsError>;
98}
99
100pub struct Kyber768;
102
103impl Kem for Kyber768 {
104 fn keypair() -> Result<(PublicKey, SecretKey), OqsError> {
105 #[cfg(feature = "liboqs")]
106 {
107 let (pk, sk) = crate::ffi::kyber768_keypair()?;
108 Ok((PublicKey(pk), SecretKey(sk)))
109 }
110 #[cfg(not(feature = "liboqs"))]
111 {
112 let mut pk = vec![0u8; 1184]; let mut sk = vec![0u8; 2400]; OsRng.fill_bytes(&mut pk);
116 OsRng.fill_bytes(&mut sk);
117 Ok((PublicKey(pk), SecretKey(sk)))
118 }
119 }
120
121 fn encapsulate(pk: &PublicKey) -> Result<(Ciphertext, SharedSecret), OqsError> {
122 #[cfg(feature = "liboqs")]
123 {
124 crate::ffi::kyber768_encapsulate(pk.as_bytes())
125 .map(|(c, s)| (Ciphertext(c), SharedSecret(s)))
126 }
127 #[cfg(not(feature = "liboqs"))]
128 {
129 if pk.len() != 1184 {
130 return Err(OqsError::InvalidLength);
131 }
132 let mut ct = vec![0u8; 1088]; let mut ss = vec![0u8; 32]; OsRng.fill_bytes(&mut ct);
135 OsRng.fill_bytes(&mut ss);
136 Ok((Ciphertext(ct), SharedSecret(ss)))
137 }
138 }
139
140 fn decapsulate(ct: &Ciphertext, sk: &SecretKey) -> Result<SharedSecret, OqsError> {
141 #[cfg(feature = "liboqs")]
142 {
143 crate::ffi::kyber768_decapsulate(ct.as_bytes(), sk.as_bytes()).map(SharedSecret)
144 }
145 #[cfg(not(feature = "liboqs"))]
146 {
147 if ct.len() != 1088 || sk.len() != 2400 {
148 return Err(OqsError::InvalidLength);
149 }
150 let mut ss = vec![0u8; 32];
151 OsRng.fill_bytes(&mut ss);
152 Ok(SharedSecret(ss))
153 }
154 }
155}
156
157#[cfg(feature = "testing")]
159impl PublicKey {
160 pub fn from_bytes_unchecked(bytes: Vec<u8>) -> Self {
162 Self(bytes)
163 }
164}
165#[cfg(feature = "testing")]
166impl SecretKey {
167 pub fn from_bytes_unchecked(bytes: Vec<u8>) -> Self {
169 Self(bytes)
170 }
171}
172#[cfg(feature = "testing")]
173impl Ciphertext {
174 pub fn from_bytes_unchecked(bytes: Vec<u8>) -> Self {
176 Self(bytes)
177 }
178}