emissary_core/crypto/
mod.rs1use crate::{
20 crypto::dsa::{DsaPublicKey, DsaSignature},
21 error::Error,
22};
23
24use data_encoding::{Encoding, Specification};
25use ed25519_dalek::Signer;
26use lazy_static::lazy_static;
27use p256::ecdsa::signature::Verifier as _;
28use rand_core::{CryptoRng, RngCore};
29use zeroize::Zeroize;
30
31use alloc::{string::String, vec::Vec};
32use core::convert::TryInto;
33
34pub mod aes;
35pub mod chachapoly;
36pub mod dsa;
37pub mod hmac;
38pub mod noise;
39pub mod sha256;
40pub mod siphash;
41
42lazy_static! {
46 pub static ref I2P_BASE64: Encoding = {
47 let mut spec = Specification::new();
48 spec.symbols
49 .push_str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-~");
50 spec.padding = Some('=');
51 spec.encoding().unwrap()
52 };
53 pub static ref I2P_BASE32: Encoding = {
54 let mut spec = Specification::new();
55 spec.symbols.push_str("abcdefghijklmnopqrstuvwxyz234567");
56 spec.encoding().unwrap()
57 };
58}
59
60pub fn base64_encode<T: AsRef<[u8]>>(data: T) -> String {
62 I2P_BASE64.encode(data.as_ref())
63}
64
65pub fn base64_decode<T: AsRef<[u8]>>(data: T) -> Option<Vec<u8>> {
67 I2P_BASE64.decode(data.as_ref()).ok()
68}
69
70pub fn base32_encode(data: impl AsRef<[u8]>) -> String {
72 I2P_BASE32.encode(data.as_ref())
73}
74
75#[allow(unused)]
77pub fn base32_decode(data: impl AsRef<[u8]>) -> Option<Vec<u8>> {
78 I2P_BASE32.decode(data.as_ref()).ok()
79}
80
81pub trait SecretKey {
83 fn diffie_hellman<T: AsRef<x25519_dalek::PublicKey>>(&self, public_key: &T) -> [u8; 32];
85}
86
87pub enum SigningKeyKind {
91 DsaSha1(usize),
93
94 EcDsaSha256P256(usize),
96
97 EdDsaSha512Ed25519(usize),
99}
100
101impl TryFrom<u16> for SigningKeyKind {
102 type Error = ();
103
104 fn try_from(value: u16) -> Result<Self, Self::Error> {
105 match value {
106 0 => Ok(SigningKeyKind::DsaSha1(128)),
107 1 => Ok(SigningKeyKind::EcDsaSha256P256(64)),
108 7 => Ok(SigningKeyKind::EdDsaSha512Ed25519(32)),
109 _ => Err(()),
110 }
111 }
112}
113
114pub enum PrivateKeyKind {
118 ElGamal(usize),
120
121 P256(usize),
123
124 X25519(usize),
126}
127
128impl TryFrom<u16> for PrivateKeyKind {
129 type Error = ();
130
131 fn try_from(value: u16) -> Result<Self, Self::Error> {
132 match value {
133 0 => Ok(PrivateKeyKind::ElGamal(256)),
134 1 => Ok(PrivateKeyKind::P256(64)),
135 4 => Ok(PrivateKeyKind::X25519(32)),
136 _ => Err(()),
137 }
138 }
139}
140
141#[derive(Debug, Clone)]
143pub enum StaticPublicKey {
144 X25519(x25519_dalek::PublicKey),
146}
147
148impl StaticPublicKey {
149 pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
151 let key: [u8; 32] = bytes.try_into().ok()?;
152
153 Some(Self::X25519(x25519_dalek::PublicKey::from(key)))
154 }
155
156 pub fn to_vec(&self) -> Vec<u8> {
158 match self {
159 Self::X25519(key) => key.to_bytes().to_vec(),
160 }
161 }
162}
163
164impl From<[u8; 32]> for StaticPublicKey {
165 fn from(value: [u8; 32]) -> Self {
166 StaticPublicKey::X25519(x25519_dalek::PublicKey::from(value))
167 }
168}
169
170impl AsRef<[u8]> for StaticPublicKey {
171 fn as_ref(&self) -> &[u8] {
172 match self {
173 Self::X25519(key) => key.as_ref(),
174 }
175 }
176}
177
178impl AsRef<x25519_dalek::PublicKey> for StaticPublicKey {
179 fn as_ref(&self) -> &x25519_dalek::PublicKey {
180 match self {
181 Self::X25519(key) => key,
182 }
183 }
184}
185
186#[derive(Clone)]
188pub enum StaticPrivateKey {
189 X25519(x25519_dalek::StaticSecret),
191}
192
193impl StaticPrivateKey {
194 pub fn random(csprng: impl RngCore + CryptoRng) -> Self {
196 Self::X25519(x25519_dalek::StaticSecret::random_from_rng(csprng))
197 }
198
199 pub fn public(&self) -> StaticPublicKey {
201 match self {
202 Self::X25519(key) => StaticPublicKey::X25519(x25519_dalek::PublicKey::from(key)),
203 }
204 }
205
206 pub fn diffie_hellman<T: AsRef<x25519_dalek::PublicKey>>(&self, public_key: &T) -> Vec<u8> {
208 match self {
209 Self::X25519(key) => key.diffie_hellman(public_key.as_ref()).to_bytes().to_vec(),
210 }
211 }
212
213 pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
215 let key: [u8; 32] = bytes.try_into().ok()?;
216
217 Some(StaticPrivateKey::X25519(x25519_dalek::StaticSecret::from(
218 key,
219 )))
220 }
221}
222
223impl From<[u8; 32]> for StaticPrivateKey {
224 fn from(value: [u8; 32]) -> Self {
225 StaticPrivateKey::X25519(x25519_dalek::StaticSecret::from(value))
226 }
227}
228
229impl AsRef<[u8]> for StaticPrivateKey {
230 fn as_ref(&self) -> &[u8] {
231 match self {
232 Self::X25519(key) => key.as_ref(),
233 }
234 }
235}
236
237impl SecretKey for StaticPrivateKey {
238 fn diffie_hellman<T: AsRef<x25519_dalek::PublicKey>>(&self, public_key: &T) -> [u8; 32] {
239 match self {
240 Self::X25519(key) => key.diffie_hellman(public_key.as_ref()).to_bytes(),
241 }
242 }
243}
244
245pub enum EphemeralPrivateKey {
247 X25519(x25519_dalek::ReusableSecret),
249}
250
251impl EphemeralPrivateKey {
252 pub fn random(csprng: impl RngCore + CryptoRng) -> Self {
254 Self::X25519(x25519_dalek::ReusableSecret::random_from_rng(csprng))
255 }
256
257 pub fn public(&self) -> EphemeralPublicKey {
259 match self {
260 Self::X25519(key) => EphemeralPublicKey::X25519(x25519_dalek::PublicKey::from(key)),
261 }
262 }
263
264 pub fn diffie_hellman<T: AsRef<x25519_dalek::PublicKey>>(&self, public_key: &T) -> Vec<u8> {
266 match self {
267 Self::X25519(key) => key.diffie_hellman(public_key.as_ref()).to_bytes().to_vec(),
268 }
269 }
270
271 pub fn zeroize(self) {
273 match self {
274 Self::X25519(mut key) => key.zeroize(),
275 }
276 }
277}
278
279impl SecretKey for EphemeralPrivateKey {
280 fn diffie_hellman<T: AsRef<x25519_dalek::PublicKey>>(&self, public_key: &T) -> [u8; 32] {
281 match self {
282 Self::X25519(key) => key.diffie_hellman(public_key.as_ref()).to_bytes(),
283 }
284 }
285}
286
287#[derive(Clone)]
289pub enum EphemeralPublicKey {
290 X25519(x25519_dalek::PublicKey),
292}
293
294impl EphemeralPublicKey {
295 pub fn to_vec(&self) -> Vec<u8> {
297 match self {
298 Self::X25519(key) => key.as_bytes().to_vec(),
299 }
300 }
301
302 pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
304 let key: [u8; 32] = bytes.try_into().ok()?;
305
306 Some(Self::X25519(x25519_dalek::PublicKey::from(key)))
307 }
308}
309
310impl AsRef<[u8]> for EphemeralPublicKey {
311 fn as_ref(&self) -> &[u8] {
312 match self {
313 Self::X25519(key) => key.as_ref(),
314 }
315 }
316}
317
318impl AsRef<x25519_dalek::PublicKey> for EphemeralPublicKey {
319 fn as_ref(&self) -> &x25519_dalek::PublicKey {
320 match self {
321 Self::X25519(key) => key,
322 }
323 }
324}
325
326impl Zeroize for EphemeralPublicKey {
327 fn zeroize(&mut self) {
328 match self {
329 Self::X25519(key) => key.zeroize(),
330 }
331 }
332}
333
334#[derive(Clone)]
336pub enum SigningPrivateKey {
337 Ed25519(ed25519_dalek::SigningKey),
339}
340
341impl SigningPrivateKey {
342 pub fn random(mut csprng: impl RngCore + CryptoRng) -> Self {
344 Self::Ed25519(ed25519_dalek::SigningKey::generate(&mut csprng))
345 }
346
347 pub fn from_bytes(key: &[u8]) -> Option<Self> {
349 let key: [u8; 32] = key.to_vec().try_into().ok()?;
350 let key = ed25519_dalek::SigningKey::from_bytes(&key);
351
352 Some(SigningPrivateKey::Ed25519(key))
353 }
354
355 pub fn sign(&self, message: &[u8]) -> Vec<u8> {
357 match self {
358 Self::Ed25519(key) => key.sign(message).to_bytes().to_vec(),
359 }
360 }
361
362 pub fn public(&self) -> SigningPublicKey {
364 match self {
365 Self::Ed25519(key) => SigningPublicKey::Ed25519(key.verifying_key()),
366 }
367 }
368
369 pub fn signature_len(&self) -> usize {
371 match self {
372 Self::Ed25519(_) => 64usize,
373 }
374 }
375}
376
377impl From<[u8; 32]> for SigningPrivateKey {
378 fn from(value: [u8; 32]) -> Self {
379 SigningPrivateKey::Ed25519(ed25519_dalek::SigningKey::from(value))
380 }
381}
382
383impl AsRef<[u8]> for SigningPrivateKey {
384 fn as_ref(&self) -> &[u8] {
385 match self {
386 Self::Ed25519(key) => key.as_bytes(),
387 }
388 }
389}
390
391#[derive(Debug, Clone, PartialEq, Eq)]
393pub enum SigningPublicKey {
394 Ed25519(ed25519_dalek::VerifyingKey),
396
397 P256(p256::EncodedPoint, p256::ecdsa::VerifyingKey),
403
404 DsaSha1(DsaPublicKey),
410}
411
412impl SigningPublicKey {
413 pub fn from_bytes(key: &[u8; 32]) -> Option<Self> {
417 Some(SigningPublicKey::Ed25519(
418 ed25519_dalek::VerifyingKey::from_bytes(key).ok()?,
419 ))
420 }
421
422 pub fn p256(data: &[u8]) -> Option<Self> {
424 let encoded = p256::EncodedPoint::from_untagged_bytes(data.into());
425
426 Some(Self::P256(
427 encoded,
428 p256::ecdsa::VerifyingKey::from_encoded_point(&encoded).ok()?,
429 ))
430 }
431
432 pub fn dsa_sha1(data: &[u8]) -> Option<Self> {
434 DsaPublicKey::from_bytes(data).map(Self::DsaSha1)
435 }
436
437 pub fn verify(&self, message: &[u8], signature: &[u8]) -> crate::Result<()> {
439 match self {
440 Self::Ed25519(key) => {
441 let signature: [u8; 64] = signature.try_into().map_err(|_| Error::InvalidData)?;
442 let signature = ed25519_dalek::Signature::from_bytes(&signature);
443
444 key.verify_strict(message, &signature).map_err(From::from)
445 }
446 Self::P256(_, vk) => {
447 let signature =
448 p256::ecdsa::Signature::try_from(signature).map_err(|_| Error::InvalidData)?;
449
450 vk.verify(message, &signature).map_err(|_| Error::InvalidData)
451 }
452 Self::DsaSha1(public_key) => {
453 let signature = DsaSignature::from_bytes(signature).ok_or(Error::InvalidData)?;
454
455 match public_key.verify(message, &signature) {
456 true => Ok(()),
457 false => Err(Error::InvalidData),
458 }
459 }
460 }
461 }
462
463 pub fn signature_len(&self) -> usize {
465 match self {
466 Self::Ed25519(_) => 64usize,
467 Self::P256(_, _) => 64usize,
468 Self::DsaSha1(_) => 40usize,
469 }
470 }
471}
472
473impl AsRef<[u8]> for SigningPublicKey {
474 fn as_ref(&self) -> &[u8] {
475 match self {
476 Self::Ed25519(key) => key.as_bytes(),
477 Self::P256(pk, _) => &pk.as_bytes()[1..],
478 Self::DsaSha1(key) => key.as_bytes(),
479 }
480 }
481}