1#![no_std]
93#![warn(missing_docs)]
94
95#[cfg(feature = "alloc")]
96extern crate alloc;
97
98#[cfg(test)]
99#[macro_use]
100extern crate std;
101
102#[cfg(feature = "b64")]
103mod b64;
104
105#[cfg(feature = "dalek_module")]
106#[doc(hidden)]
107pub mod dalek;
108#[cfg(feature = "sodium_module")]
109#[doc(hidden)]
110pub mod sodium;
111
112mod hash;
113pub use hash::*;
114
115mod auth;
116pub use auth::*;
117
118mod sign;
119pub use sign::*;
120
121pub mod ephemeral;
122pub mod secretbox;
123pub mod utils;
124
125pub use zerocopy::{AsBytes, FromBytes};
126
127#[cfg(all(test, any(feature = "sodium", feature = "dalek")))]
128mod tests {
129 #[allow(unused_imports)]
130 use crate::{ephemeral::*, Keypair, PublicKey};
131
132 #[test]
133 #[cfg(any(feature = "sodium", feature = "getrandom"))]
134 fn shared_secret_with_zero() {
135 let (c_eph_pk, _) = generate_ephemeral_keypair();
136 let c_keys = Keypair::generate();
137
138 let (_, s_eph_sk) = generate_ephemeral_keypair();
139 let s_keys = Keypair::generate();
140
141 assert!(derive_shared_secret(&s_eph_sk, &c_eph_pk).is_some());
142 assert!(derive_shared_secret_pk(&s_eph_sk, &c_keys.public).is_some());
146 let zero_pk = PublicKey([0; PublicKey::SIZE]);
147 assert!(derive_shared_secret_pk(&s_eph_sk, &zero_pk).is_none());
148
149 assert!(derive_shared_secret_sk(&s_keys.secret, &c_eph_pk).is_some());
150 }
152}
153
154#[cfg(all(
155 test,
156 any(feature = "sodium", feature = "dalek"),
157 all(feature = "dalek_module", feature = "sodium_module")
158))]
159mod dalek_vs_sodium {
160 #[cfg(any(feature = "force_sodium", not(feature = "dalek")))]
161 use crate::dalek as other;
162 #[cfg(all(feature = "dalek", not(feature = "force_sodium")))]
163 use crate::sodium as other;
164
165 use crate::dalek;
166 use crate::sodium;
167 use crate::Keypair;
168
169 #[test]
170 #[cfg(any(feature = "sodium", feature = "getrandom"))]
171 fn auth() {
172 use crate::{ephemeral::*, NetworkKey};
173
174 let (pk, _sk) = generate_ephemeral_keypair();
175 let netkey = NetworkKey::SSB_MAIN_NET;
176 let auth = netkey.authenticate(&pk.0);
177 let auth2 = other::auth::authenticate(&netkey, &pk.0);
178 assert_eq!(auth.0, auth2.0);
179
180 assert!(netkey.verify(&auth, &pk.0));
181 assert!(other::auth::verify(&netkey, &auth, &pk.0));
182 }
183
184 #[test]
185 fn auth_test_vecs() {
186 use crate::NetworkKey;
187 use hmac::{Hmac, Mac, NewMac};
188 use sha2::Sha512;
189
190 let key = NetworkKey([
191 74, 101, 102, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
192 0, 0, 0, 0, 0,
193 ]);
194 let c = [
195 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20, 0x79, 0x61, 0x20, 0x77, 0x61, 0x6e,
196 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x3f,
197 ];
198
199 let a_expected = [
200 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, 0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56,
201 0xe0, 0xa3, 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6, 0x10, 0x27, 0x0c, 0xd7,
202 0xea, 0x25, 0x05, 0x54,
203 ];
204 let a1 = sodium::auth::authenticate(&key, &c);
205 assert_eq!(a1.0, a_expected);
206
207 let mut mac = Hmac::<Sha512>::new_varkey(&key.0).unwrap();
208 mac.update(&c);
209 assert_eq!(mac.finalize().into_bytes().as_ref()[..32], a_expected);
210
211 let a2 = dalek::auth::authenticate(&key, &c);
212 assert_eq!(a2.0, a_expected);
213 }
214 #[test]
215 fn hash() {
216 let m = "hello this is a message".as_bytes();
217 assert_eq!(crate::hash::hash(m), other::hash::hash(m));
218 }
219
220 #[test]
221 #[cfg(any(feature = "sodium", feature = "getrandom"))]
222 fn sign() {
223 let m = "hello this is a message".as_bytes();
224 let kp = Keypair::generate();
225 let sig1 = kp.sign(m);
226 let sig2 = other::sign::sign(&kp, m);
227
228 assert_eq!(sig1, sig2);
229 assert!(kp.public.verify(&sig1, m));
230 assert!(other::sign::verify(&kp.public, &sig1, m));
231 }
232
233 #[test]
234 fn sign_test_vecs() {
235 use hex::decode;
236
237 let vecs = [("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60",
238 "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a",
239 "",
240 "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b"),
241 ("833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42",
242 "ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf",
243 "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
244 "dc2a4459e7369633a52b1bf277839a00201009a3efbf3ecb69bea2186c26b58909351fc9ac90b3ecfdfbc7c66431e0303dca179c138ac17ad9bef1177331a704")];
245
246 for (sk, pk, msg, sig) in &vecs {
247 let sk = decode(sk).unwrap();
248 let pk = decode(pk).unwrap();
249 let msg = decode(msg).unwrap();
250 let sig = decode(sig).unwrap();
251
252 let s_k = sodium::sign::keypair_from_seed(&sk).unwrap();
253 let d_k = dalek::sign::keypair_from_seed(&sk).unwrap();
254
255 assert_eq!(s_k.public, d_k.public);
256 assert_eq!(&s_k.public.0, &pk[..]);
257 assert_eq!(s_k.secret.0, d_k.secret.0);
258
259 let sig1 = s_k.sign(&msg);
260 let sig2 = d_k.sign(&msg);
261 dbg!(sig1);
262 dbg!(sig2);
263 assert_eq!(sig1, sig2);
264 assert_eq!(&sig[..], &sig1.0[..]);
265 assert!(s_k.public.verify(&sig1, &msg));
266 assert!(d_k.public.verify(&sig1, &msg));
267 }
268 }
269
270 #[test]
271 fn ephemeral() {
272 use dalek::ephemeral as dal;
273 use sodium::ephemeral as sod;
274 use x25519_dalek as x25519;
275
276 let (xp, xs) = sod::generate_ephemeral_keypair();
277 let (yp, ys) = sod::generate_ephemeral_keypair();
278
279 let xs2 = x25519::StaticSecret::from(xs.0);
280 let xp2 = x25519::PublicKey::from(&xs2);
281 assert_eq!(&xp.0, xp2.as_bytes());
282
283 let ys2 = x25519::StaticSecret::from(ys.0);
284 let yp2 = x25519::PublicKey::from(&ys2);
285 let yp3 = x25519::PublicKey::from(yp.0);
286 assert_eq!(&yp.0, yp2.as_bytes());
287 assert_eq!(&yp.0, yp3.as_bytes());
288
289 let dh = xs2.diffie_hellman(&yp2);
290 let sod_secret = sod::derive_shared_secret(&xs, &yp).unwrap();
291 let dal_secret = dal::derive_shared_secret(&xs, &yp).unwrap();
292 assert_eq!(&sod_secret.0, dh.as_bytes());
293 assert_eq!(&dal_secret.0, dh.as_bytes());
294
295 let dh = ys2.diffie_hellman(&xp2);
296 let sod_secret = sod::derive_shared_secret(&ys, &xp).unwrap();
297 let dal_secret = dal::derive_shared_secret(&ys, &xp).unwrap();
298 assert_eq!(&sod_secret.0, dh.as_bytes());
299 assert_eq!(&dal_secret.0, dh.as_bytes());
300 }
301}