From 65a466434b44fc39f5bb72e7964abdc0daf43b32 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 17 Jan 2018 15:23:22 +0100 Subject: [PATCH 1/6] Signing with crypto. --- substrate/Cargo.lock | 26 ++++++++++ substrate/primitives/Cargo.toml | 2 + substrate/primitives/src/lib.rs | 92 +++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 2ac1c11912..524ec96570 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -261,6 +261,11 @@ dependencies = [ "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "gcc" +version = "0.3.54" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "globset" version = "0.1.4" @@ -701,6 +706,7 @@ dependencies = [ "fixed-hash 0.1.0 (git+https://github.com/paritytech/primitives.git)", "polkadot-serializer 0.1.0", "pretty_assertions 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -846,6 +852,18 @@ dependencies = [ "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rust-crypto" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc-demangle" version = "0.1.5" @@ -856,6 +874,11 @@ name = "rustc-hex" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustc-serialize" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rustc_version" version = "0.1.7" @@ -1199,6 +1222,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82" "checksum futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "118b49cac82e04121117cbd3121ede3147e885627d82c4546b87c702debb90c1" "checksum futures-cpupool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e86f49cc0d92fe1b97a5980ec32d56208272cbb00f15044ea9e2799dde766fdf" +"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" "checksum globset 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90d069fe6beb9be359ef505650b3f73228c5591a3c4b1f32be2f4f44459ffa3a" "checksum hashdb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d97be07c358c5b461268b4ce60304024c5fa5acfd4bd8cd743639f0252003cf5" "checksum heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "54fab2624374e5137ae4df13bf32b0b269cb804df42d13a51221bbd431d1a237" @@ -1247,8 +1271,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" "checksum relay 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f301bafeb60867c85170031bdb2fcf24c8041f33aee09e7b116a58d4e9f781c5" "checksum rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "babe6fce20c0ca9b1582998734c4569082d0ad08e43772a1c6c40aef4f106ef9" +"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" "checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e" +"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" "checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" diff --git a/substrate/primitives/Cargo.toml b/substrate/primitives/Cargo.toml index f31afccf5b..3e2877e073 100644 --- a/substrate/primitives/Cargo.toml +++ b/substrate/primitives/Cargo.toml @@ -11,6 +11,8 @@ serde = "1.0" serde_derive = "1.0" tiny-keccak = "1.3" uint = { git = "https://github.com/paritytech/primitives.git" } +rust-crypto = "0.2.36" +ring = "0.12" [dev-dependencies] polkadot-serializer = { path = "../serializer", version = "0.1" } diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs index ca32f302f3..ad4c6efd58 100644 --- a/substrate/primitives/src/lib.rs +++ b/substrate/primitives/src/lib.rs @@ -21,6 +21,7 @@ extern crate rustc_hex; extern crate serde; extern crate tiny_keccak; +extern crate crypto; #[macro_use] extern crate crunchy; @@ -59,3 +60,94 @@ pub use self::uint::{U256, U512}; pub fn hash(data: &[u8]) -> hash::H256 { tiny_keccak::keccak256(data).into() } + +/// Cool module. +pub mod ed25519 { + use crypto; + use rustc_hex::FromHex; + + #[derive(PartialEq, Clone)] + struct Public ([u8; 32]); + #[derive(Clone)] + struct Pair ([u8; 64]); + #[derive(Clone)] + struct Signature ([u8; 64]); + impl Pair { + pub fn from_seed(seed: &[u8]) -> Pair { + let (secret_public, public) = crypto::ed25519::keypair(seed); + assert_eq!(&secret_public[32..64], &public[0..32]); + Pair(secret_public) + } + pub fn sign(&self, message: &[u8]) -> Signature { + Signature(crypto::ed25519::signature(message, &self.0)) + } + pub fn public(&self) -> Public { + let mut r = [0u8; 32]; + r.copy_from_slice(&self.0[32..64]); + Public(r) + } + } + impl From<&'static str> for Public { + fn from(hex: &'static str) -> Self { + let mut r = [0u8; 32]; + r.copy_from_slice(&FromHex::from_hex(hex).unwrap()[0..32]); + Public(r) + } + } + impl From<&'static str> for Pair { + fn from(hex: &'static str) -> Self { + let mut r = [0u8; 64]; + r.copy_from_slice(&FromHex::from_hex(hex).unwrap()[0..64]); + Pair(r) + } + } + impl From<&'static str> for Signature { + fn from(hex: &'static str) -> Self { + let mut r = [0u8; 64]; + r.copy_from_slice(&FromHex::from_hex(hex).unwrap()[0..64]); + Signature(r) + } + } + + impl PartialEq for Signature { + fn eq(&self, other: &Signature) -> bool { + self.0.iter().eq(other.0.iter()) + } + } + + impl PartialEq for Pair { + fn eq(&self, other: &Pair) -> bool { + self.0.iter().eq(other.0.iter()) + } + } + + impl Signature { + fn verify(&self, message: &[u8], public: &Public) -> bool { + crypto::ed25519::verify(message, &public.0, &self.0) + } + } + + #[cfg(test)] + mod test { + use super::*; + + #[test] + fn test_vector_should_work() { + let pair: Pair = "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a".into(); + let public = pair.public(); + let message = b""; + let signature: Signature = "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b".into(); + assert!(&pair.sign(&message[..]) == &signature); + assert!(signature.verify(&message[..], &public)); + } + + #[test] + fn generated_pair_should_work() { + let pair = Pair::from_seed(b"test"); + let public = pair.public(); + let message = b"Something important"; + let signature = pair.sign(&message[..]); + assert!(signature.verify(&message[..], &public)); + } + } +} From 435c4ac71ae4e8006979f70152cf980760246ed6 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 17 Jan 2018 18:33:20 +0100 Subject: [PATCH 2/6] Introduce Ed25519 crypto. --- substrate/Cargo.lock | 85 ++++++++++++++++----- substrate/ed25519.pk8 | Bin 0 -> 85 bytes substrate/pkcs8.key | 28 +++++++ substrate/primitives/Cargo.toml | 2 +- substrate/primitives/src/lib.rs | 127 ++++++++++++++++++++++++-------- 5 files changed, 191 insertions(+), 51 deletions(-) create mode 100644 substrate/ed25519.pk8 create mode 100644 substrate/pkcs8.key diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 524ec96570..ce227ffe4b 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -129,6 +129,15 @@ dependencies = [ "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "coco" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crunchy" version = "0.1.6" @@ -153,6 +162,11 @@ name = "dtoa" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "either" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "elastic-array" version = "0.9.0" @@ -706,12 +720,13 @@ dependencies = [ "fixed-hash 0.1.0 (git+https://github.com/paritytech/primitives.git)", "polkadot-serializer 0.1.0", "pretty_assertions 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "uint 0.1.0 (git+https://github.com/paritytech/primitives.git)", + "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -791,6 +806,26 @@ dependencies = [ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rayon" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon-core" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "redox_syscall" version = "0.1.31" @@ -829,6 +864,18 @@ dependencies = [ "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ring" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rlp" version = "0.2.1" @@ -852,18 +899,6 @@ dependencies = [ "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rust-crypto" -version = "0.2.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rustc-demangle" version = "0.1.5" @@ -874,11 +909,6 @@ name = "rustc-hex" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "rustc-serialize" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "rustc_version" version = "0.1.7" @@ -905,6 +935,11 @@ name = "scoped-tls" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "scopeguard" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "semver" version = "0.1.20" @@ -1150,6 +1185,11 @@ dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "untrusted" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "utf8-ranges" version = "1.0.0" @@ -1206,10 +1246,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b13a57efd6b30ecd6598ebdb302cca617930b5470647570468a65d12ef9719" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" "checksum clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1b8c532887f1a292d17de05ae858a8fe50a301e196f9ef0ddb7ccd0d1d00f180" +"checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd" "checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" "checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" +"checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3" "checksum elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "258ff6a9a94f648d0379dbd79110e057edbb53eb85cc237e33eadf8e5a30df85" "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" @@ -1265,20 +1307,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum pretty_assertions 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94b6bbc8a323d89a019c4cdde21850522fb8405e97add70827177fc2f86c1495" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6475140dfd8655aeb72e1fd4b7a1cc1c202be65d71669476e392fe62532b9edd" +"checksum rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b614fe08b6665cb9a231d07ac1364b0ef3cb3698f1239ee0c4c3a88a524f54c8" +"checksum rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e64b609139d83da75902f88fd6c01820046840a18471e4dfcd5ac7c0f46bea53" "checksum redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "8dde11f18c108289bef24469638a04dce49da56084f2d50618b226e47eb04509" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" "checksum relay 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f301bafeb60867c85170031bdb2fcf24c8041f33aee09e7b116a58d4e9f781c5" +"checksum ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7d28b30a72c01b458428e0ae988d4149c20d902346902be881e3edc4bb325c" "checksum rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "babe6fce20c0ca9b1582998734c4569082d0ad08e43772a1c6c40aef4f106ef9" -"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" "checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e" -"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" "checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" +"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" "checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" @@ -1310,6 +1354,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" diff --git a/substrate/ed25519.pk8 b/substrate/ed25519.pk8 new file mode 100644 index 0000000000000000000000000000000000000000..57a8e9f84df1dc3175d02132f88bf7d03563ed8a GIT binary patch literal 85 zcmV-b0IL5mQvv}2Fa-t!D`jv5A_O2jp9~yh%qqhDL7XlV#y11mAEmT)YK|2S8mY`X rKcB~;BLg7-wIOt@fg3EC6j=CGA>0MTxofFio@CXjjO!~zYbh_!erz9j literal 0 HcmV?d00001 diff --git a/substrate/pkcs8.key b/substrate/pkcs8.key new file mode 100644 index 0000000000..250fbac646 --- /dev/null +++ b/substrate/pkcs8.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDMpfNjaigc9FKC +8owWoKvAua3O1es2CB7Gq6pFI4Ctv34Wt5XSk83XkSXLOsf2ib1zCpzLUQSVLtH1 +c05uTH6rXLmjbH3lFOUCqD41dIveqo72sekHnYjS23ME2v5JCkg9YFmn32FffHGt +2Uaho+MQZWbpT3SD5tKRdaUUx1f/i16oB4Fnk8zCdQ7NPFru+WUV0cvQnK3rOpOo +KbK59Jo04bHmf/EPeVmxonwt/nmAJRUemuQXPl1cH8sk+t6Bxxp9FLzX6rtmpGDk +mBwrYBNC5auT3L1V2xabI2TKobd/qa+9/Sz41PeHsYLX/cu9Iplvj+LU85gYwv5d +kjvMEI7pAgMBAAECggEBAID7z21HSUUGkMLL0JOqbNYpsWx906PYdl1NcSHmgIIC +AZyb1ShF1CUb7LAsuj+fDPLnK2/R/otwWRDUvggy2ltzM+XWyXqLMtP76kmSzV1o +Lnc6Jt+P4N7VRac3x7GNc36LrbZqylp+er/SA/x46PI6lyRR2eQQpYLcnVF9Wu9K +bbTQ9nH+hxJiRG85GXKjeFkIj7PXBYAiYYcgiPF1RfB3o2R0cXZI24Y5/Ufc3OKg +Jws/VsTIzoxoLd3u6rDKX/N40/VBrGqv76HFqVwgnbxeG+i6HZNIAvZn+6m3a6l5 +APIZp7FfLJ1vZaHP7S7GeNmcz+eJ9Y/FanItohJGfqECgYEA5d17o9Ol3H+6wkQk +a3LU03NfvcdU5TqTOGvzx6yGGASjlByZWb7rMsRMyQ/wP60j+2Hd/G4rXbkF6vee +5uen7geJ6bzhUev1nd1NDcVdZay8x0r3huePUV96k+wU1IrOZrZddlqPyUJMctDy +VbwbDPM0saGx0xIlx/JOC1kEEr0CgYEA4+p/TSEq9DWH5QaMlVxBp48HY4Yrv/gQ +UmNUbCyd7J21Re+7cY3ZGF5IoC2l4K4yPM6ovNipkX9WDZrw8T68sD8yTQzL/tDE +CuXxG+X0b81k5UiZBFIGXiBb8JpoHRKNNGjZTZyBNhOKc902oKoNyTKILX3qI/aL +M2v/SELm5Z0CgYEAx+XZnPn09pF5t3GM/ogpPw3Jh/+t+376AooWwWFuZ7q5Cpfo +YFygq1B8uimLM8T9UqKkat7gBaxe0hyvanyw1FZoAAXLKPP7cGLAnKYzd7VFoka2 +hfIf95MBxVv8LW3c2wPiuYc+HbbzRrIg3KAuIg/qlkNYoobYpk44wrOR0D0CgYB0 +RNeGaGo6ROi7nHixZWwU57FUQ0kkWI8zCHsz6Br0b4vfTqooBr3+YXLZTBA4K4Vz +YdXQ6RKwJ+6laCqMV334x3SIvAOBTc0E5kL3AXuOYZCcK0nsW0/mSsm8V3jPg/xH +BUn9/t4n0RYrf2lz0uzPfBjeZELC7+4ZYHnNyltyPQKBgQCvT40UwZ5yHAt3leWG +stGRTkbupenh2z23hXY0Cio8Zqa7KE5jBWdF4uu27ScK4rhFdS1sgQJFghj6SxRO +VT5PQuRP9ETJIVwNgNQbAxbfeg8DADKGAWX9W5r//WlW1xH0/tSAxX6Pp/IiT9or +cRljrhP8zW6qhj3BKjdivPDgPw== +-----END PRIVATE KEY----- diff --git a/substrate/primitives/Cargo.toml b/substrate/primitives/Cargo.toml index 3e2877e073..045afba827 100644 --- a/substrate/primitives/Cargo.toml +++ b/substrate/primitives/Cargo.toml @@ -11,8 +11,8 @@ serde = "1.0" serde_derive = "1.0" tiny-keccak = "1.3" uint = { git = "https://github.com/paritytech/primitives.git" } -rust-crypto = "0.2.36" ring = "0.12" +untrusted = "0.5" [dev-dependencies] polkadot-serializer = { path = "../serializer", version = "0.1" } diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs index ad4c6efd58..cd166f0a54 100644 --- a/substrate/primitives/src/lib.rs +++ b/substrate/primitives/src/lib.rs @@ -21,7 +21,8 @@ extern crate rustc_hex; extern crate serde; extern crate tiny_keccak; -extern crate crypto; +extern crate ring; +extern crate untrusted; #[macro_use] extern crate crunchy; @@ -63,30 +64,85 @@ pub fn hash(data: &[u8]) -> hash::H256 { /// Cool module. pub mod ed25519 { - use crypto; + use untrusted; + use ring::{rand, signature}; use rustc_hex::FromHex; - #[derive(PartialEq, Clone)] - struct Public ([u8; 32]); + struct HexDisplay<'a>(&'a [u8]); + + impl<'a> ::std::fmt::Display for HexDisplay<'a> { + fn fmt(&self, fmtr: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { + for byte in self.0 { + try!( fmtr.write_fmt(format_args!("{:02x}", byte))); + } + Ok(()) + } + } + + /// A public key. + #[derive(PartialEq, Clone, Debug)] + pub struct Public ([u8; 32]); + + /// A key pair. + pub struct Pair(signature::Ed25519KeyPair); + + /// A signature. #[derive(Clone)] - struct Pair ([u8; 64]); - #[derive(Clone)] - struct Signature ([u8; 64]); + pub struct Signature ([u8; 64]); + impl Pair { - pub fn from_seed(seed: &[u8]) -> Pair { - let (secret_public, public) = crypto::ed25519::keypair(seed); - assert_eq!(&secret_public[32..64], &public[0..32]); - Pair(secret_public) + /// Generate new secure (random) key pair. + pub fn new() -> Pair { + let rng = rand::SystemRandom::new(); + let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap(); + Pair(signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8_bytes)).unwrap()) } + /// Make a new key pair from a seed phrase. + pub fn from_seed(seed: &[u8; 32]) -> Pair { + Pair(signature::Ed25519KeyPair::from_seed_unchecked(untrusted::Input::from(&seed[..])).unwrap()) + } + /// Make a new key pair from the raw secret. + pub fn from_secret(secret: &[u8; 32]) -> Pair { + let mut pkcs8_bytes = FromHex::from_hex("302e020100300506032b657004220420").unwrap(); + pkcs8_bytes.extend_from_slice(&secret[..]); + Pair(signature::Ed25519KeyPair::from_pkcs8_maybe_unchecked(untrusted::Input::from(&pkcs8_bytes)).unwrap()) + } + /// Make a new key pair from the raw secret and public key (it will check to make sure + /// they correspond to each other). + pub fn from_both(secret_public: &[u8; 64]) -> Option { + let mut pkcs8_bytes = FromHex::from_hex("3053020101300506032b657004220420").unwrap(); + pkcs8_bytes.extend_from_slice(&secret_public[0..32]); + pkcs8_bytes.extend_from_slice(&[0xa1u8, 0x23, 0x03, 0x21, 0x00]); + pkcs8_bytes.extend_from_slice(&secret_public[32..64]); + signature::Ed25519KeyPair::from_pkcs8_maybe_unchecked(untrusted::Input::from(&pkcs8_bytes)).ok().map(Pair) + } + /// Sign a message. pub fn sign(&self, message: &[u8]) -> Signature { - Signature(crypto::ed25519::signature(message, &self.0)) + let mut r = [0u8; 64]; + r.copy_from_slice(self.0.sign(message).as_ref()); + Signature(r) } + /// Get the public key. pub fn public(&self) -> Public { let mut r = [0u8; 32]; - r.copy_from_slice(&self.0[32..64]); + let pk = self.0.public_key_bytes(); + r.copy_from_slice(pk); Public(r) } } + impl Signature { + /// Verify a message. + pub fn verify(&self, message: &[u8], public: &Public) -> bool { + let peer_public_key = untrusted::Input::from(&public.0[..]); + let msg = untrusted::Input::from(message); + let sig = untrusted::Input::from(&self.0[..]); + + match signature::verify(&signature::ED25519, peer_public_key, msg, sig) { + Ok(_) => true, + _ => false, + } + } + } impl From<&'static str> for Public { fn from(hex: &'static str) -> Self { let mut r = [0u8; 32]; @@ -96,9 +152,22 @@ pub mod ed25519 { } impl From<&'static str> for Pair { fn from(hex: &'static str) -> Self { - let mut r = [0u8; 64]; - r.copy_from_slice(&FromHex::from_hex(hex).unwrap()[0..64]); - Pair(r) + let data = FromHex::from_hex(hex).expect("Key pair given is static so hex should be good."); + match data.len() { + 32 => { + let mut r = [0u8; 32]; + r.copy_from_slice(&data[0..32]); + Pair::from_secret(&r) + } + 64 => { + let mut r = [0u8; 64]; + r.copy_from_slice(&data[0..64]); + Pair::from_both(&r).expect("Key pair given is static so should be good.") + } + _ => { + panic!("Key pair given is static so should be correct length."); + } + } } } impl From<&'static str> for Signature { @@ -115,26 +184,15 @@ pub mod ed25519 { } } - impl PartialEq for Pair { - fn eq(&self, other: &Pair) -> bool { - self.0.iter().eq(other.0.iter()) - } - } - - impl Signature { - fn verify(&self, message: &[u8], public: &Public) -> bool { - crypto::ed25519::verify(message, &public.0, &self.0) - } - } - #[cfg(test)] mod test { use super::*; #[test] fn test_vector_should_work() { - let pair: Pair = "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a".into(); + let pair: Pair = "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60".into(); let public = pair.public(); + assert_eq!(public, "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a".into()); let message = b""; let signature: Signature = "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b".into(); assert!(&pair.sign(&message[..]) == &signature); @@ -143,7 +201,16 @@ pub mod ed25519 { #[test] fn generated_pair_should_work() { - let pair = Pair::from_seed(b"test"); + let pair = Pair::new(); + let public = pair.public(); + let message = b"Something important"; + let signature = pair.sign(&message[..]); + assert!(signature.verify(&message[..], &public)); + } + + #[test] + fn seeded_pair_should_work() { + let pair = Pair::from_seed(b"12345678901234567890123456789012"); let public = pair.public(); let message = b"Something important"; let signature = pair.sign(&message[..]); From 6360a56e725bd8b4026c587db3ea5dc02b9f4076 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 17 Jan 2018 18:34:40 +0100 Subject: [PATCH 3/6] Repotting. --- substrate/primitives/src/ed25519.rs | 155 +++++++++++++++++++++++++++ substrate/primitives/src/lib.rs | 158 +--------------------------- 2 files changed, 156 insertions(+), 157 deletions(-) create mode 100644 substrate/primitives/src/ed25519.rs diff --git a/substrate/primitives/src/ed25519.rs b/substrate/primitives/src/ed25519.rs new file mode 100644 index 0000000000..676f8ef266 --- /dev/null +++ b/substrate/primitives/src/ed25519.rs @@ -0,0 +1,155 @@ +//! Simple Ed25519 API. + +use untrusted; +use ring::{rand, signature}; +use rustc_hex::FromHex; + +struct HexDisplay<'a>(&'a [u8]); + +impl<'a> ::std::fmt::Display for HexDisplay<'a> { + fn fmt(&self, fmtr: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { + for byte in self.0 { + try!( fmtr.write_fmt(format_args!("{:02x}", byte))); + } + Ok(()) + } +} + +/// A public key. +#[derive(PartialEq, Clone, Debug)] +pub struct Public ([u8; 32]); + +/// A key pair. +pub struct Pair(signature::Ed25519KeyPair); + +/// A signature. +#[derive(Clone)] +pub struct Signature ([u8; 64]); + +impl Pair { + /// Generate new secure (random) key pair. + pub fn new() -> Pair { + let rng = rand::SystemRandom::new(); + let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap(); + Pair(signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8_bytes)).unwrap()) + } + /// Make a new key pair from a seed phrase. + pub fn from_seed(seed: &[u8; 32]) -> Pair { + Pair(signature::Ed25519KeyPair::from_seed_unchecked(untrusted::Input::from(&seed[..])).unwrap()) + } + /// Make a new key pair from the raw secret. + pub fn from_secret(secret: &[u8; 32]) -> Pair { + let mut pkcs8_bytes = FromHex::from_hex("302e020100300506032b657004220420").unwrap(); + pkcs8_bytes.extend_from_slice(&secret[..]); + Pair(signature::Ed25519KeyPair::from_pkcs8_maybe_unchecked(untrusted::Input::from(&pkcs8_bytes)).unwrap()) + } + /// Make a new key pair from the raw secret and public key (it will check to make sure + /// they correspond to each other). + pub fn from_both(secret_public: &[u8; 64]) -> Option { + let mut pkcs8_bytes = FromHex::from_hex("3053020101300506032b657004220420").unwrap(); + pkcs8_bytes.extend_from_slice(&secret_public[0..32]); + pkcs8_bytes.extend_from_slice(&[0xa1u8, 0x23, 0x03, 0x21, 0x00]); + pkcs8_bytes.extend_from_slice(&secret_public[32..64]); + signature::Ed25519KeyPair::from_pkcs8_maybe_unchecked(untrusted::Input::from(&pkcs8_bytes)).ok().map(Pair) + } + /// Sign a message. + pub fn sign(&self, message: &[u8]) -> Signature { + let mut r = [0u8; 64]; + r.copy_from_slice(self.0.sign(message).as_ref()); + Signature(r) + } + /// Get the public key. + pub fn public(&self) -> Public { + let mut r = [0u8; 32]; + let pk = self.0.public_key_bytes(); + r.copy_from_slice(pk); + Public(r) + } +} +impl Signature { + /// Verify a message. + pub fn verify(&self, message: &[u8], public: &Public) -> bool { + let peer_public_key = untrusted::Input::from(&public.0[..]); + let msg = untrusted::Input::from(message); + let sig = untrusted::Input::from(&self.0[..]); + + match signature::verify(&signature::ED25519, peer_public_key, msg, sig) { + Ok(_) => true, + _ => false, + } + } +} +impl From<&'static str> for Public { + fn from(hex: &'static str) -> Self { + let mut r = [0u8; 32]; + r.copy_from_slice(&FromHex::from_hex(hex).unwrap()[0..32]); + Public(r) + } +} +impl From<&'static str> for Pair { + fn from(hex: &'static str) -> Self { + let data = FromHex::from_hex(hex).expect("Key pair given is static so hex should be good."); + match data.len() { + 32 => { + let mut r = [0u8; 32]; + r.copy_from_slice(&data[0..32]); + Pair::from_secret(&r) + } + 64 => { + let mut r = [0u8; 64]; + r.copy_from_slice(&data[0..64]); + Pair::from_both(&r).expect("Key pair given is static so should be good.") + } + _ => { + panic!("Key pair given is static so should be correct length."); + } + } + } +} +impl From<&'static str> for Signature { + fn from(hex: &'static str) -> Self { + let mut r = [0u8; 64]; + r.copy_from_slice(&FromHex::from_hex(hex).unwrap()[0..64]); + Signature(r) + } +} + +impl PartialEq for Signature { + fn eq(&self, other: &Signature) -> bool { + self.0.iter().eq(other.0.iter()) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_vector_should_work() { + let pair: Pair = "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60".into(); + let public = pair.public(); + assert_eq!(public, "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a".into()); + let message = b""; + let signature: Signature = "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b".into(); + assert!(&pair.sign(&message[..]) == &signature); + assert!(signature.verify(&message[..], &public)); + } + + #[test] + fn generated_pair_should_work() { + let pair = Pair::new(); + let public = pair.public(); + let message = b"Something important"; + let signature = pair.sign(&message[..]); + assert!(signature.verify(&message[..], &public)); + } + + #[test] + fn seeded_pair_should_work() { + let pair = Pair::from_seed(b"12345678901234567890123456789012"); + let public = pair.public(); + let message = b"Something important"; + let signature = pair.sign(&message[..]); + assert!(signature.verify(&message[..], &public)); + } +} diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs index cd166f0a54..fc26658200 100644 --- a/substrate/primitives/src/lib.rs +++ b/substrate/primitives/src/lib.rs @@ -48,6 +48,7 @@ pub mod hash; pub mod parachain; pub mod uint; pub mod validator; +pub mod ed25519; /// Alias to 160-bit hash when used in the context of an account address. pub type Address = hash::H160; @@ -61,160 +62,3 @@ pub use self::uint::{U256, U512}; pub fn hash(data: &[u8]) -> hash::H256 { tiny_keccak::keccak256(data).into() } - -/// Cool module. -pub mod ed25519 { - use untrusted; - use ring::{rand, signature}; - use rustc_hex::FromHex; - - struct HexDisplay<'a>(&'a [u8]); - - impl<'a> ::std::fmt::Display for HexDisplay<'a> { - fn fmt(&self, fmtr: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { - for byte in self.0 { - try!( fmtr.write_fmt(format_args!("{:02x}", byte))); - } - Ok(()) - } - } - - /// A public key. - #[derive(PartialEq, Clone, Debug)] - pub struct Public ([u8; 32]); - - /// A key pair. - pub struct Pair(signature::Ed25519KeyPair); - - /// A signature. - #[derive(Clone)] - pub struct Signature ([u8; 64]); - - impl Pair { - /// Generate new secure (random) key pair. - pub fn new() -> Pair { - let rng = rand::SystemRandom::new(); - let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap(); - Pair(signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8_bytes)).unwrap()) - } - /// Make a new key pair from a seed phrase. - pub fn from_seed(seed: &[u8; 32]) -> Pair { - Pair(signature::Ed25519KeyPair::from_seed_unchecked(untrusted::Input::from(&seed[..])).unwrap()) - } - /// Make a new key pair from the raw secret. - pub fn from_secret(secret: &[u8; 32]) -> Pair { - let mut pkcs8_bytes = FromHex::from_hex("302e020100300506032b657004220420").unwrap(); - pkcs8_bytes.extend_from_slice(&secret[..]); - Pair(signature::Ed25519KeyPair::from_pkcs8_maybe_unchecked(untrusted::Input::from(&pkcs8_bytes)).unwrap()) - } - /// Make a new key pair from the raw secret and public key (it will check to make sure - /// they correspond to each other). - pub fn from_both(secret_public: &[u8; 64]) -> Option { - let mut pkcs8_bytes = FromHex::from_hex("3053020101300506032b657004220420").unwrap(); - pkcs8_bytes.extend_from_slice(&secret_public[0..32]); - pkcs8_bytes.extend_from_slice(&[0xa1u8, 0x23, 0x03, 0x21, 0x00]); - pkcs8_bytes.extend_from_slice(&secret_public[32..64]); - signature::Ed25519KeyPair::from_pkcs8_maybe_unchecked(untrusted::Input::from(&pkcs8_bytes)).ok().map(Pair) - } - /// Sign a message. - pub fn sign(&self, message: &[u8]) -> Signature { - let mut r = [0u8; 64]; - r.copy_from_slice(self.0.sign(message).as_ref()); - Signature(r) - } - /// Get the public key. - pub fn public(&self) -> Public { - let mut r = [0u8; 32]; - let pk = self.0.public_key_bytes(); - r.copy_from_slice(pk); - Public(r) - } - } - impl Signature { - /// Verify a message. - pub fn verify(&self, message: &[u8], public: &Public) -> bool { - let peer_public_key = untrusted::Input::from(&public.0[..]); - let msg = untrusted::Input::from(message); - let sig = untrusted::Input::from(&self.0[..]); - - match signature::verify(&signature::ED25519, peer_public_key, msg, sig) { - Ok(_) => true, - _ => false, - } - } - } - impl From<&'static str> for Public { - fn from(hex: &'static str) -> Self { - let mut r = [0u8; 32]; - r.copy_from_slice(&FromHex::from_hex(hex).unwrap()[0..32]); - Public(r) - } - } - impl From<&'static str> for Pair { - fn from(hex: &'static str) -> Self { - let data = FromHex::from_hex(hex).expect("Key pair given is static so hex should be good."); - match data.len() { - 32 => { - let mut r = [0u8; 32]; - r.copy_from_slice(&data[0..32]); - Pair::from_secret(&r) - } - 64 => { - let mut r = [0u8; 64]; - r.copy_from_slice(&data[0..64]); - Pair::from_both(&r).expect("Key pair given is static so should be good.") - } - _ => { - panic!("Key pair given is static so should be correct length."); - } - } - } - } - impl From<&'static str> for Signature { - fn from(hex: &'static str) -> Self { - let mut r = [0u8; 64]; - r.copy_from_slice(&FromHex::from_hex(hex).unwrap()[0..64]); - Signature(r) - } - } - - impl PartialEq for Signature { - fn eq(&self, other: &Signature) -> bool { - self.0.iter().eq(other.0.iter()) - } - } - - #[cfg(test)] - mod test { - use super::*; - - #[test] - fn test_vector_should_work() { - let pair: Pair = "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60".into(); - let public = pair.public(); - assert_eq!(public, "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a".into()); - let message = b""; - let signature: Signature = "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b".into(); - assert!(&pair.sign(&message[..]) == &signature); - assert!(signature.verify(&message[..], &public)); - } - - #[test] - fn generated_pair_should_work() { - let pair = Pair::new(); - let public = pair.public(); - let message = b"Something important"; - let signature = pair.sign(&message[..]); - assert!(signature.verify(&message[..], &public)); - } - - #[test] - fn seeded_pair_should_work() { - let pair = Pair::from_seed(b"12345678901234567890123456789012"); - let public = pair.public(); - let message = b"Something important"; - let signature = pair.sign(&message[..]); - assert!(signature.verify(&message[..], &public)); - } - } -} From 6b1153d9757f98d7a8d226bd319f52bb2bcbc215 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 17 Jan 2018 19:05:31 +0100 Subject: [PATCH 4/6] Add ed25519_verify external. --- substrate/executor/src/wasm_executor.rs | 19 +++++++++++++++++++ substrate/primitives/src/ed25519.rs | 22 ++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index 8597656c51..719343f8fa 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -27,6 +27,7 @@ use error::{Error, ErrorKind, Result}; use wasm_utils::{MemoryInstance, UserDefinedElements, AddModuleWithoutFullDependentInstance}; use tiny_keccak; +use primitives::ed25519; struct Heap { end: u32, @@ -148,6 +149,24 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, [0; 32] }; let _ = this.memory.set(out, &result); + }, + ext_ed25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32 => { + (||{ + let mut sig = [0u8; 64]; + if let Err(_) = this.memory.get_into(sig_data, &mut sig[..]) { + return 0; + }; + let mut pubkey = [0u8; 32]; + if let Err(_) = this.memory.get_into(pubkey_data, &mut pubkey[..]) { + return 0; + }; + + if let Ok(msg) = this.memory.get(msg_data, msg_len as usize) { + if ed25519::Signature::from(sig).verify(&msg, &ed25519::Public::from(pubkey)) { 1 } else { 0 } + } else { + 0 + } + })() } => <'e, E: Externalities + 'e> ); diff --git a/substrate/primitives/src/ed25519.rs b/substrate/primitives/src/ed25519.rs index 676f8ef266..576d1a409a 100644 --- a/substrate/primitives/src/ed25519.rs +++ b/substrate/primitives/src/ed25519.rs @@ -26,6 +26,28 @@ pub struct Pair(signature::Ed25519KeyPair); #[derive(Clone)] pub struct Signature ([u8; 64]); +impl Signature { + pub fn from(data: [u8; 64]) -> Self { + Signature(data) + } + pub fn from_slice(data: &[u8]) -> Self { + let mut r = [0u8; 64]; + r.copy_from_slice(data); + Signature(r) + } +} + +impl Public { + pub fn from(data: [u8; 32]) -> Self { + Public(data) + } + pub fn from_slice(data: &[u8]) -> Self { + let mut r = [0u8; 32]; + r.copy_from_slice(data); + Public(r) + } +} + impl Pair { /// Generate new secure (random) key pair. pub fn new() -> Pair { From ec78b7244a6c8355257d7b0f01fc390f0d9cd28b Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 17 Jan 2018 19:17:34 +0100 Subject: [PATCH 5/6] Introduce Ed25519 verify as an external. --- substrate/native-runtime/support/src/lib.rs | 13 ++++++++++--- substrate/primitives/src/ed25519.rs | 11 +++++++++++ substrate/wasm-runtime/support/src/lib.rs | 11 +++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index a2fe13eb10..7f2de2d103 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -3,6 +3,9 @@ extern crate environmental; extern crate polkadot_state_machine; extern crate tiny_keccak; +use std::fmt; +use primitives::ed25519; + pub use std::vec::Vec; pub use std::rc::Rc; pub use std::cell::RefCell; @@ -11,7 +14,6 @@ pub use std::slice; pub use std::mem::{size_of, transmute, swap, uninitialized}; pub use polkadot_state_machine::Externalities; -use std::fmt; // TODO: use the real error, not NoError. @@ -63,9 +65,9 @@ pub fn storage_into(_key: &[u8]) -> Option { }).unwrap_or(None) } -pub fn set_storage(_key: &[u8], _value: &[u8]) { +pub fn set_storage(key: &[u8], value: &[u8]) { ext::with(|holder| - holder.ext.set_storage(_key.to_vec(), _value.to_vec()) + holder.ext.set_storage(key.to_vec(), value.to_vec()) ); } @@ -79,6 +81,11 @@ pub fn chain_id() -> u64 { /// Conduct a Keccak-256 hash of the given data. pub use tiny_keccak::keccak256; +/// Verify a ed25519 signature. +pub fn ed25519_verify(sig: &[u8; 64], msg: &[u8], pubkey: &[u8; 32]) -> bool { + ed25519::verify(&sig[..], msg, &pubkey[..]) +} + /// Execute the given closure with global function available whose functionality routes into the /// externalities `ext`. Forwards the value that the closure returns. pub fn with_externalities R>(ext: &mut Externalities, f: F) -> R { diff --git a/substrate/primitives/src/ed25519.rs b/substrate/primitives/src/ed25519.rs index 576d1a409a..58556b6669 100644 --- a/substrate/primitives/src/ed25519.rs +++ b/substrate/primitives/src/ed25519.rs @@ -15,6 +15,17 @@ impl<'a> ::std::fmt::Display for HexDisplay<'a> { } } +pub fn verify(sig: &[u8], message: &[u8], public: &[u8]) -> bool { + let public_key = untrusted::Input::from(public); + let msg = untrusted::Input::from(message); + let sig = untrusted::Input::from(sig); + + match signature::verify(&signature::ED25519, public_key, msg, sig) { + Ok(_) => true, + _ => false, + } +} + /// A public key. #[derive(PartialEq, Clone, Debug)] pub struct Public ([u8; 32]); diff --git a/substrate/wasm-runtime/support/src/lib.rs b/substrate/wasm-runtime/support/src/lib.rs index ae3feb14c9..9f75504513 100644 --- a/substrate/wasm-runtime/support/src/lib.rs +++ b/substrate/wasm-runtime/support/src/lib.rs @@ -30,6 +30,7 @@ extern "C" { fn ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32) -> u32; fn ext_chain_id() -> u64; fn ext_keccak256(data: *const u8, len: u32, out: *mut u8); + fn ext_ed25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32; } pub fn storage(key: &[u8]) -> Vec { @@ -89,6 +90,16 @@ pub fn keccak256(data: &[u8]) -> [u8; 32] { } } +/// Verify a ed25519 signature. +pub fn ed25519_verify(sig: &[u8; 64], msg: &[u8], pubkey: &[u8; 32]) -> bool { + unsafe { + match ext_ed25519_verify(&msg[0], msg.len() as u32, &sig[0], &pubkey[0]) { + 0 => false, + _ => true, + } + } +} + pub trait Printable { fn print(self); } From 3b850c7ed1208268b248782d001e1438d34eb69b Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 17 Jan 2018 19:20:48 +0100 Subject: [PATCH 6/6] Compile fixes. --- substrate/Cargo.lock | 1 + substrate/native-runtime/support/Cargo.toml | 1 + substrate/native-runtime/support/src/lib.rs | 1 + 3 files changed, 3 insertions(+) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index ce227ffe4b..f886c60be5 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -895,6 +895,7 @@ dependencies = [ "environmental 0.1.0", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "polkadot-primitives 0.1.0", "polkadot-state-machine 0.1.0", "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/substrate/native-runtime/support/Cargo.toml b/substrate/native-runtime/support/Cargo.toml index 185dea5f92..f576037bd2 100644 --- a/substrate/native-runtime/support/Cargo.toml +++ b/substrate/native-runtime/support/Cargo.toml @@ -12,3 +12,4 @@ parking_lot = "0.5" polkadot-state-machine = { path = "../../state_machine" , version = "0.1" } environmental = { path = "../../environmental", version = "0.1.0" } tiny-keccak = "1.3" +polkadot-primitives = { path = "../../primitives", version = "0.1.0" } diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index 7f2de2d103..02a4b8b2ed 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -2,6 +2,7 @@ extern crate environmental; extern crate polkadot_state_machine; extern crate tiny_keccak; +extern crate polkadot_primitives as primitives; use std::fmt; use primitives::ed25519;