From 5f60778ebcd4349c31bf46b6909fddc9b682e11c Mon Sep 17 00:00:00 2001 From: Amit Yadav Date: Fri, 11 Aug 2023 00:11:09 +0530 Subject: [PATCH 1/5] add ed25519 extern --- contracts/oracle/src/lib.rs | 61 ++++++++++++++++++++++++++++-------- contracts/oracle/src/util.rs | 5 +++ 2 files changed, 53 insertions(+), 13 deletions(-) diff --git a/contracts/oracle/src/lib.rs b/contracts/oracle/src/lib.rs index 278c5972..29da4ad0 100644 --- a/contracts/oracle/src/lib.rs +++ b/contracts/oracle/src/lib.rs @@ -130,12 +130,13 @@ impl Contract { )); } - let sig = b64_decode("claim_sig", claim_sig)?; + //let sig = b64_decode("claim_sig", claim_sig)?; let claim_bytes = b64_decode("claim_b64", claim_b64)?; // let claim = Claim::deserialize(&mut &claim_bytes[..]) let claim = Claim::try_from_slice(&claim_bytes) .map_err(|_| CtrError::Borsh("claim".to_string()))?; - verify_claim(&self.authority_pubkey, claim_bytes, sig)?; + let signature = sig_from_b64(claim_sig); + verify_claim(&self.authority_pubkey, claim_bytes, &signature)?; if claim.verified_kyc { require!( @@ -299,18 +300,51 @@ impl Contract { // - fn sbt_renew } +mod sys { + extern "C" { + pub fn ed25519_verify( + sig_len: u64, + sig_ptr: u64, + msg_len: u64, + msg_ptr: u64, + pub_key_len: u64, + pub_key_ptr: u64, + ) -> u64; + } + } + + pub fn ed25519_verify(signature: &[u8; 64], message: &[u8], public_key: &[u8; 32]) -> bool { + unsafe { + sys::ed25519_verify( + signature.len() as _, + signature.as_ptr() as _, + message.len() as _, + message.as_ptr() as _, + public_key.len() as _, + public_key.as_ptr() as _, + ) == 1 + } +} + fn verify_claim( pubkey: &[u8; PUBLIC_KEY_LENGTH], claim: Vec, - claim_sig: Vec, + claim_sig: &[u8; 64], ) -> Result<(), CtrError> { - let pk = PublicKey::from_bytes(pubkey).unwrap(); - let sig = match Signature::from_bytes(&claim_sig) { - Ok(sig) => sig, - Err(_) => return Err(CtrError::Signature("malformed signature".to_string())), - }; - pk.verify(&claim, &sig) - .map_err(|_| CtrError::Signature("invalid signature".to_string())) + //let sig: &[u8; 64] = claim_sig.try_into().expect("authority pubkey must be 64 bytes"); + let valid = ed25519_verify(claim_sig, &claim, pubkey); + if !valid { + return Err(CtrError::Signature("invalid signature".to_string())) + } else { + Ok(()) + } + // let pk = PublicKey::from_bytes(pubkey).unwrap(); + // let sig = match Signature::from_bytes(&claim_sig) { + // Ok(sig) => sig, + // Err(_) => return Err(CtrError::Signature("malformed signature".to_string())), + // }; + // pk.verify(&claim, &sig) + // .map_err(|_| CtrError::Signature("invalid signature".to_string())) } #[near_bindgen] @@ -561,8 +595,9 @@ mod tests { let claim_sig_b64 = "38X2TnWgc6moc4zReAJFQ7BjtOUlWZ+i3YQl9gSMOXwnm5gupfHV/YGmGPOek6SSkotT586d4zTTT2U8Qh3GBw==".to_owned(); let claim_bytes = b64_decode("claim_b64", claim_b64.clone()).unwrap(); - let sig = b64_decode("claim_sig", claim_sig_b64.clone()).unwrap(); - verify_claim(&ctr.authority_pubkey, claim_bytes, sig).unwrap(); + //let sig = b64_decode("claim_sig", claim_sig_b64.clone()).unwrap(); + let sig = sig_from_b64(claim_sig_b64.clone()); + verify_claim(&ctr.authority_pubkey, claim_bytes, &sig).unwrap(); let r = ctr.sbt_mint(claim_b64, claim_sig_b64, None); match r { @@ -647,7 +682,7 @@ mod tests { let res = verify_claim( &k.public.to_bytes(), claim_bytes, - b64_decode("sig", sig).unwrap(), + &sig_from_b64(sig), ); assert!(res.is_ok(), "verification result: {:?}", res); } diff --git a/contracts/oracle/src/util.rs b/contracts/oracle/src/util.rs index cee89451..df03d836 100644 --- a/contracts/oracle/src/util.rs +++ b/contracts/oracle/src/util.rs @@ -38,6 +38,11 @@ pub fn pubkey_from_b64(pubkey: String) -> [u8; PUBLIC_KEY_LENGTH] { pk_bz.try_into().expect("authority pubkey must be 32 bytes") } +pub fn sig_from_b64(sig: String) -> [u8; PUBLIC_KEY_LENGTH * 2] { + let sig_bz = base64::decode(sig).expect("authority_pubkey is not a valid standard base64"); + sig_bz.try_into().expect("authority pubkey must be 32 bytes") +} + /// only root accounts and implicit accounts are supported pub(crate) fn is_supported_account(account: Chars) -> bool { let mut num_dots = 0; From 3a261844a68646647fa0a8534b3a3b093c07d867 Mon Sep 17 00:00:00 2001 From: Amit Yadav Date: Fri, 11 Aug 2023 00:53:54 +0530 Subject: [PATCH 2/5] fix --- contracts/oracle/src/lib.rs | 30 ++++++++++-------------------- contracts/oracle/src/util.rs | 4 ++-- 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/contracts/oracle/src/lib.rs b/contracts/oracle/src/lib.rs index 29da4ad0..5d5d24a4 100644 --- a/contracts/oracle/src/lib.rs +++ b/contracts/oracle/src/lib.rs @@ -1,4 +1,4 @@ -use ed25519_dalek::{PublicKey, Signature, Verifier, PUBLIC_KEY_LENGTH}; +use ed25519_dalek::{PUBLIC_KEY_LENGTH}; use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; use near_sdk::collections::{LazyOption, UnorderedSet}; use near_sdk::serde::Serialize; @@ -130,9 +130,7 @@ impl Contract { )); } - //let sig = b64_decode("claim_sig", claim_sig)?; let claim_bytes = b64_decode("claim_b64", claim_b64)?; - // let claim = Claim::deserialize(&mut &claim_bytes[..]) let claim = Claim::try_from_slice(&claim_bytes) .map_err(|_| CtrError::Borsh("claim".to_string()))?; let signature = sig_from_b64(claim_sig); @@ -331,20 +329,12 @@ fn verify_claim( claim: Vec, claim_sig: &[u8; 64], ) -> Result<(), CtrError> { - //let sig: &[u8; 64] = claim_sig.try_into().expect("authority pubkey must be 64 bytes"); let valid = ed25519_verify(claim_sig, &claim, pubkey); if !valid { return Err(CtrError::Signature("invalid signature".to_string())) } else { Ok(()) } - // let pk = PublicKey::from_bytes(pubkey).unwrap(); - // let sig = match Signature::from_bytes(&claim_sig) { - // Ok(sig) => sig, - // Err(_) => return Err(CtrError::Signature("malformed signature".to_string())), - // }; - // pk.verify(&claim, &sig) - // .map_err(|_| CtrError::Signature("invalid signature".to_string())) } #[near_bindgen] @@ -717,13 +707,13 @@ mod tests { assert_eq!(c, claim2, "serialization should work"); } - #[allow(dead_code)] - // #[test] - fn sig_deserialization_check() { - let sig_b64 = - "o8MGudK9OrdNKVCMhjF7rEv9LangB+PdjxuQ0kgglCskZX7Al4JPrwf7tRlT252kiNpJaGPURgAvAA=="; - let sig_bz = b64_decode("sig", sig_b64.to_string()).unwrap(); - println!("sig len: {}", sig_bz.len()); - Signature::from_bytes(&sig_bz).unwrap(); - } + // #[allow(dead_code)] + // // #[test] + // fn sig_deserialization_check() { + // let sig_b64 = + // "o8MGudK9OrdNKVCMhjF7rEv9LangB+PdjxuQ0kgglCskZX7Al4JPrwf7tRlT252kiNpJaGPURgAvAA=="; + // let sig_bz = b64_decode("sig", sig_b64.to_string()).unwrap(); + // println!("sig len: {}", sig_bz.len()); + // Signature::from_bytes(&sig_bz).unwrap(); + // } } diff --git a/contracts/oracle/src/util.rs b/contracts/oracle/src/util.rs index df03d836..a2b42745 100644 --- a/contracts/oracle/src/util.rs +++ b/contracts/oracle/src/util.rs @@ -38,9 +38,9 @@ pub fn pubkey_from_b64(pubkey: String) -> [u8; PUBLIC_KEY_LENGTH] { pk_bz.try_into().expect("authority pubkey must be 32 bytes") } -pub fn sig_from_b64(sig: String) -> [u8; PUBLIC_KEY_LENGTH * 2] { +pub fn sig_from_b64(sig: String) -> [u8; 64] { let sig_bz = base64::decode(sig).expect("authority_pubkey is not a valid standard base64"); - sig_bz.try_into().expect("authority pubkey must be 32 bytes") + sig_bz.try_into().expect("signature must be 64 bytes") } /// only root accounts and implicit accounts are supported From 850bb8d7a01c9ced209bcb251412ee41d13e300c Mon Sep 17 00:00:00 2001 From: Amit Yadav Date: Fri, 11 Aug 2023 01:05:54 +0530 Subject: [PATCH 3/5] Apply suggestions from code review --- contracts/oracle/src/lib.rs | 1 - contracts/oracle/src/util.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/contracts/oracle/src/lib.rs b/contracts/oracle/src/lib.rs index be9806c5..fe678c12 100644 --- a/contracts/oracle/src/lib.rs +++ b/contracts/oracle/src/lib.rs @@ -585,7 +585,6 @@ mod tests { let claim_sig_b64 = "38X2TnWgc6moc4zReAJFQ7BjtOUlWZ+i3YQl9gSMOXwnm5gupfHV/YGmGPOek6SSkotT586d4zTTT2U8Qh3GBw==".to_owned(); let claim_bytes = b64_decode("claim_b64", claim_b64.clone()).unwrap(); - //let sig = b64_decode("claim_sig", claim_sig_b64.clone()).unwrap(); let sig = sig_from_b64(claim_sig_b64.clone()); verify_claim(&ctr.authority_pubkey, claim_bytes, &sig).unwrap(); diff --git a/contracts/oracle/src/util.rs b/contracts/oracle/src/util.rs index a2b42745..1689e833 100644 --- a/contracts/oracle/src/util.rs +++ b/contracts/oracle/src/util.rs @@ -39,7 +39,7 @@ pub fn pubkey_from_b64(pubkey: String) -> [u8; PUBLIC_KEY_LENGTH] { } pub fn sig_from_b64(sig: String) -> [u8; 64] { - let sig_bz = base64::decode(sig).expect("authority_pubkey is not a valid standard base64"); + let sig_bz = base64::decode(sig).expect("signature is not a valid standard base64"); sig_bz.try_into().expect("signature must be 64 bytes") } From ca32afeb6fd02e524a7fdc3df1078d3e6306d6ed Mon Sep 17 00:00:00 2001 From: Amit Yadav Date: Fri, 11 Aug 2023 01:15:22 +0530 Subject: [PATCH 4/5] updates --- contracts/oracle/src/lib.rs | 24 +++++++++--------------- contracts/oracle/src/util.rs | 5 ----- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/contracts/oracle/src/lib.rs b/contracts/oracle/src/lib.rs index 5d5d24a4..1b843d62 100644 --- a/contracts/oracle/src/lib.rs +++ b/contracts/oracle/src/lib.rs @@ -133,7 +133,9 @@ impl Contract { let claim_bytes = b64_decode("claim_b64", claim_b64)?; let claim = Claim::try_from_slice(&claim_bytes) .map_err(|_| CtrError::Borsh("claim".to_string()))?; - let signature = sig_from_b64(claim_sig); + let sign = b64_decode("sign_b64", claim_sig)?; + let signature: [u8; 64] = sign.try_into().expect("signature must be 64 bytes"); + verify_claim(&self.authority_pubkey, claim_bytes, &signature)?; if claim.verified_kyc { @@ -585,9 +587,9 @@ mod tests { let claim_sig_b64 = "38X2TnWgc6moc4zReAJFQ7BjtOUlWZ+i3YQl9gSMOXwnm5gupfHV/YGmGPOek6SSkotT586d4zTTT2U8Qh3GBw==".to_owned(); let claim_bytes = b64_decode("claim_b64", claim_b64.clone()).unwrap(); - //let sig = b64_decode("claim_sig", claim_sig_b64.clone()).unwrap(); - let sig = sig_from_b64(claim_sig_b64.clone()); - verify_claim(&ctr.authority_pubkey, claim_bytes, &sig).unwrap(); + let sign = b64_decode("sign_b64", claim_sig_b64.clone()).unwrap(); + let signature: [u8; 64] = sign.try_into().expect("signature must be 64 bytes"); + verify_claim(&ctr.authority_pubkey, claim_bytes, &signature).unwrap(); let r = ctr.sbt_mint(claim_b64, claim_sig_b64, None); match r { @@ -669,10 +671,12 @@ mod tests { let (_, c_str, sig) = mk_claim_sign(start() / SECOND, "0x12", &k, false); let claim_bytes = b64_decode("claim_b64", c_str).unwrap(); + let sign = b64_decode("sign_b64", sig).unwrap(); + let signature: [u8; 64] = sign.try_into().expect("signature must be 64 bytes"); let res = verify_claim( &k.public.to_bytes(), claim_bytes, - &sig_from_b64(sig), + &signature, ); assert!(res.is_ok(), "verification result: {:?}", res); } @@ -706,14 +710,4 @@ mod tests { let claim2 = checks::tests::deserialize_claim(&claim_str); assert_eq!(c, claim2, "serialization should work"); } - - // #[allow(dead_code)] - // // #[test] - // fn sig_deserialization_check() { - // let sig_b64 = - // "o8MGudK9OrdNKVCMhjF7rEv9LangB+PdjxuQ0kgglCskZX7Al4JPrwf7tRlT252kiNpJaGPURgAvAA=="; - // let sig_bz = b64_decode("sig", sig_b64.to_string()).unwrap(); - // println!("sig len: {}", sig_bz.len()); - // Signature::from_bytes(&sig_bz).unwrap(); - // } } diff --git a/contracts/oracle/src/util.rs b/contracts/oracle/src/util.rs index a2b42745..cee89451 100644 --- a/contracts/oracle/src/util.rs +++ b/contracts/oracle/src/util.rs @@ -38,11 +38,6 @@ pub fn pubkey_from_b64(pubkey: String) -> [u8; PUBLIC_KEY_LENGTH] { pk_bz.try_into().expect("authority pubkey must be 32 bytes") } -pub fn sig_from_b64(sig: String) -> [u8; 64] { - let sig_bz = base64::decode(sig).expect("authority_pubkey is not a valid standard base64"); - sig_bz.try_into().expect("signature must be 64 bytes") -} - /// only root accounts and implicit accounts are supported pub(crate) fn is_supported_account(account: Chars) -> bool { let mut num_dots = 0; From 4f68c7f078b2f87a24cc8191872987de4b8a7607 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Thu, 10 Aug 2023 22:52:18 +0200 Subject: [PATCH 5/5] Apply suggestions from code review --- contracts/oracle/src/lib.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/contracts/oracle/src/lib.rs b/contracts/oracle/src/lib.rs index f6f600dd..107c1b7d 100644 --- a/contracts/oracle/src/lib.rs +++ b/contracts/oracle/src/lib.rs @@ -133,9 +133,8 @@ impl Contract { let claim_bytes = b64_decode("claim_b64", claim_b64)?; let claim = Claim::try_from_slice(&claim_bytes) .map_err(|_| CtrError::Borsh("claim".to_string()))?; - let sign = b64_decode("sign_b64", claim_sig)?; - let signature: [u8; 64] = sign.try_into().expect("signature must be 64 bytes"); - + let signature = b64_decode("sign_b64", claim_sig)?; + let signature: [u8; 64] = signature.try_into().expect("signature must be 64 bytes"); verify_claim(&self.authority_pubkey, claim_bytes, &signature)?; if claim.verified_kyc { @@ -587,8 +586,8 @@ mod tests { let claim_sig_b64 = "38X2TnWgc6moc4zReAJFQ7BjtOUlWZ+i3YQl9gSMOXwnm5gupfHV/YGmGPOek6SSkotT586d4zTTT2U8Qh3GBw==".to_owned(); let claim_bytes = b64_decode("claim_b64", claim_b64.clone()).unwrap(); - let sign = b64_decode("sign_b64", claim_sig_b64.clone()).unwrap(); - let signature: [u8; 64] = sign.try_into().expect("signature must be 64 bytes"); + let signature = b64_decode("sign_b64", claim_sig_b64.clone()).unwrap(); + let signature: [u8; 64] = signature.try_into().expect("signature must be 64 bytes"); verify_claim(&ctr.authority_pubkey, claim_bytes, &signature).unwrap(); let r = ctr.sbt_mint(claim_b64, claim_sig_b64, None); @@ -671,8 +670,8 @@ mod tests { let (_, c_str, sig) = mk_claim_sign(start() / SECOND, "0x12", &k, false); let claim_bytes = b64_decode("claim_b64", c_str).unwrap(); - let sign = b64_decode("sign_b64", sig).unwrap(); - let signature: [u8; 64] = sign.try_into().expect("signature must be 64 bytes"); + let signature = b64_decode("sign_b64", sig).unwrap(); + let signature: [u8; 64] = signature.try_into().expect("signature must be 64 bytes"); let res = verify_claim( &k.public.to_bytes(), claim_bytes,