use super::SeaError;
use base64::{engine::general_purpose, Engine as _};
use p256::{PublicKey, SecretKey};
pub async fn derive_secret(
their_epub: &str,
our_epriv: &str,
our_epub: &str,
) -> Result<String, SeaError> {
let their_pub = parse_epub(their_epub)?;
let _our_pub = parse_epub(our_epub)?;
let our_priv_bytes = general_purpose::STANDARD_NO_PAD
.decode(our_epriv)
.map_err(|_| SeaError::InvalidKey)?;
if our_priv_bytes.len() != 32 {
return Err(SeaError::InvalidKey);
}
let mut priv_array = [0u8; 32];
priv_array.copy_from_slice(&our_priv_bytes);
let our_secret = SecretKey::from_bytes(&priv_array.into()).map_err(|_| SeaError::InvalidKey)?;
let shared_secret =
p256::ecdh::diffie_hellman(our_secret.to_nonzero_scalar(), their_pub.as_affine());
let shared_point = shared_secret.raw_secret_bytes();
#[allow(deprecated)] #[allow(deprecated)] Ok(general_purpose::STANDARD_NO_PAD.encode(shared_point.as_slice()))
}
fn parse_epub(epub: &str) -> Result<PublicKey, SeaError> {
let parts: Vec<&str> = epub.split('.').collect();
if parts.len() != 2 {
return Err(SeaError::InvalidKey);
}
let x = general_purpose::STANDARD_NO_PAD
.decode(parts[0])
.map_err(|_| SeaError::InvalidKey)?;
let y = general_purpose::STANDARD_NO_PAD
.decode(parts[1])
.map_err(|_| SeaError::InvalidKey)?;
let mut pub_bytes = vec![0x04u8];
pub_bytes.extend_from_slice(&x);
pub_bytes.extend_from_slice(&y);
PublicKey::from_sec1_bytes(&pub_bytes).map_err(|_| SeaError::InvalidKey)
}