Skip to content

Commit

Permalink
feat: add Borsh (#150)
Browse files Browse the repository at this point in the history
Add Borsh(De)Serialize for keys and signatures.
  • Loading branch information
Cifko committed Nov 23, 2022
1 parent ea33445 commit 4a4b633
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/wasm.yml
Expand Up @@ -16,7 +16,7 @@ jobs:
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly-2022-01-17
toolchain: nightly
target: wasm32-unknown-unknown
override: true
- name: install wasm-pack
Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Expand Up @@ -11,10 +11,11 @@ version = "0.16.2"
edition = "2018"

[dependencies]
tari_utilities = { git = "https://github.com/tari-project/tari_utilities.git", tag="v0.4.9" }
tari_utilities = { git = "https://github.com/tari-project/tari_utilities.git", tag = "v0.4.10" }

base64 = "0.10.1"
blake2 = "0.9.1"
borsh = { version = "0.9.3", optional = true }
bulletproofs = { package = "tari_bulletproofs", git = "https://github.com/tari-project/bulletproofs", tag = "v4.3.0" }
bulletproofs_plus = { package = "tari_bulletproofs_plus", git = "https://github.com/tari-project/bulletproofs-plus", tag = "v0.1.0" }
curve25519-dalek = { package = "curve25519-dalek", version = "3.2.1", default-features = false, features = ["serde", "alloc"] }
Expand Down
14 changes: 14 additions & 0 deletions src/commitment.rs
Expand Up @@ -35,6 +35,20 @@ use crate::{
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct HomomorphicCommitment<P>(pub(crate) P);

#[cfg(feature = "borsh")]
impl<P: borsh::BorshDeserialize> borsh::BorshDeserialize for HomomorphicCommitment<P> {
fn deserialize(buf: &mut &[u8]) -> std::io::Result<Self> {
Ok(Self(P::deserialize(buf)?))
}
}

#[cfg(feature = "borsh")]
impl<P: borsh::BorshSerialize> borsh::BorshSerialize for HomomorphicCommitment<P> {
fn serialize<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
self.0.serialize(writer)
}
}

impl<P> HomomorphicCommitment<P>
where P: PublicKey
{
Expand Down
4 changes: 2 additions & 2 deletions src/ffi/keys.rs
Expand Up @@ -484,8 +484,8 @@ mod test {
pub fn test_verify_invalid_params() {
let pub_key = [1; KEY_LENGTH];
let msg = "msg\0";
let mut pub_nonce = [0; KEY_LENGTH];
let mut signature = [0; KEY_LENGTH];
let pub_nonce = [0; KEY_LENGTH];
let signature = [0; KEY_LENGTH];
let mut err_code = 0i32;
unsafe {
assert!(!verify(
Expand Down
35 changes: 35 additions & 0 deletions src/ristretto/ristretto_keys.rs
Expand Up @@ -9,6 +9,8 @@ use std::{
hash::{Hash, Hasher},
ops::{Add, Mul, Sub},
};
#[cfg(feature = "borsh")]
use std::{convert::TryInto, io, io::Write};

use blake2::Blake2b;
use curve25519_dalek::{
Expand Down Expand Up @@ -54,6 +56,24 @@ use crate::{
#[zeroize(drop)]
pub struct RistrettoSecretKey(pub(crate) Scalar);

#[cfg(feature = "borsh")]
impl borsh::BorshSerialize for RistrettoSecretKey {
fn serialize<W: Write>(&self, writer: &mut W) -> io::Result<()> {
borsh::BorshSerialize::serialize(&self.0.as_bytes(), writer)
}
}

#[cfg(feature = "borsh")]
impl borsh::BorshDeserialize for RistrettoSecretKey {
fn deserialize(buf: &mut &[u8]) -> io::Result<Self> {
Ok(Self(
// Self::from_bytes(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e.to_string()))
Scalar::from_canonical_bytes((&buf[..]).try_into().unwrap())
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Deserialize error"))?,
))
}
}

const SCALAR_LENGTH: usize = 32;
const PUBLIC_KEY_LENGTH: usize = 32;

Expand Down Expand Up @@ -238,6 +258,21 @@ pub struct RistrettoPublicKey {
compressed: OnceCell<CompressedRistretto>,
}

#[cfg(feature = "borsh")]
impl borsh::BorshSerialize for RistrettoPublicKey {
fn serialize<W: Write>(&self, writer: &mut W) -> io::Result<()> {
borsh::BorshSerialize::serialize(&self.as_bytes(), writer)
}
}

#[cfg(feature = "borsh")]
impl borsh::BorshDeserialize for RistrettoPublicKey {
fn deserialize(buf: &mut &[u8]) -> io::Result<Self> {
let bytes: Vec<u8> = borsh::BorshDeserialize::deserialize(buf)?;
Self::from_bytes(bytes.as_slice()).map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e.to_string()))
}
}

impl RistrettoPublicKey {
// Private constructor
pub(super) fn new_from_pk(pk: RistrettoPoint) -> Self {
Expand Down
3 changes: 3 additions & 0 deletions src/signatures/commitment_and_public_key_signature.rs
Expand Up @@ -52,7 +52,9 @@ pub enum CommitmentAndPublicKeySignatureError {
/// `u_a*H + (u_x + w*u_y)*G - ephemeral_commitment - w*ephemeral_pubkey - e*commitment - (w*e)*pubkey == 0`
/// The use of efficient multiscalar multiplication algorithms may also be useful for efficiency.
/// The use of precomputation tables for `G` and `H` may also be useful for efficiency.

#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))]
pub struct CommitmentAndPublicKeySignature<P, K> {
ephemeral_commitment: HomomorphicCommitment<P>,
ephemeral_pubkey: P,
Expand Down Expand Up @@ -80,6 +82,7 @@ where
/// Complete a signature using the given challenge. The challenge is provided by the caller to support the
/// multiparty use case. It is _very important_ that it be computed using strong Fiat-Shamir! Further, the
/// values `r_a, r_x, r_y` are nonces, must be sampled uniformly at random, and must never be reused.
#[allow(clippy::too_many_arguments)]
pub fn sign<C>(
a: &K,
x: &K,
Expand Down
2 changes: 2 additions & 0 deletions src/signatures/commitment_signature.rs
Expand Up @@ -44,8 +44,10 @@ pub enum CommitmentSignatureError {
/// Verification of the Commitment Signature (R, u, v) entails the following:
/// S = v*H + u*G ... (Pedersen commitment of the publicly known private signature keys)
/// S =? R + e.C ... (final verification)

#[allow(non_snake_case)]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "borsh", derive(borsh::BorshDeserialize, borsh::BorshSerialize))]
pub struct CommitmentSignature<P, K> {
public_nonce: HomomorphicCommitment<P>,
u: K,
Expand Down
1 change: 1 addition & 0 deletions src/signatures/schnorr.rs
Expand Up @@ -42,6 +42,7 @@ pub enum SchnorrSignatureError {
/// More details on Schnorr signatures can be found at [TLU](https://tlu.tarilabs.com/cryptography/introduction-schnorr-signatures).
#[allow(non_snake_case)]
#[derive(PartialEq, Eq, Copy, Debug, Clone, Serialize, Deserialize, Hash)]
#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))]
pub struct SchnorrSignature<P, K, H = SchnorrSigChallenge> {
public_nonce: P,
signature: K,
Expand Down
7 changes: 6 additions & 1 deletion src/wasm/key_utils.rs
Expand Up @@ -152,7 +152,7 @@ pub fn sign_challenge_with_nonce(private_key: &str, private_nonce: &str, challen
Ok(s) => s,
Err(e) => {
result.error = format!("Could not create signature. {e}");
return JsValue::from_serde(&result).unwrap();
return serde_wasm_bindgen::to_value(&result).unwrap();
},
};
result.public_nonce = Some(pub_r.to_hex());
Expand Down Expand Up @@ -500,6 +500,7 @@ pub fn sign_comandpubsig_challenge_with_nonce(
serde_wasm_bindgen::to_value(&result).unwrap()
}

#[allow(clippy::too_many_arguments)]
pub(crate) fn sign_comandpubsig_message_with_key(
private_key_a: &RistrettoSecretKey,
private_key_x: &RistrettoSecretKey,
Expand All @@ -523,6 +524,7 @@ pub(crate) fn sign_comandpubsig_message_with_key(
);
}

#[allow(clippy::too_many_arguments)]
pub(crate) fn sign_comandpubsig_with_key(
private_key_a: &RistrettoSecretKey,
private_key_x: &RistrettoSecretKey,
Expand Down Expand Up @@ -572,6 +574,7 @@ pub(crate) fn sign_comandpubsig_with_key(
}

/// Checks the validity of a Commitment signature
#[allow(clippy::too_many_arguments)]
#[allow(non_snake_case)]
#[wasm_bindgen]
pub fn check_comandpubsig_signature(
Expand Down Expand Up @@ -1322,6 +1325,7 @@ mod test {
mod check_comandpubsig_signature {
use super::*;

#[allow(clippy::too_many_arguments)]
fn check_comandpubsig_signature(
ephemeral_commitment: &str,
ephemeral_pubkey: &str,
Expand Down Expand Up @@ -1405,6 +1409,7 @@ mod test {

#[wasm_bindgen_test]
fn it_fails_if_verification_is_invalid() {
#[allow(clippy::too_many_arguments)]
fn it_fails(
ephemeral_commitment: &str,
ephemeral_pubkey: &str,
Expand Down

0 comments on commit 4a4b633

Please sign in to comment.