use anyhow::Result;
use curve25519::edwards::CompressedEdwardsY;
use curve25519::scalar::Scalar;
use sha3::Digest;
use super::{PrivateKey, PublicKey, SharedSecret, H256, KEY_BYTES_SIZE};
pub trait BlockCipher: Sized {
fn encrypt_message(
signer_sk: &[u8; KEY_BYTES_SIZE],
receiver_pk: &[u8; KEY_BYTES_SIZE],
msg: &[u8],
) -> Result<Vec<u8>>;
fn decrypt_message(
receiver_sk: &[u8; KEY_BYTES_SIZE],
signer_pk: &[u8; KEY_BYTES_SIZE],
enc_msg: &[u8],
) -> Result<Vec<u8>>;
}
pub fn derive_shared_secret<D: Digest>(
secret_key: PrivateKey,
public_key: PublicKey,
) -> SharedSecret {
let public = CompressedEdwardsY::from_slice(public_key.as_ref())
.decompress()
.unwrap();
let secret = scalar_from_sk::<D>(secret_key);
let shared_point = secret * &(public);
let shared_point_compressed = shared_point.compress();
SharedSecret::from(shared_point_compressed.as_bytes())
}
fn scalar_from_sk<D: Digest>(secret_key: PrivateKey) -> Scalar {
let sk_hash = D::digest(secret_key.as_bytes());
let mut sk_hash_fix: H256 = H256::default();
sk_hash_fix.assign_from_slice(&sk_hash.as_slice()[0..32]);
sk_hash_fix.0[0] &= 0xF8; sk_hash_fix.0[31] &= 0x7F; sk_hash_fix.0[31] |= 0x40;
Scalar::from_bits(sk_hash_fix.into())
}