Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

introduce ed25519_verify #1007

Closed
wants to merge 1 commit into from
Closed
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
12 changes: 6 additions & 6 deletions near-sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,19 @@ near-abi = { version = "0.3.0", features = ["__chunked-entries"], optional = tru

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
# alt_bn128 feature will need to be removed on the next version update (now stabilized)
near-vm-logic = { version = "0.14", optional = true, features = ["protocol_feature_alt_bn128"] }
near-primitives-core = { version = "0.14", optional = true }
near-primitives = { version = "0.14", optional = true }
near-crypto = { version = "0.14", optional = true }
near-vm-logic = { git = "https://github.com/near/nearcore.git", rev = "6e08a41084c632010b1d4c42132ad58ecf1398a2", optional = true, features = [] }
near-primitives-core = { git = "https://github.com/near/nearcore.git", rev = "6e08a41084c632010b1d4c42132ad58ecf1398a2", optional = true }
near-primitives = { git = "https://github.com/near/nearcore.git", rev = "6e08a41084c632010b1d4c42132ad58ecf1398a2", optional = true }
near-crypto = { git = "https://github.com/near/nearcore.git", rev = "6e08a41084c632010b1d4c42132ad58ecf1398a2", optional = true }

[dev-dependencies]
rand = "0.8.4"
trybuild = "1.0"
rustversion = "1.0"
rand_xorshift = "0.3"
quickcheck = "1.0"
arbitrary = { version = ">=1.0, <1.1.4", features = ["derive"] }
derive_arbitrary = ">=1.0, <=1.1.6"
arbitrary = { version = "1.2.3", features = ["derive"] }
derive_arbitrary = "1.2.3"
hex = { version = "0.4.3", features = ["serde"] }

[features]
Expand Down
57 changes: 57 additions & 0 deletions near-sdk/src/environment/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,20 @@ pub fn is_valid_account_id(account_id: &[u8]) -> bool {
!last_char_is_separator
}

/// Verifies an ED25519 signature
pub fn ed25519_verify(signature: &[u8], msg: &[u8], pub_key: &[u8]) -> bool {
unsafe {
sys::ed25519_verify(
signature.len() as _,
signature.as_ptr() as _,
msg.len() as _,
msg.as_ptr() as _,
pub_key.len() as _,
pub_key.as_ptr() as _,
) == 1
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -1050,4 +1064,47 @@ mod tests {
.build());
assert_eq!(super::signer_account_pk(), key);
}

#[test]
fn ed25519_verify() {
const SIGNATURE: [u8; 64] = [
145, 193, 203, 18, 114, 227, 14, 117, 33, 213, 121, 66, 130, 14, 25, 4, 36, 120, 46,
142, 226, 215, 7, 66, 122, 112, 97, 30, 249, 135, 61, 165, 221, 249, 252, 23, 105, 40,
56, 70, 31, 152, 236, 141, 154, 122, 207, 20, 75, 118, 79, 90, 168, 6, 221, 122, 213,
29, 126, 196, 216, 104, 191, 6,
];

const BAD_SIGNATURE: [u8; 64] = [1; 64];

// create a forged signature with the `s` scalar not properly reduced
// https://docs.rs/ed25519/latest/src/ed25519/lib.rs.html#302
const FORGED_SIGNATURE: [u8; 64] = {
let mut sig = SIGNATURE;
sig[63] = 0b1110_0001;
sig
};

const PUBLIC_KEY: [u8; 32] = [
32, 122, 6, 120, 146, 130, 30, 37, 215, 112, 241, 251, 160, 196, 124, 17, 255, 75, 129,
62, 84, 22, 46, 206, 158, 184, 57, 224, 118, 35, 26, 182,
];

// create a forged public key to force a PointDecompressionError
// https://docs.rs/ed25519-dalek/latest/src/ed25519_dalek/public.rs.html#142
const FORGED_PUBLIC_KEY: [u8; 32] = {
let mut key = PUBLIC_KEY;
key[31] = 0b1110_0001;
key
};

// 32 bytes message
const MESSAGE: [u8; 32] = [
107, 97, 106, 100, 108, 102, 107, 106, 97, 108, 107, 102, 106, 97, 107, 108, 102, 106,
100, 107, 108, 97, 100, 106, 102, 107, 108, 106, 97, 100, 115, 107,
];
assert!(super::ed25519_verify(&SIGNATURE, &MESSAGE, &PUBLIC_KEY));
assert_eq!(super::ed25519_verify(&BAD_SIGNATURE, &MESSAGE, &FORGED_PUBLIC_KEY), false);
assert_eq!(super::ed25519_verify(&SIGNATURE, &MESSAGE, &FORGED_PUBLIC_KEY), false);
assert_eq!(super::ed25519_verify(&FORGED_SIGNATURE, &MESSAGE, &PUBLIC_KEY), false);
}
}
8 changes: 6 additions & 2 deletions near-sdk/src/environment/mock/external.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use near_primitives::types::TrieNodesCount;
use near_primitives_core::hash::{hash, CryptoHash};
use near_primitives_core::types::{AccountId, Balance};
use near_vm_logic::{External, ValuePtr};
use near_vm_logic::{External, StorageGetMode, ValuePtr};
use std::collections::HashMap;

type Result<T> = ::core::result::Result<T, near_vm_logic::VMLogicError>;
Expand Down Expand Up @@ -41,7 +41,11 @@ impl External for SdkExternal {
Ok(())
}

fn storage_get(&self, key: &[u8]) -> Result<Option<Box<dyn ValuePtr>>> {
fn storage_get(
&self,
key: &[u8],
_storage_get_mode: StorageGetMode,
) -> Result<Option<Box<dyn ValuePtr>>> {
Ok(self
.fake_trie
.get(key)
Expand Down
32 changes: 29 additions & 3 deletions near-sdk/src/environment/mock/mocked_blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl MockedBlockchain {
let context = sdk_context_to_vm_context(context);
ext.fake_trie = storage;
ext.validators = validators.into_iter().map(|(k, v)| (k.parse().unwrap(), v)).collect();
let memory = memory_opt.unwrap_or_else(|| Box::new(MockedMemory {}));
let memory = memory_opt.unwrap_or_else(|| Box::new(MockedMemory::default())); // TODO: find a better way to del with MockedMemory
Copy link
Author

Choose a reason for hiding this comment

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

been having issues with the memory, when running the tests. HELP!

let promise_results = Box::new(promise_results.into_iter().map(From::from).collect());
let config = Box::new(config);
let fees_config = Box::new(fees_config);
Expand Down Expand Up @@ -118,7 +118,7 @@ fn sdk_context_to_vm_context(context: VMContext) -> near_vm_logic::VMContext {
signer_account_pk: context.signer_account_pk.into_bytes(),
predecessor_account_id: context.predecessor_account_id.as_str().parse().unwrap(),
input: context.input,
block_index: context.block_index,
block_height: context.block_index,
block_timestamp: context.block_timestamp,
epoch_height: context.epoch_height,
account_balance: context.account_balance,
Expand Down Expand Up @@ -178,7 +178,13 @@ fn action_to_sdk_action(action: &PrimitivesAction) -> VmAction {

fn pub_key_conversion(key: &VmPublicKey) -> PublicKey {
// Hack by serializing and deserializing the key. This format should be consistent.
String::from(key).parse().unwrap()
// String::from(key).parse().unwrap()
let key_type = if key.key_type() as u8 == 0 { 0u8 } else { 1u8 };

let mut pubkey_bytes = vec![key_type];
pubkey_bytes.extend(key.key_data());

PublicKey::try_from(pubkey_bytes).unwrap()
}

#[cfg(not(target_arch = "wasm32"))]
Expand Down Expand Up @@ -577,4 +583,24 @@ mod mock_chain {
extern "C" fn alt_bn128_pairing_check(value_len: u64, value_ptr: u64) -> u64 {
with_mock_interface(|b| b.alt_bn128_pairing_check(value_len, value_ptr))
}
#[no_mangle]
extern "C" fn ed25519_verify(
signature_len: u64,
signature_ptr: u64,
message_len: u64,
message_ptr: u64,
public_key_len: u64,
public_key_ptr: u64,
) -> u64 {
with_mock_interface(|b| {
b.ed25519_verify(
signature_len,
signature_ptr,
message_len,
message_ptr,
public_key_len,
public_key_ptr,
)
})
}
}
8 changes: 8 additions & 0 deletions sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ extern "C" {
malleability_flag: u64,
register_id: u64,
) -> u64;
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;
// #####################
// # Miscellaneous API #
// #####################
Expand Down