Skip to content

Commit

Permalink
Verify signature with public key (#1292)
Browse files Browse the repository at this point in the history
* verify with public key

* nit
  • Loading branch information
codabrink authored Nov 19, 2024
1 parent 28162bd commit a0c14de
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 31 deletions.
34 changes: 29 additions & 5 deletions bindings_ffi/src/mls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::{FfiSubscribeError, GenericError};
use std::{collections::HashMap, convert::TryInto, sync::Arc};
use tokio::sync::Mutex;
use xmtp_api_grpc::grpc_api_helper::Client as TonicApiClient;
use xmtp_id::associations::verify_signed_with_public_context;
use xmtp_id::scw_verifier::RemoteSignatureVerifier;
use xmtp_id::{
associations::{
Expand Down Expand Up @@ -367,13 +368,25 @@ impl FfiXmtpClient {

pub fn sign_with_installation_key(&self, text: &str) -> Result<Vec<u8>, GenericError> {
let inner = self.inner_client.as_ref();
Ok(inner.context().public_sign(text)?)
Ok(inner.context().sign_with_public_context(text)?)
}

pub fn verify_signed_with_installation_key(
&self,
signature_text: &str,
signature_bytes: Vec<u8>,
) -> Result<(), GenericError> {
let inner = self.inner_client.as_ref();
let public_key = inner.installation_public_key();

self.verify_signed_with_public_key(signature_text, signature_bytes, public_key)
}

pub fn verify_signed_with_public_key(
&self,
signature_text: &str,
signature_bytes: Vec<u8>,
public_key: Vec<u8>,
) -> Result<(), GenericError> {
let signature_bytes: [u8; 64] =
signature_bytes
Expand All @@ -385,10 +398,21 @@ impl FfiXmtpClient {
),
})?;

let inner = self.inner_client.as_ref();
Ok(inner
.context()
.public_verify(signature_text, &signature_bytes)?)
let public_key: [u8; 32] =
public_key
.try_into()
.map_err(|v: Vec<u8>| GenericError::Generic {
err: format!(
"public_key is not 32 bytes long. (Actual size: {})",
v.len()
),
})?;

Ok(verify_signed_with_public_context(
signature_text,
&signature_bytes,
&public_key,
)?)
}
}

Expand Down
34 changes: 33 additions & 1 deletion bindings_node/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use tracing_subscriber::{fmt, prelude::*};
pub use xmtp_api_grpc::grpc_api_helper::Client as TonicApiClient;
use xmtp_cryptography::signature::ed25519_public_key_to_address;
use xmtp_id::associations::builder::SignatureRequest;
use xmtp_id::associations::verify_signed_with_public_context;
use xmtp_mls::builder::ClientBuilder;
use xmtp_mls::groups::scoped_client::LocalScopedGroupClient;
use xmtp_mls::identity::IdentityStrategy;
Expand Down Expand Up @@ -295,9 +296,40 @@ impl Client {
let result = self
.inner_client
.context()
.public_sign(text)
.sign_with_public_context(text)
.map_err(ErrorWrapper::from)?;

Ok(result)
}

#[napi]
pub fn verify_signed_with_installation_key(
&self,
signature_text: String,
signature_bytes: Vec<u8>,
) -> Result<()> {
let public_key = self.inner_client().installation_public_key();
self.verify_signed_with_public_key(signature_text, signature_bytes, public_key)
}

#[napi]
pub fn verify_signed_with_public_key(
&self,
signature_text: String,
signature_bytes: Vec<u8>,
public_key: Vec<u8>,
) -> Result<()> {
let signature_bytes: [u8; 64] = signature_bytes
.try_into()
.map_err(|_| Error::from_reason("signature_bytes is not 64 bytes long."))?;

let public_key: [u8; 32] = public_key
.try_into()
.map_err(|_| Error::from_reason("public_key is not 32 bytes long."))?;

Ok(
verify_signed_with_public_context(signature_text, &signature_bytes, &public_key)
.map_err(ErrorWrapper::from)?,
)
}
}
3 changes: 1 addition & 2 deletions xmtp_cryptography/src/basic_credential.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use std::io::BufReader;

use ed25519_dalek::SigningKey;
use k256::schnorr::CryptoRngCore;
use openmls_basic_credential::SignatureKeyPair;
use openmls_traits::signatures::Signer;
use openmls_traits::{signatures, types::SignatureScheme};
use serde::de::Error;
use std::io::BufReader;
use tls_codec::SecretTlsVecU8;
use zeroize::Zeroizing;

Expand Down
13 changes: 12 additions & 1 deletion xmtp_id/src/associations/signature.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use ed25519_dalek::{DigestSigner, Signature};
use ed25519_dalek::{DigestSigner, Signature, VerifyingKey};
use ethers::signers::{LocalWallet, Signer};
use prost::Message;
use sha2::{Digest as _, Sha512};
Expand Down Expand Up @@ -105,6 +105,17 @@ impl SigningContextProvider for PublicContext {
}
}

pub fn verify_signed_with_public_context(
signature_text: impl AsRef<str>,
signature_bytes: &[u8; 64],
public_key: &[u8; 32],
) -> Result<(), SignatureError> {
let verifying_key = VerifyingKey::from_bytes(public_key)?;
verifying_key
.credential_verify::<PublicContext>(signature_text, signature_bytes)
.map_err(Into::into)
}

#[derive(Clone, Debug, PartialEq)]
pub enum SignatureKind {
// We might want to have some sort of LegacyErc191 Signature Kind for the `CreateIdentity` signatures only
Expand Down
14 changes: 4 additions & 10 deletions xmtp_mls/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,17 +199,11 @@ impl XmtpMlsLocalContext {
self.identity.signature_request()
}

pub fn public_sign(&self, text: impl AsRef<str>) -> Result<Vec<u8>, IdentityError> {
self.identity.sign_with_public_context(text)
}

pub fn public_verify(
pub fn sign_with_public_context(
&self,
signature_text: impl AsRef<str>,
signature_bytes: &[u8; 64],
) -> Result<(), IdentityError> {
self.identity
.verify_with_public_context(signature_text, signature_bytes)
text: impl AsRef<str>,
) -> Result<Vec<u8>, IdentityError> {
self.identity.sign_with_public_context(text)
}
}

Expand Down
13 changes: 1 addition & 12 deletions xmtp_mls/src/identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use prost::Message;
use thiserror::Error;
use tracing::debug;
use tracing::info;
use xmtp_cryptography::{CredentialSign, CredentialVerify, XmtpInstallationCredential};
use xmtp_cryptography::{CredentialSign, XmtpInstallationCredential};
use xmtp_id::associations::unverified::UnverifiedSignature;
use xmtp_id::associations::{AssociationError, InstallationKeyContext, PublicContext};
use xmtp_id::scw_verifier::SmartContractSignatureVerifier;
Expand Down Expand Up @@ -429,17 +429,6 @@ impl Identity {
.map_err(Into::into)
}

pub fn verify_with_public_context(
&self,
signature_text: impl AsRef<str>,
signature_bytes: &[u8; 64],
) -> Result<(), IdentityError> {
self.installation_keys
.verifying_key()
.credential_verify::<PublicContext>(signature_text, signature_bytes)
.map_err(Into::into)
}

/// Generate a new key package and store the associated keys in the database.
pub(crate) fn new_key_package(
&self,
Expand Down

0 comments on commit a0c14de

Please sign in to comment.