use crate::constants::{PRIVATE_KEY_LENGTH, PUBLIC_KEY_LENGTH, SIGNATURE_LENGTH};
use crate::errors::{LighterError, Result};
use crate::utils::hex_to_bytes;
use goldilocks_crypto::{sign_with_nonce, Point, ScalarField};
pub trait Signer {
fn sign(&self, hashed_message: &[u8]) -> Result<Vec<u8>>;
}
pub trait KeyManager: Signer {
fn pub_key(&self) -> &[u8];
fn pub_key_bytes(&self) -> [u8; PUBLIC_KEY_LENGTH];
fn prv_key_bytes(&self) -> Vec<u8>;
}
pub struct PoseidonKeyManager {
private_key: Vec<u8>,
public_key: Vec<u8>,
}
impl PoseidonKeyManager {
pub fn new(private_key_bytes: &[u8]) -> Result<Self> {
if private_key_bytes.len() != 32 && private_key_bytes.len() != PRIVATE_KEY_LENGTH {
return Err(LighterError::InvalidPrivateKeyLength {
expected: PRIVATE_KEY_LENGTH,
actual: private_key_bytes.len(),
});
}
let public_key = Self::derive_public_key(private_key_bytes)?;
Ok(Self {
private_key: private_key_bytes.to_vec(),
public_key,
})
}
pub fn from_hex(hex_private_key: &str) -> Result<Self> {
let bytes = hex_to_bytes(hex_private_key)?;
Self::new(&bytes)
}
fn derive_public_key(private_key: &[u8]) -> Result<Vec<u8>> {
let scalar = ScalarField::from_bytes_le(private_key)
.map_err(|e| LighterError::CryptoError(format!("Invalid private key: {e:?}")))?;
let public_key_point = Point::generator().mul(&scalar);
let pub_key_encoded = public_key_point.encode();
Ok(pub_key_encoded.to_bytes_le().to_vec())
}
fn generate_nonce(private_key: &[u8], message: &[u8]) -> Result<ScalarField> {
use sha2::{Digest, Sha256};
let mut hasher = Sha256::new();
hasher.update(private_key);
hasher.update(message);
let hash_result = hasher.finalize();
let mut nonce_bytes = [0u8; 40];
let copy_len = hash_result.len().min(32);
nonce_bytes[..copy_len].copy_from_slice(&hash_result[..copy_len]);
ScalarField::from_bytes_le(&nonce_bytes)
.map_err(|e| LighterError::CryptoError(format!("Nonce generation failed: {e:?}")))
}
}
impl Signer for PoseidonKeyManager {
fn sign(&self, hashed_message: &[u8]) -> Result<Vec<u8>> {
if hashed_message.len() != 40 {
return Err(LighterError::CryptoError(format!(
"Invalid hashed message length: expected 40, got {}",
hashed_message.len()
)));
}
let nonce = Self::generate_nonce(&self.private_key, hashed_message)?;
let signature = sign_with_nonce(&self.private_key, hashed_message, &nonce.to_bytes_le())
.map_err(|e| LighterError::CryptoError(format!("Signing failed: {e:?}")))?;
if signature.len() != SIGNATURE_LENGTH {
return Err(LighterError::CryptoError(format!(
"Invalid signature length: expected {}, got {}",
SIGNATURE_LENGTH,
signature.len()
)));
}
Ok(signature)
}
}
impl KeyManager for PoseidonKeyManager {
fn pub_key(&self) -> &[u8] {
&self.public_key
}
fn pub_key_bytes(&self) -> [u8; PUBLIC_KEY_LENGTH] {
let mut result = [0u8; PUBLIC_KEY_LENGTH];
result.copy_from_slice(&self.public_key[..PUBLIC_KEY_LENGTH]);
result
}
fn prv_key_bytes(&self) -> Vec<u8> {
self.private_key.clone()
}
}
pub fn new_key_manager(hex_key: &str) -> Result<Box<dyn KeyManager>> {
Ok(Box::new(PoseidonKeyManager::from_hex(hex_key)?))
}