1use crate::{BSVErrors, Hash, PrivateKey, PublicKey, AES};
2use elliptic_curve::sec1::ToEncodedPoint;
3use k256::PublicKey as K256PublicKey;
4
5pub mod ecies_ciphertext;
6pub use ecies_ciphertext::*;
7
8#[derive(Clone)]
13pub struct ECIES {}
14
15#[derive(Clone)]
16pub struct CipherKeys {
17 pub(crate) iv: Vec<u8>,
18 pub(crate) ke: Vec<u8>,
19 pub(crate) km: Vec<u8>,
20}
21
22impl CipherKeys {
23 pub fn get_iv(&self) -> Vec<u8> {
24 self.iv.clone()
25 }
26
27 pub fn get_ke(&self) -> Vec<u8> {
28 self.ke.clone()
29 }
30
31 pub fn get_km(&self) -> Vec<u8> {
32 self.km.clone()
33 }
34}
35
36impl ECIES {
37 pub(crate) fn encrypt_impl(message: &[u8], private_key: &PrivateKey, recipient_pub_key: &PublicKey, exclude_pub_key: bool) -> Result<ECIESCiphertext, BSVErrors> {
38 let cipher = ECIES::derive_cipher_keys_impl(private_key, recipient_pub_key)?;
39 let cipher_text = AES::encrypt_impl(&cipher.ke, &cipher.iv, message, crate::AESAlgorithms::AES128_CBC)?;
40
41 let mut buffer: Vec<u8> = Vec::new();
42 buffer.extend_from_slice(b"BIE1");
43
44 let r_buf = match exclude_pub_key {
45 true => None,
46 false => {
47 let pub_key = private_key.to_public_key_impl()?.to_compressed_impl()?.to_bytes_impl()?;
48 buffer.extend_from_slice(&pub_key);
49 Some(pub_key)
50 }
51 };
52 buffer.extend_from_slice(&cipher_text);
53
54 let hmac = Hash::sha_256_hmac(&buffer, &cipher.km).to_bytes();
55
56 Ok(ECIESCiphertext {
57 ciphertext_bytes: cipher_text,
58 public_key_bytes: r_buf,
59 hmac_bytes: hmac,
60 keys: Some(cipher),
61 })
62 }
63
64 pub(crate) fn encrypt_with_ephemeral_private_key_impl(message: &[u8], recipient_pub_key: &PublicKey) -> Result<ECIESCiphertext, BSVErrors> {
69 let private_key = PrivateKey::from_random();
70 ECIES::encrypt_impl(message, &private_key, recipient_pub_key, false)
71 }
72
73 pub(crate) fn decrypt_impl(ciphertext: &ECIESCiphertext, recipient_priv_key: &PrivateKey, sender_pub_key: &PublicKey) -> Result<Vec<u8>, BSVErrors> {
74 let cipher_keys = ECIES::derive_cipher_keys_impl(recipient_priv_key, sender_pub_key)?;
75
76 let hmac = &ciphertext.hmac_bytes;
77
78 let mut preimage = b"BIE1".to_vec();
79 if let Some(pk) = &ciphertext.public_key_bytes {
80 preimage.extend_from_slice(pk);
81 }
82 preimage.extend_from_slice(&ciphertext.ciphertext_bytes);
83
84 let verify_hmac = Hash::sha_256_hmac(&preimage, &cipher_keys.km);
85
86 if hmac != &verify_hmac.to_bytes() {
87 return Err(BSVErrors::ECIESError("Invalid Checksum".into()));
88 }
89
90 let plain_text = AES::decrypt_impl(&cipher_keys.ke, &cipher_keys.iv, &ciphertext.ciphertext_bytes, crate::AESAlgorithms::AES128_CBC)?;
91 Ok(plain_text)
92 }
93
94 pub(crate) fn derive_cipher_keys_impl(priv_key: &PrivateKey, pub_key: &PublicKey) -> Result<CipherKeys, BSVErrors> {
95 let private_scalar = *priv_key.secret_key.to_nonzero_scalar();
96 let pub_key_point = K256PublicKey::from_sec1_bytes(&pub_key.to_bytes_impl()?)?.to_projective();
97
98 let shared_point = pub_key_point * private_scalar;
99 let shared_pub = K256PublicKey::from_affine(shared_point.to_affine())?;
100
101 let shared_mod_point = shared_pub.to_encoded_point(true);
102 let hash = Hash::sha_512(shared_mod_point.as_bytes()).to_bytes();
103
104 Ok(CipherKeys {
105 iv: hash[0..16].into(),
106 ke: hash[16..32].into(),
107 km: hash[32..64].into(),
108 })
109 }
110}
111
112impl ECIES {
113 pub fn encrypt(message: &[u8], sender_priv_key: &PrivateKey, recipient_pub_key: &PublicKey, exclude_pub_key: bool) -> Result<ECIESCiphertext, BSVErrors> {
114 ECIES::encrypt_impl(message, sender_priv_key, recipient_pub_key, exclude_pub_key)
115 }
116
117 pub fn encrypt_with_ephemeral_private_key(message: &[u8], recipient_pub_key: &PublicKey) -> Result<ECIESCiphertext, BSVErrors> {
122 ECIES::encrypt_with_ephemeral_private_key_impl(message, recipient_pub_key)
123 }
124
125 pub fn decrypt(ciphertext: &ECIESCiphertext, recipient_priv_key: &PrivateKey, sender_pub_key: &PublicKey) -> Result<Vec<u8>, BSVErrors> {
126 ECIES::decrypt_impl(ciphertext, recipient_priv_key, sender_pub_key)
127 }
128
129 pub fn derive_cipher_keys(priv_key: &PrivateKey, pub_key: &PublicKey) -> Result<CipherKeys, BSVErrors> {
130 ECIES::derive_cipher_keys_impl(priv_key, pub_key)
131 }
132}