simple_encryption/
lib.rs

1// extern crate crypto;
2extern crate rand;
3use std::error;
4
5// pub mod pq;
6use chacha20poly1305::aead::Aead;
7use chacha20poly1305::{ChaCha20Poly1305, KeyInit, Nonce};
8// use curve25519_dalek::ristretto::CompressedRistretto;
9// use ed25519_dalek::SigningKey;
10use thiserror::Error;
11
12use rand::RngCore;
13use rand::{rngs::OsRng, Rng};
14use x25519_dalek::x25519;
15// use crypto::curve25519::{curve25519_base, curve25519};
16// use crypto::chacha20poly1305::ChaCha20Poly1305;
17// use crypto::aead::{AeadEncryptor, AeadDecryptor};
18#[derive(Error, Debug)]
19pub enum EncryptError {
20    // #[error("rng init failed")]
21    // RngInitializationFailed,
22    #[error("encryption failed")]
23    EncryptionFailure,
24}
25pub fn x25519_base(a: [u8; 32]) -> [u8; 32] {
26    return x25519(a, x25519_dalek::X25519_BASEPOINT_BYTES);
27}
28
29pub fn encrypt(
30    public_key: &[u8; 32],
31    message: &[u8],
32    mut rng: impl Rng,
33) -> Result<Vec<u8>, EncryptError> {
34    // let mut rng = OsRng::default();
35
36    let mut ephemeral_secret_key = [0u8; 32];
37    rng.fill_bytes(&mut ephemeral_secret_key[..]);
38
39    let ephemeral_public_key: [u8; 32] = x25519_base(ephemeral_secret_key);
40    let symmetric_key = x25519_dalek::x25519(ephemeral_secret_key, *public_key);
41
42    let mut c = ChaCha20Poly1305::new_from_slice(&symmetric_key).unwrap();
43
44    let mut output = vec![0; 32 + 16];
45    let mut tag: [u8; 16] = rng.gen();
46    output.append(
47        &mut c
48            .encrypt(&Nonce::from_slice(&tag[..12]), message)
49            .map_err(|_| EncryptError::EncryptionFailure)?,
50    );
51    // c.encrypt(message, , &mut tag[..]);
52
53    for (dest, src) in (&mut output[0..32])
54        .iter_mut()
55        .zip(ephemeral_public_key.iter())
56    {
57        *dest = *src;
58    }
59
60    for (dest, src) in (&mut output[32..48]).iter_mut().zip(tag.iter()) {
61        *dest = *src;
62    }
63
64    Ok(output)
65}
66#[derive(Error, Debug)]
67pub enum DecryptError {
68    #[error("malformed input")]
69    Malformed,
70    #[error("invalid input")]
71    Invalid,
72}
73
74pub fn decrypt(secret_key: &[u8; 32], message: &[u8]) -> Result<Vec<u8>, DecryptError> {
75    if message.len() < 48 {
76        return Err(DecryptError::Malformed);
77    }
78
79    let ephemeral_public_key = (&message[0..32]).try_into().unwrap();
80    let tag = &message[32..48];
81    let ciphertext = &message[48..];
82
83    let mut plaintext = vec![0; ciphertext.len()];
84    let symmetric_key = x25519(*secret_key, ephemeral_public_key);
85
86    let mut decrypter = ChaCha20Poly1305::new_from_slice(&symmetric_key).unwrap();
87    // if !decrypter.decrypt(ciphertext, &mut plaintext[..], tag) {
88    //     return Err(DecryptError::Invalid);
89    // }
90
91    // Ok(plaintext)
92    return decrypter
93        .decrypt(&Nonce::from_slice(&tag[..12]), ciphertext)
94        .map_err(|e| DecryptError::Invalid);
95}