use sha2::{Digest, Sha256};
use sha3::Keccak256;
use k256::{
elliptic_curve::{
sec1::{ToEncodedPoint, FromEncodedPoint},
PrimeField,
},
ProjectivePoint, Scalar, AffinePoint
};
use crate::{Result, VeilCryptoError};
macro_rules! array_ref {
($arr:expr, $offset:expr, $len:expr) => {{
{
#[inline]
fn as_array<T>(slice: &[T]) -> &[T; $len] {
unsafe { &*(slice.as_ptr() as *const [T; $len]) }
}
as_array(&$arr[$offset..$offset + $len])
}
}};
}
pub fn hash_sha256(data: &[u8]) -> [u8; 32] {
let mut hasher = Sha256::new();
hasher.update(data);
hasher.finalize().into()
}
pub fn hash_keccak256(data: &[u8]) -> [u8; 32] {
let mut hasher = Keccak256::new();
hasher.update(data);
hasher.finalize().into()
}
pub fn derive_pubkey(secret: &[u8]) -> Result<Vec<u8>> {
if secret.len() != 32 {
return Err(VeilCryptoError::InvalidSecretKey);
}
let scalar = Scalar::from_repr((*array_ref![secret, 0, 32]).into())
.into_option()
.ok_or(VeilCryptoError::InvalidSecretKey)?;
let point = ProjectivePoint::GENERATOR * scalar;
let affine = point.to_affine();
let encoded = affine.to_encoded_point(true);
Ok(encoded.as_bytes().to_vec())
}
pub fn point_add_scalar(pubkey: &[u8], scalar: &[u8]) -> Result<Vec<u8>> {
if pubkey.len() != 33 {
return Err(VeilCryptoError::InvalidPublicKey);
}
if scalar.len() != 32 {
return Err(VeilCryptoError::InvalidSecretKey);
}
let point = AffinePoint::from_encoded_point(&k256::EncodedPoint::from_bytes(pubkey).map_err(|_| VeilCryptoError::InvalidPublicKey)?)
.into_option()
.ok_or(VeilCryptoError::InvalidPublicKey)?;
let scalar_val = Scalar::from_repr((*array_ref![scalar, 0, 32]).into())
.into_option()
.ok_or(VeilCryptoError::InvalidSecretKey)?;
let scalar_point = ProjectivePoint::GENERATOR * scalar_val;
let result = ProjectivePoint::from(point) + scalar_point;
let affine = result.to_affine();
let encoded = affine.to_encoded_point(true);
Ok(encoded.as_bytes().to_vec())
}
pub fn point_multiply(pubkey: &[u8], scalar: &[u8]) -> Result<Vec<u8>> {
if pubkey.len() != 33 {
return Err(VeilCryptoError::InvalidPublicKey);
}
if scalar.len() != 32 {
return Err(VeilCryptoError::InvalidSecretKey);
}
let point = AffinePoint::from_encoded_point(&k256::EncodedPoint::from_bytes(pubkey).map_err(|_| VeilCryptoError::InvalidPublicKey)?)
.into_option()
.ok_or(VeilCryptoError::InvalidPublicKey)?;
let scalar_val = Scalar::from_repr((*array_ref![scalar, 0, 32]).into())
.into_option()
.ok_or(VeilCryptoError::InvalidSecretKey)?;
let result = ProjectivePoint::from(point) * scalar_val;
let affine = result.to_affine();
let encoded = affine.to_encoded_point(true);
Ok(encoded.as_bytes().to_vec())
}
pub fn private_add(a: &[u8], b: &[u8]) -> Result<Vec<u8>> {
if a.len() != 32 || b.len() != 32 {
return Err(VeilCryptoError::InvalidSecretKey);
}
let a_scalar = Scalar::from_repr((*array_ref![a, 0, 32]).into())
.into_option()
.ok_or(VeilCryptoError::InvalidSecretKey)?;
let b_scalar = Scalar::from_repr((*array_ref![b, 0, 32]).into())
.into_option()
.ok_or(VeilCryptoError::InvalidSecretKey)?;
let result = a_scalar + b_scalar;
Ok(result.to_bytes().to_vec())
}
pub fn hash_to_point(_data: &[u8]) -> Vec<u8> {
vec![]
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_hash_sha256() {
let data = b"hello world";
let hash = hash_sha256(data);
assert_eq!(hash.len(), 32);
}
#[test]
fn test_hash_keccak256() {
let data = b"hello world";
let hash = hash_keccak256(data);
assert_eq!(hash.len(), 32);
}
}