diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..b5d37f8 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,33 @@ +name: CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Install latest nightly + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + override: true + components: rustfmt + - name: Format code. + uses: actions-rs/cargo@v1 + with: + command: fmt + - name: Build + uses: actions-rs/cargo@v1 + with: + command: build + - name: Tests + uses: actions-rs/cargo@v1 + with: + command: test diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2b6292f --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target +/test/* +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..5ca214a --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "libnode" +version = "0.1.0" +authors = ["luo4lu "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +kv-hal-sled = { git = "https://github.com/Yinet-project/kv-hal-sled" } +kv-hal = { git = "https://github.com/Yinet-project/kv-hal" } +rust-crypto = "0.2.36" +rand = "0.7.3" +async-trait = "0.1" +sled = "0.30.3" +tokio = { version = "0.2", features = ["full"] } + +[dev-dependencies.cargo-husky] +version = "1" +default-features = false +features = ["precommit-hook", "run-cargo-fmt", "run-cargo-test", "run-cargo-clippy"] \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..40f23cb --- /dev/null +++ b/src/lib.rs @@ -0,0 +1 @@ +pub mod node_information; diff --git a/src/node_information.rs b/src/node_information.rs new file mode 100644 index 0000000..56c41a0 --- /dev/null +++ b/src/node_information.rs @@ -0,0 +1,135 @@ +use crypto::{digest::Digest, ed25519, ripemd160::Ripemd160, sha3::Sha3}; +use kv_hal::kv::Storage; +use kv_hal_sled::SledStorage; +use std::convert::TryFrom; +//use sled; + +pub struct NodeInfo { + seed: [u8; 32], + secret_key: [u8; 64], + public_key: [u8; 32], + node_id: [u8; 20], +} + +impl NodeInfo { + pub async fn new(string: &str, key: &[u8]) -> Self { + let seed = NodeInfo::get_value(string, key).await; + if let Ok(seed) = seed { + if let Some(seed) = seed { + NodeInfo::init_node(&seed) + } else { + NodeInfo::rebuild_key() + } + } else { + NodeInfo::rebuild_key() + } + } + + //get seed rand sum from kv-hal-sled trait in the get function + async fn get_value(string: &str, key: &[u8]) -> Result>, sled::Error> { + let stor = SledStorage::new(string); + stor.get(key).await + } + + //如果value存在初始化结构体 + fn init_node(seed_s: &[u8]) -> Self { + //于rebuild_key接口功能类似,不产生随机种子而是根据入参计算秘钥,秘钥-》nodeid + let seed: [u8; 32] = TryFrom::try_from(seed_s).unwrap(); + let (secret_key, public_key) = ed25519::keypair(&seed); + //两次hash let nodeID = ripemd160(sha3(public key)); + //创建一个SHA3-256的对象 + let mut hasher = Sha3::sha3_256(); + //传入公钥 + hasher.input(&public_key); + let mut hex: Vec = Vec::new(); + hasher.result(&mut hex); + + let mut ripemd = Ripemd160::new(); + ripemd.input(&hex); + let mut node_id: [u8; 20] = [0; 20]; + ripemd.result(&mut node_id); + + Self { + seed, + secret_key, + public_key, + node_id, + } + } + + //通过公钥私钥计算出NodeID + pub fn get_node(&self) -> [u8; 20] { + //获取nodeid,rebuild_key里面的算法获取 + let mut hasher = Sha3::sha3_256(); + //传入公钥 + hasher.input(&self.public_key); + let mut hex: Vec = Vec::new(); + hasher.result(&mut hex); + + let mut ripemd = Ripemd160::new(); + ripemd.input(&hex); + let mut node_id: [u8; 20] = [0; 20]; + ripemd.result(&mut node_id); + assert_eq!(node_id, self.node_id); + node_id + } + + //检查是否存在公钥私钥 + pub fn check_key(&self) -> bool { + //由get_value获取的私钥计算出公钥与数据结构中存在的公秘钥比较 + let (secret_key, public_key) = ed25519::keypair(&self.seed); + for (i, _) in secret_key.iter().enumerate() { + assert_eq!(secret_key[i], self.secret_key[i]); + } + assert_eq!(public_key, self.public_key); + if self.secret_key.len() != 64 && self.public_key.len() != 32 { + return false; + } + true + } + + //如果value不存在生成新的公私钥 + fn rebuild_key() -> Self { + let iter: [u8; 32] = [0; 32]; + let mut seed: [u8; 32] = [0; 32]; + for (i, _) in iter.iter().enumerate() { + seed[i] = rand::random::(); + } + let (secret_key, public_key) = ed25519::keypair(&seed); + //两次hash let nodeID = ripemd160(sha3(public key)); + //创建一个SHA3-256的对象 + let mut hasher = Sha3::sha3_256(); + //传入公钥 + hasher.input(&public_key); + let mut hex: Vec = Vec::new(); + hasher.result(&mut hex); + + let mut ripemd = Ripemd160::new(); + ripemd.input(&hex); + let mut node_id: [u8; 20] = [0; 20]; + ripemd.result(&mut node_id); + + Self { + seed, + secret_key, + public_key, + node_id, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + async fn test_node() { + let node_inf = NodeInfo::new("test/test.db", b"seed").await; + + let value = node_inf.check_key(); + assert_eq!(value, false || true); + + let node = node_inf.get_node(); + assert_eq!(node, node_inf.node_id); + } +}