use crate::crypto::{KeyType, KeyedCryptoPrimitive, PrivateKey, PublicKey, Signature};
use crate::error::{ChaincraftError, CryptoError, Result};
use async_trait::async_trait;
use base64::{engine::general_purpose, Engine as _};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone)]
pub struct EcdsaSignature {
pub key_type: KeyType,
}
impl EcdsaSignature {
pub fn new(key_type: KeyType) -> Self {
Self { key_type }
}
pub fn ed25519() -> Self {
Self::new(KeyType::Ed25519)
}
pub fn secp256k1() -> Self {
Self::new(KeyType::Secp256k1)
}
}
impl Default for EcdsaSignature {
fn default() -> Self {
Self::ed25519()
}
}
#[async_trait]
impl KeyedCryptoPrimitive for EcdsaSignature {
type PublicKey = PublicKey;
type PrivateKey = PrivateKey;
type Input = Vec<u8>;
type Output = Vec<u8>;
type Message = Vec<u8>;
type Signature = Signature;
async fn generate_keypair(&self) -> Result<(Self::PrivateKey, Self::PublicKey)> {
crate::crypto::utils::generate_keypair(self.key_type)
}
async fn compute(&self, key: &Self::PrivateKey, input: Self::Input) -> Result<Self::Output> {
let signature = self.sign(key, &input).await?;
Ok(signature.to_bytes())
}
async fn sign(
&self,
private_key: &Self::PrivateKey,
message: &Self::Message,
) -> Result<Self::Signature> {
crate::crypto::utils::sign_message(private_key, message)
}
async fn verify(
&self,
key: &Self::PublicKey,
input: Self::Input,
output: &Self::Output,
) -> Result<bool> {
match key {
PublicKey::Ed25519(pk) => {
if output.len() != 64 {
return Err(ChaincraftError::Crypto(CryptoError::InvalidSignature));
}
let mut sig_bytes = [0u8; 64];
sig_bytes.copy_from_slice(&output[0..64]);
let signature = ed25519_dalek::Signature::from(sig_bytes);
use ed25519_dalek::Verifier;
match pk.verify(&input, &signature) {
Ok(_) => Ok(true),
Err(_) => Ok(false), }
},
PublicKey::Secp256k1(pk) => {
let signature = match k256::ecdsa::Signature::from_slice(output.as_slice()) {
Ok(s) => s,
Err(_) => return Err(ChaincraftError::Crypto(CryptoError::InvalidSignature)),
};
use k256::ecdsa::{signature::Verifier, VerifyingKey};
let verifying_key = VerifyingKey::from(pk);
Ok(verifying_key.verify(&input, &signature).is_ok())
},
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ECDSASignature {
data: Vec<u8>,
}
impl ECDSASignature {
pub fn new(data: Vec<u8>) -> Self {
Self { data }
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
Ok(Self {
data: bytes.to_vec(),
})
}
pub fn to_bytes(&self) -> Vec<u8> {
self.data.clone()
}
}
#[derive(Debug)]
pub struct ECDSASigner {
private_key: PrivateKey,
public_key: PublicKey,
provider: EcdsaSignature,
}
impl ECDSASigner {
pub fn new() -> Result<Self> {
let provider = EcdsaSignature::ed25519();
let (private_key, public_key) = futures::executor::block_on(provider.generate_keypair())?;
Ok(Self {
private_key,
public_key,
provider,
})
}
pub fn sign(&self, message: &[u8]) -> Result<ECDSASignature> {
let signature =
futures::executor::block_on(self.provider.sign(&self.private_key, &message.to_vec()))?;
Ok(ECDSASignature::new(signature.to_bytes()))
}
pub fn get_public_key_pem(&self) -> Result<String> {
match &self.public_key {
PublicKey::Ed25519(pk) => {
let bytes = pk.to_bytes();
let b64 = general_purpose::STANDARD.encode(bytes);
Ok(format!("-----BEGIN PUBLIC KEY-----\n{b64}\n-----END PUBLIC KEY-----"))
},
PublicKey::Secp256k1(pk) => {
use k256::elliptic_curve::sec1::ToEncodedPoint;
let point = pk.to_encoded_point(true);
let b64 = general_purpose::STANDARD.encode(point.as_bytes());
Ok(format!("-----BEGIN PUBLIC KEY-----\n{b64}\n-----END PUBLIC KEY-----"))
},
}
}
}
#[derive(Debug, Clone)]
pub struct ECDSAVerifier {
provider: EcdsaSignature,
}
impl ECDSAVerifier {
pub fn new() -> Self {
Self {
provider: EcdsaSignature::ed25519(),
}
}
pub fn verify(
&self,
message: &[u8],
signature: &ECDSASignature,
public_key_pem: &str,
) -> Result<bool> {
let public_key = self.parse_public_key_pem(public_key_pem)?;
futures::executor::block_on(self.provider.verify(
&public_key,
message.to_vec(),
&signature.data,
))
}
fn parse_public_key_pem(&self, pem: &str) -> Result<PublicKey> {
let cleaned_pem = pem
.replace("-----BEGIN PUBLIC KEY-----", "")
.replace("-----END PUBLIC KEY-----", "")
.replace(['\n', '\r', ' '], "");
let key_bytes = general_purpose::STANDARD
.decode(cleaned_pem)
.map_err(|_| ChaincraftError::Crypto(CryptoError::InvalidSignature))?;
if key_bytes.len() == 32 {
let mut array = [0u8; 32];
array.copy_from_slice(&key_bytes);
match ed25519_dalek::VerifyingKey::from_bytes(&array) {
Ok(pk) => Ok(PublicKey::Ed25519(pk)),
Err(_) => Err(ChaincraftError::Crypto(CryptoError::InvalidSignature)),
}
} else if key_bytes.len() == 33 {
match k256::PublicKey::from_sec1_bytes(&key_bytes) {
Ok(pk) => Ok(PublicKey::Secp256k1(pk)),
Err(_) => Err(ChaincraftError::Crypto(CryptoError::InvalidSignature)),
}
} else {
Err(ChaincraftError::Crypto(CryptoError::InvalidSignature))
}
}
}
impl Default for ECDSAVerifier {
fn default() -> Self {
Self::new()
}
}