Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 58 additions & 6 deletions crates/iris-crypto/src/cheetah.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
#[cfg(feature = "wasm")]
use alloc::{boxed::Box, format, string::ToString};
#[cfg(feature = "alloc")]
use alloc::{
boxed::Box,
format,
string::{String, ToString},
vec::Vec,
};
use alloc::{string::String, vec::Vec};
use arrayvec::ArrayVec;
use core::convert::Infallible;
use core::future::{ready, Future};
use iris_ztd::{
crypto::cheetah::{
ch_add, ch_neg, ch_scal_big, trunc_g_order, CheetahPoint, F6lt, A_GEN, G_ORDER,
Expand Down Expand Up @@ -220,6 +219,28 @@ pub struct Signature {
pub s: U256,
}

impl Signature {
pub const BYTE_LEN: usize = 64;

pub fn to_bytes_le(&self) -> [u8; Self::BYTE_LEN] {
let mut out = [0u8; Self::BYTE_LEN];
out[..32].copy_from_slice(&self.c.to_le_bytes());
out[32..].copy_from_slice(&self.s.to_le_bytes());
out
}

pub fn from_bytes_le(bytes: &[u8]) -> Option<Self> {
if bytes.len() != Self::BYTE_LEN {
return None;
}

Some(Self {
c: U256::from_le_slice(&bytes[..32]),
s: U256::from_le_slice(&bytes[32..]),
})
}
}

// Aggregate signature of the same challenge
impl core::iter::Sum<Signature> for Option<Signature> {
fn sum<I: Iterator<Item = Signature>>(mut iter: I) -> Self {
Expand Down Expand Up @@ -277,9 +298,40 @@ impl Hashable for Signature {
}
}

/// ECDSA signing for transaction witnesses. Implemented by [`PrivateKey`] and
/// wasm-side key handles that delegate to local or external signers.
pub trait SigningKey {
type Error;

fn public_key(&self) -> impl Future<Output = Result<PublicKey, Self::Error>> + '_;

fn sign_digests<'a>(
&'a self,
digests: &'a [Digest],
) -> impl Future<Output = Result<alloc::vec::Vec<Signature>, Self::Error>> + 'a;
}

#[derive(Debug, Clone)]
pub struct PrivateKey(pub U256);

impl SigningKey for PrivateKey {
type Error = Infallible;

fn public_key(&self) -> impl Future<Output = Result<PublicKey, Self::Error>> + '_ {
ready(Ok(PrivateKey::public_key(self)))
}

fn sign_digests<'a>(
&'a self,
digests: &'a [Digest],
) -> impl Future<Output = Result<alloc::vec::Vec<Signature>, Self::Error>> + 'a {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this needs to be gated by the alloc feature, otherwise it might break compilation on iris-rs with --no-default features.

ready(Ok(digests
.iter()
.map(|d| PrivateKey::sign(self, d))
.collect()))
}
}

impl Drop for PrivateKey {
fn drop(&mut self) {
unsafe {
Expand Down
2 changes: 1 addition & 1 deletion crates/iris-crypto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use alloc::string::{String, ToString};
pub mod cheetah;
pub mod slip10;

pub use cheetah::{PrivateKey, PublicKey, Signature};
pub use cheetah::{PrivateKey, PublicKey, Signature, SigningKey};
pub use slip10::{derive_master_key, ExtendedKey};

#[cfg(feature = "mnemonic")]
Expand Down
Loading
Loading