use crypto_bigint::modular::constant_mod::ResidueParams;
use crypto_bigint::{impl_modulus, Encoding, NonZero, Random, RandomMod, U256};
use std::fmt;
use zeroize::Zeroize;
use crate::errors::{CryptoError, Error};
impl_modulus!(
Secp256k1Order,
U256,
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"
);
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Zeroize)]
pub struct Random32Bytes(U256);
impl Random32Bytes {
pub fn generate() -> Self {
let mut rng = rand::thread_rng();
Self(U256::random(&mut rng))
}
pub fn generate_mod_q() -> Self {
let mut rng = rand::thread_rng();
let modulus = NonZero::new(Secp256k1Order::MODULUS).unwrap();
Self(U256::random_mod(&mut rng, &modulus))
}
pub fn as_u256(&self) -> U256 {
self.0
}
pub fn to_be_bytes(&self) -> [u8; 32] {
self.0.to_be_bytes()
}
}
impl From<U256> for Random32Bytes {
fn from(value: U256) -> Self {
Self(value)
}
}
impl From<[u8; 32]> for Random32Bytes {
fn from(value: [u8; 32]) -> Self {
Self(U256::from_be_slice(&value))
}
}
impl TryFrom<&[u8]> for Random32Bytes {
type Error = Error;
fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
if slice.len() == 32 {
Ok(Self(U256::from_be_slice(slice)))
} else {
Err(Error::Encoding)
}
}
}
impl fmt::Display for Random32Bytes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_u256())
}
}
pub fn verify_signature(
verifying_key: &VerifyingKey,
msg: &[u8],
signature: &Signature,
) -> Result<(), CryptoError> {
if (verifying_key.algo, verifying_key.curve) != (signature.algo, signature.curve) {
Err(CryptoError::SchemeMismatch)
} else {
match (verifying_key.algo, verifying_key.curve) {
(SignatureAlgorithm::ECDSA, EllipticCurve::Secp256k1) => {
match signature.hash {
MessageDigest::SHA256 => {
match (verifying_key.enc, signature.enc) {
(KeyEncoding::SEC1, SignatureEncoding::DER) => {
let ver_key =
k256::ecdsa::VerifyingKey::from_sec1_bytes(&verifying_key.key);
let sig = k256::ecdsa::Signature::from_der(&signature.sig)
.map_err(|_| CryptoError::InvalidSignature)?;
use k256::ecdsa::signature::Verifier;
ver_key
.map_err(|_| CryptoError::InvalidVerifyingKey)?
.verify(msg, &sig)
.map_err(|_| CryptoError::InvalidSignature)
}
_ => Err(CryptoError::UnsupportedEncoding),
}
}
_ => Err(CryptoError::UnsupportedDigest),
}
}
_ => Err(CryptoError::UnsupportedScheme),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VerifyingKey {
pub key: Vec<u8>,
pub algo: SignatureAlgorithm,
pub curve: EllipticCurve,
pub enc: KeyEncoding,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Signature {
pub sig: Vec<u8>,
pub algo: SignatureAlgorithm,
pub curve: EllipticCurve,
pub hash: MessageDigest,
pub enc: SignatureEncoding,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum SignatureAlgorithm {
ECDSA,
EdDSA,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EllipticCurve {
Secp256k1,
Curve25519,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MessageDigest {
SHA256,
Keccak256,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum KeyEncoding {
SEC1,
EIP55,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SignatureEncoding {
DER,
RLP,
}