crypto.rs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. // Minimal implementation of ECIES with x25519_dalek
  2. use aes_gcm::{
  3. aead::{Aead, AeadCore},
  4. Aes256Gcm, Key, KeyInit, Nonce,
  5. };
  6. use hkdf::Hkdf;
  7. use serde::{Deserialize, Serialize};
  8. use sha3::Sha3_256;
  9. use x25519_dalek::{EphemeralSecret, PublicKey, StaticSecret};
  10. const SALT_STRING: &str = "ECIES symmetric key for Troll Patrol";
  11. #[derive(Serialize, Deserialize)]
  12. pub struct EciesCiphertext {
  13. pubkey: PublicKey,
  14. nonce: Vec<u8>,
  15. ct: Vec<u8>,
  16. }
  17. impl EciesCiphertext {
  18. pub fn encrypt(message: &[u8], receiver_pubkey: &PublicKey) -> Result<Self, String> {
  19. // Compute shared secret based on new ephemeral ECDH key
  20. let mut rng = rand::thread_rng();
  21. let secret = EphemeralSecret::random_from_rng(&mut rng);
  22. let client_pubkey = PublicKey::from(&secret);
  23. let shared_secret = secret.diffie_hellman(&receiver_pubkey);
  24. // Compute key
  25. let hk = Hkdf::<Sha3_256>::new(None, shared_secret.as_bytes());
  26. let mut symmetric_key = [0u8; 32];
  27. if hk
  28. .expand(SALT_STRING.as_bytes(), &mut symmetric_key)
  29. .is_err()
  30. {
  31. return Err("Failed to encrypt".to_string());
  32. }
  33. // Encrypt with key
  34. let key: Key<Aes256Gcm> = symmetric_key.into();
  35. let cipher = Aes256Gcm::new(&key);
  36. let nonce = Aes256Gcm::generate_nonce(&mut rng);
  37. match cipher.encrypt(&nonce, &*message) {
  38. Ok(ct) => Ok(EciesCiphertext {
  39. pubkey: client_pubkey,
  40. nonce: nonce.to_vec(),
  41. ct: ct,
  42. }),
  43. Err(_) => Err("Failed to encrypt".to_string()),
  44. }
  45. }
  46. pub fn decrypt(self, secret: &StaticSecret) -> Result<Vec<u8>, String> {
  47. // Compute shared secret
  48. let shared_secret = secret.diffie_hellman(&self.pubkey);
  49. // Compute key
  50. let hk = Hkdf::<Sha3_256>::new(None, shared_secret.as_bytes());
  51. let mut symmetric_key = [0u8; 32];
  52. if hk
  53. .expand(SALT_STRING.as_bytes(), &mut symmetric_key)
  54. .is_err()
  55. {
  56. return Err("Failed to decrypt".to_string());
  57. }
  58. // Decrypt with key
  59. let key: Key<Aes256Gcm> = symmetric_key.into();
  60. let cipher = Aes256Gcm::new(&key);
  61. let nonce = Nonce::from_slice(&self.nonce);
  62. match cipher.decrypt(nonce, &*self.ct) {
  63. Ok(m) => Ok(m),
  64. Err(_) => Err("Failed to decrypt".to_string()),
  65. }
  66. }
  67. }