mirror of
https://github.com/fluencelabs/trust-graph
synced 2024-12-04 23:30:19 +00:00
commit
e922f7bf97
19
Cargo.lock
generated
19
Cargo.lock
generated
@ -356,6 +356,23 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fluence-identity"
|
||||||
|
version = "0.2.0"
|
||||||
|
dependencies = [
|
||||||
|
"bs58 0.3.1",
|
||||||
|
"derivative",
|
||||||
|
"ed25519-dalek",
|
||||||
|
"failure",
|
||||||
|
"fluence-fork-libp2p-core",
|
||||||
|
"log",
|
||||||
|
"rand 0.7.3",
|
||||||
|
"ref-cast",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"signature",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
@ -1325,11 +1342,13 @@ dependencies = [
|
|||||||
"ed25519-dalek",
|
"ed25519-dalek",
|
||||||
"failure",
|
"failure",
|
||||||
"fluence-fork-libp2p-core",
|
"fluence-fork-libp2p-core",
|
||||||
|
"fluence-identity",
|
||||||
"log",
|
"log",
|
||||||
"rand 0.7.3",
|
"rand 0.7.3",
|
||||||
"ref-cast",
|
"ref-cast",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"signature",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -9,6 +9,7 @@ license = "Apache-2.0"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
libp2p-core = { package = "fluence-fork-libp2p-core", version = "0.26.0" }
|
libp2p-core = { package = "fluence-fork-libp2p-core", version = "0.26.0" }
|
||||||
serde = { version = "=1.0.118", features = ["derive"] }
|
serde = { version = "=1.0.118", features = ["derive"] }
|
||||||
|
fluence-identity = { path = "identity" }
|
||||||
serde_json = "1.0.58"
|
serde_json = "1.0.58"
|
||||||
bs58 = "0.3.1"
|
bs58 = "0.3.1"
|
||||||
failure = "0.1.6"
|
failure = "0.1.6"
|
||||||
@ -16,6 +17,5 @@ log = "0.4.11"
|
|||||||
ref-cast = "1.0.2"
|
ref-cast = "1.0.2"
|
||||||
derivative = "2.1.1"
|
derivative = "2.1.1"
|
||||||
ed25519-dalek = "1.0.1"
|
ed25519-dalek = "1.0.1"
|
||||||
|
rand = "0.7.0"
|
||||||
[dev-dependencies]
|
signature = "1.3.0"
|
||||||
rand = "0.7.3"
|
|
||||||
|
1614
bin/Cargo.lock
generated
Normal file
1614
bin/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
16
bin/Cargo.toml
Normal file
16
bin/Cargo.toml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
[package]
|
||||||
|
name = "trust-graph-wasm"
|
||||||
|
version = "0.2.0"
|
||||||
|
authors = ["Fluence Labs"]
|
||||||
|
edition = "2018"
|
||||||
|
description = "trust graph wasm"
|
||||||
|
license = "Apache-2.0"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "trust-graph"
|
||||||
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
trust-graph = { path = "../" }
|
||||||
|
log = "0.4.8"
|
||||||
|
fluence = { version = "0.2.18", features = ["logger"] }
|
8
bin/src/main.rs
Normal file
8
bin/src/main.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use fluence::WasmLoggerBuilder;
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
WasmLoggerBuilder::new()
|
||||||
|
.with_log_level(log::Level::Info)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
}
|
0
bin/src/service_api.rs
Normal file
0
bin/src/service_api.rs
Normal file
3
bin/src/storage_impl.rs
Normal file
3
bin/src/storage_impl.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// store list of trusts
|
||||||
|
// check if trust is already in list before adding
|
||||||
|
// if there is an older trust - don't add received trust
|
20
identity/Cargo.toml
Normal file
20
identity/Cargo.toml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
[package]
|
||||||
|
name = "fluence-identity"
|
||||||
|
version = "0.2.0"
|
||||||
|
authors = ["Fluence Labs"]
|
||||||
|
edition = "2018"
|
||||||
|
description = "identity"
|
||||||
|
license = "Apache-2.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libp2p-core = { package = "fluence-fork-libp2p-core", version = "0.26.0" }
|
||||||
|
serde = { version = "=1.0.118", features = ["derive"] }
|
||||||
|
serde_json = "1.0.58"
|
||||||
|
bs58 = "0.3.1"
|
||||||
|
failure = "0.1.6"
|
||||||
|
log = "0.4.11"
|
||||||
|
ref-cast = "1.0.2"
|
||||||
|
derivative = "2.1.1"
|
||||||
|
ed25519-dalek = "1.0.1"
|
||||||
|
rand = "0.7.0"
|
||||||
|
signature = "1.3.0"
|
@ -14,71 +14,79 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::ed25519::{Keypair as Libp2pKeyPair, PublicKey, SecretKey};
|
use crate::ed25519::Keypair as Libp2pKeyPair;
|
||||||
use ed25519_dalek::SignatureError;
|
use ed25519_dalek::SignatureError;
|
||||||
use libp2p_core::identity::error::DecodingError;
|
use ed25519_dalek::{PublicKey, SecretKey, Signer};
|
||||||
|
|
||||||
|
use core::fmt::Debug;
|
||||||
|
use rand::rngs::OsRng;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
pub type Signature = Vec<u8>;
|
pub type Signature = ed25519_dalek::Signature;
|
||||||
|
|
||||||
/// An Ed25519 keypair.
|
/// An Ed25519 keypair.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Debug)]
|
||||||
pub struct KeyPair {
|
pub struct KeyPair {
|
||||||
pub key_pair: Libp2pKeyPair,
|
pub key_pair: ed25519_dalek::Keypair,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KeyPair {
|
impl KeyPair {
|
||||||
/// Generate a new Ed25519 keypair.
|
/// Generate a new Ed25519 keypair.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn generate() -> Self {
|
pub fn generate() -> Self {
|
||||||
let kp = Libp2pKeyPair::generate();
|
let mut csprng = OsRng {};
|
||||||
|
let kp = ed25519_dalek::Keypair::generate(&mut csprng);
|
||||||
kp.into()
|
kp.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_bytes(sk_bytes: impl AsMut<[u8]>) -> Result<Self, DecodingError> {
|
pub fn from_bytes(sk_bytes: &[u8]) -> Result<Self, SignatureError> {
|
||||||
let sk = SecretKey::from_bytes(sk_bytes)?;
|
let kp = ed25519_dalek::Keypair::from_bytes(sk_bytes)?;
|
||||||
Ok(Libp2pKeyPair::from(sk).into())
|
Ok(KeyPair { key_pair: kp })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encode the keypair into a byte array by concatenating the bytes
|
/// Encode the keypair into a byte array by concatenating the bytes
|
||||||
/// of the secret scalar and the compressed public point/
|
/// of the secret scalar and the compressed public point/
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn encode(&self) -> [u8; 64] {
|
pub fn encode(&self) -> [u8; 64] {
|
||||||
self.key_pair.encode()
|
self.key_pair.to_bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decode a keypair from the format produced by `encode`.
|
/// Decode a keypair from the format produced by `encode`.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn decode(kp: &[u8]) -> Result<KeyPair, SignatureError> {
|
pub fn decode(kp: &[u8]) -> Result<KeyPair, SignatureError> {
|
||||||
let kp = ed25519_dalek::Keypair::from_bytes(kp)?;
|
let kp = ed25519_dalek::Keypair::from_bytes(kp)?;
|
||||||
Ok(Self {
|
Ok(Self { key_pair: kp })
|
||||||
key_pair: kp.into(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the public key of this keypair.
|
/// Get the public key of this keypair.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn public_key(&self) -> PublicKey {
|
pub fn public_key(&self) -> PublicKey {
|
||||||
self.key_pair.public()
|
self.key_pair.public
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sign a message using the private key of this keypair.
|
/// Sign a message using the private key of this keypair.
|
||||||
pub fn sign(&self, msg: &[u8]) -> Vec<u8> {
|
pub fn sign(&self, msg: &[u8]) -> Signature {
|
||||||
self.key_pair.sign(msg)
|
self.key_pair.sign(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Verify the Ed25519 signature on a message using the public key.
|
/// Verify the Ed25519 signature on a message using the public key.
|
||||||
pub fn verify(pk: &PublicKey, msg: &[u8], signature: &[u8]) -> Result<(), String> {
|
pub fn verify(pk: &PublicKey, msg: &[u8], signature: Signature) -> Result<(), String> {
|
||||||
if pk.verify(msg, signature) {
|
// let signature = ed25519_dalek::Signature::from_bytes(signature)
|
||||||
return Ok(());
|
// .map_err(|err| format!("Cannot convert bytes to a signature: {:?}", err))?;
|
||||||
}
|
pk.verify_strict(msg, &signature)
|
||||||
|
.map_err(|err| format!("Signature verification failed: {:?}", err))
|
||||||
Err("Signature is not valid.".to_string())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Libp2pKeyPair> for KeyPair {
|
impl From<Libp2pKeyPair> for KeyPair {
|
||||||
fn from(kp: Libp2pKeyPair) -> Self {
|
fn from(kp: Libp2pKeyPair) -> Self {
|
||||||
|
let kp = ed25519_dalek::Keypair::from_bytes(&kp.encode()).unwrap();
|
||||||
|
Self { key_pair: kp }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ed25519_dalek::Keypair> for KeyPair {
|
||||||
|
fn from(kp: ed25519_dalek::Keypair) -> Self {
|
||||||
Self { key_pair: kp }
|
Self { key_pair: kp }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,3 +132,16 @@ impl<'de> serde::Deserialize<'de> for KeyPair {
|
|||||||
deserializer.deserialize_str(KeyPairVisitor)
|
deserializer.deserialize_str(KeyPairVisitor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Clone for KeyPair {
|
||||||
|
fn clone(&self) -> KeyPair {
|
||||||
|
let mut sk_bytes = self.key_pair.secret.to_bytes();
|
||||||
|
let secret = SecretKey::from_bytes(&mut sk_bytes)
|
||||||
|
.expect("ed25519::SecretKey::from_bytes(to_bytes(k)) != k");
|
||||||
|
let public = PublicKey::from_bytes(&self.key_pair.public.to_bytes())
|
||||||
|
.expect("ed25519::PublicKey::from_bytes(to_bytes(k)) != k");
|
||||||
|
KeyPair {
|
||||||
|
key_pair: ed25519_dalek::Keypair { secret, public },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
33
identity/src/lib.rs
Normal file
33
identity/src/lib.rs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 Fluence Labs Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#![recursion_limit = "512"]
|
||||||
|
#![warn(rust_2018_idioms)]
|
||||||
|
#![deny(
|
||||||
|
dead_code,
|
||||||
|
nonstandard_style,
|
||||||
|
unused_imports,
|
||||||
|
unused_mut,
|
||||||
|
unused_variables,
|
||||||
|
unused_unsafe,
|
||||||
|
unreachable_patterns
|
||||||
|
)]
|
||||||
|
|
||||||
|
pub mod key_pair;
|
||||||
|
|
||||||
|
pub use key_pair::KeyPair;
|
||||||
|
|
||||||
|
pub(crate) use libp2p_core::identity::ed25519;
|
@ -14,9 +14,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::ed25519::PublicKey;
|
|
||||||
use crate::key_pair::KeyPair;
|
|
||||||
use crate::trust::{Trust, TRUST_LEN};
|
use crate::trust::{Trust, TRUST_LEN};
|
||||||
|
use ed25519_dalek::PublicKey;
|
||||||
|
use fluence_identity::key_pair::KeyPair;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
@ -236,6 +236,7 @@ impl FromStr for Certificate {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::misc::current_time;
|
use crate::misc::current_time;
|
||||||
|
use fluence_identity::key_pair::KeyPair;
|
||||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
pub fn one_second() -> Duration {
|
pub fn one_second() -> Duration {
|
||||||
@ -260,7 +261,7 @@ mod tests {
|
|||||||
|
|
||||||
let new_cert = Certificate::issue(
|
let new_cert = Certificate::issue(
|
||||||
&second_kp,
|
&second_kp,
|
||||||
third_kp.key_pair.public(),
|
third_kp.key_pair.public,
|
||||||
&cert,
|
&cert,
|
||||||
cur_time.checked_add(one_second()).unwrap(),
|
cur_time.checked_add(one_second()).unwrap(),
|
||||||
cur_time,
|
cur_time,
|
||||||
@ -287,7 +288,7 @@ mod tests {
|
|||||||
|
|
||||||
let new_cert = Certificate::issue(
|
let new_cert = Certificate::issue(
|
||||||
&second_kp,
|
&second_kp,
|
||||||
third_kp.key_pair.public(),
|
third_kp.key_pair.public,
|
||||||
&cert,
|
&cert,
|
||||||
cur_time.checked_add(one_second()).unwrap(),
|
cur_time.checked_add(one_second()).unwrap(),
|
||||||
cur_time,
|
cur_time,
|
||||||
@ -347,7 +348,7 @@ mod tests {
|
|||||||
|
|
||||||
let new_cert = Certificate::issue(
|
let new_cert = Certificate::issue(
|
||||||
&second_kp,
|
&second_kp,
|
||||||
third_kp.key_pair.public(),
|
third_kp.key_pair.public,
|
||||||
&cert,
|
&cert,
|
||||||
cur_time.checked_add(one_year()).unwrap(),
|
cur_time.checked_add(one_year()).unwrap(),
|
||||||
cur_time,
|
cur_time,
|
||||||
@ -358,18 +359,18 @@ mod tests {
|
|||||||
|
|
||||||
println!(
|
println!(
|
||||||
"root_kp:\n\tprivate: {}\n\tpublic: {}",
|
"root_kp:\n\tprivate: {}\n\tpublic: {}",
|
||||||
bs58::encode(root_kp.key_pair.secret()).into_string(),
|
bs58::encode(root_kp.clone().key_pair.secret).into_string(),
|
||||||
bs58::encode(&root_kp.key_pair.public().encode().to_vec()).into_string()
|
bs58::encode(&root_kp.key_pair.public.to_bytes().to_vec()).into_string()
|
||||||
);
|
);
|
||||||
println!(
|
println!(
|
||||||
"second_kp:\n\tprivate: {}\n\tpublic: {}",
|
"second_kp:\n\tprivate: {}\n\tpublic: {}",
|
||||||
bs58::encode(second_kp.key_pair.secret()).into_string(),
|
bs58::encode(second_kp.clone().key_pair.secret).into_string(),
|
||||||
bs58::encode(&second_kp.key_pair.public().encode().to_vec()).into_string()
|
bs58::encode(&second_kp.key_pair.public.to_bytes().to_vec()).into_string()
|
||||||
);
|
);
|
||||||
println!(
|
println!(
|
||||||
"third_kp:\n\tprivate: {}\n\tpublic: {}",
|
"third_kp:\n\tprivate: {}\n\tpublic: {}",
|
||||||
bs58::encode(third_kp.key_pair.secret()).into_string(),
|
bs58::encode(third_kp.clone().key_pair.secret).into_string(),
|
||||||
bs58::encode(&third_kp.key_pair.public().encode().to_vec()).into_string()
|
bs58::encode(&third_kp.key_pair.public.to_bytes().to_vec()).into_string()
|
||||||
);
|
);
|
||||||
println!("cert is\n{}", new_cert.to_string());
|
println!("cert is\n{}", new_cert.to_string());
|
||||||
|
|
||||||
@ -390,7 +391,7 @@ mod tests {
|
|||||||
|
|
||||||
let new_cert = Certificate::issue(
|
let new_cert = Certificate::issue(
|
||||||
&second_kp,
|
&second_kp,
|
||||||
third_kp.key_pair.public(),
|
third_kp.key_pair.public,
|
||||||
&cert,
|
&cert,
|
||||||
cur_time.checked_sub(one_second()).unwrap(),
|
cur_time.checked_sub(one_second()).unwrap(),
|
||||||
cur_time.checked_sub(one_minute()).unwrap(),
|
cur_time.checked_sub(one_minute()).unwrap(),
|
||||||
@ -412,7 +413,7 @@ mod tests {
|
|||||||
|
|
||||||
let new_cert = Certificate::issue(
|
let new_cert = Certificate::issue(
|
||||||
&second_kp,
|
&second_kp,
|
||||||
third_kp.key_pair.public(),
|
third_kp.key_pair.public,
|
||||||
&cert,
|
&cert,
|
||||||
cur_time.checked_add(one_second()).unwrap(),
|
cur_time.checked_add(one_second()).unwrap(),
|
||||||
cur_time,
|
cur_time,
|
||||||
@ -421,7 +422,7 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let new_cert = Certificate::issue(
|
let new_cert = Certificate::issue(
|
||||||
&third_kp,
|
&third_kp,
|
||||||
fourth_kp.key_pair.public(),
|
fourth_kp.key_pair.public,
|
||||||
&new_cert,
|
&new_cert,
|
||||||
cur_time.checked_add(one_second()).unwrap(),
|
cur_time.checked_add(one_second()).unwrap(),
|
||||||
cur_time,
|
cur_time,
|
||||||
@ -450,7 +451,7 @@ mod tests {
|
|||||||
|
|
||||||
let new_cert = Certificate::issue(
|
let new_cert = Certificate::issue(
|
||||||
&second_kp,
|
&second_kp,
|
||||||
third_kp.key_pair.public(),
|
third_kp.key_pair.public,
|
||||||
&cert,
|
&cert,
|
||||||
cur_time.checked_add(one_second()).unwrap(),
|
cur_time.checked_add(one_second()).unwrap(),
|
||||||
cur_time,
|
cur_time,
|
||||||
@ -459,7 +460,7 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let new_cert = Certificate::issue(
|
let new_cert = Certificate::issue(
|
||||||
&second_kp,
|
&second_kp,
|
||||||
fourth_kp.key_pair.public(),
|
fourth_kp.key_pair.public,
|
||||||
&new_cert,
|
&new_cert,
|
||||||
cur_time.checked_add(one_second()).unwrap(),
|
cur_time.checked_add(one_second()).unwrap(),
|
||||||
cur_time,
|
cur_time,
|
||||||
@ -484,7 +485,7 @@ mod tests {
|
|||||||
let bad_kp = KeyPair::generate();
|
let bad_kp = KeyPair::generate();
|
||||||
let new_cert_bad = Certificate::issue(
|
let new_cert_bad = Certificate::issue(
|
||||||
&bad_kp,
|
&bad_kp,
|
||||||
bad_kp.key_pair.public(),
|
bad_kp.key_pair.public,
|
||||||
&cert,
|
&cert,
|
||||||
cur_time.checked_add(one_second()).unwrap(),
|
cur_time.checked_add(one_second()).unwrap(),
|
||||||
cur_time,
|
cur_time,
|
||||||
|
@ -28,18 +28,15 @@
|
|||||||
|
|
||||||
mod certificate;
|
mod certificate;
|
||||||
pub mod certificate_serde;
|
pub mod certificate_serde;
|
||||||
mod key_pair;
|
|
||||||
mod misc;
|
mod misc;
|
||||||
mod public_key_hashable;
|
mod public_key_hashable;
|
||||||
mod revoke;
|
mod revoke;
|
||||||
mod trust;
|
mod trust;
|
||||||
mod trust_graph;
|
mod trust_graph;
|
||||||
|
mod trust_graph_storage;
|
||||||
mod trust_node;
|
mod trust_node;
|
||||||
|
|
||||||
pub(crate) use libp2p_core::identity::ed25519;
|
|
||||||
|
|
||||||
pub use crate::certificate::Certificate;
|
pub use crate::certificate::Certificate;
|
||||||
pub use crate::key_pair::KeyPair;
|
|
||||||
pub use crate::misc::current_time;
|
pub use crate::misc::current_time;
|
||||||
pub use crate::public_key_hashable::PublicKeyHashable;
|
pub use crate::public_key_hashable::PublicKeyHashable;
|
||||||
pub use crate::trust::Trust;
|
pub use crate::trust::Trust;
|
||||||
|
@ -14,24 +14,24 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::ed25519::PublicKey;
|
use ed25519_dalek::PublicKey;
|
||||||
|
|
||||||
|
use core::fmt;
|
||||||
use ref_cast::RefCast;
|
use ref_cast::RefCast;
|
||||||
use serde::Deserialize;
|
|
||||||
use std::{
|
use std::{
|
||||||
fmt::{Display, Formatter},
|
fmt::{Display, Formatter},
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Wrapper to use PublicKey in HashMap
|
/// Wrapper to use PublicKey in HashMap
|
||||||
#[derive(PartialEq, Eq, Debug, Clone, RefCast, Deserialize)]
|
#[derive(PartialEq, Eq, Debug, Clone, RefCast)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct PublicKeyHashable(PublicKey);
|
pub struct PublicKeyHashable(PublicKey);
|
||||||
|
|
||||||
#[allow(clippy::derive_hash_xor_eq)]
|
#[allow(clippy::derive_hash_xor_eq)]
|
||||||
impl Hash for PublicKeyHashable {
|
impl Hash for PublicKeyHashable {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
state.write(&self.0.encode());
|
state.write(&self.0.to_bytes());
|
||||||
state.finish();
|
state.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ impl Hash for PublicKeyHashable {
|
|||||||
// TODO check for overflow
|
// TODO check for overflow
|
||||||
let mut bytes: Vec<u8> = Vec::with_capacity(data.len() * 32);
|
let mut bytes: Vec<u8> = Vec::with_capacity(data.len() * 32);
|
||||||
for d in data {
|
for d in data {
|
||||||
bytes.extend_from_slice(&d.0.encode())
|
bytes.extend_from_slice(&d.0.to_bytes())
|
||||||
}
|
}
|
||||||
state.write(bytes.as_slice());
|
state.write(bytes.as_slice());
|
||||||
state.finish();
|
state.finish();
|
||||||
@ -75,6 +75,49 @@ impl AsRef<PublicKeyHashable> for PublicKey {
|
|||||||
|
|
||||||
impl Display for PublicKeyHashable {
|
impl Display for PublicKeyHashable {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{}", bs58::encode(self.0.encode()).into_string())
|
write!(f, "{}", bs58::encode(self.0.to_bytes()).into_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> serde::Deserialize<'de> for PublicKeyHashable {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
use serde::de::{Error, Visitor};
|
||||||
|
|
||||||
|
struct PKVisitor;
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for PKVisitor {
|
||||||
|
type Value = PublicKeyHashable;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
formatter.write_str("byte array or base58 string")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: Error,
|
||||||
|
{
|
||||||
|
bs58::decode(s)
|
||||||
|
.into_vec()
|
||||||
|
.map_err(|err| Error::custom(format!("Invalid string '{}': {}", s, err)))
|
||||||
|
.and_then(|v| self.visit_bytes(v.as_slice()))
|
||||||
|
.map_err(|err: E| {
|
||||||
|
Error::custom(format!("Parsed string '{}' as base58, but {}", s, err))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_bytes<E>(self, b: &[u8]) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: Error,
|
||||||
|
{
|
||||||
|
let pk = PublicKey::from_bytes(b)
|
||||||
|
.map_err(|err| Error::custom(format!("Invalid bytes {:?}: {}", b, err)))?;
|
||||||
|
Ok(PublicKeyHashable::from(pk))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializer.deserialize_str(PKVisitor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::ed25519::PublicKey;
|
|
||||||
use crate::key_pair::KeyPair;
|
|
||||||
use crate::key_pair::Signature;
|
|
||||||
use crate::trust::{EXPIRATION_LEN, PK_LEN};
|
use crate::trust::{EXPIRATION_LEN, PK_LEN};
|
||||||
|
use ed25519_dalek::PublicKey;
|
||||||
|
use fluence_identity::key_pair::KeyPair;
|
||||||
|
use fluence_identity::key_pair::Signature;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
/// "A document" that cancels trust created before.
|
/// "A document" that cancels trust created before.
|
||||||
@ -61,7 +61,7 @@ impl Revoke {
|
|||||||
|
|
||||||
fn signature_bytes(pk: &PublicKey, revoked_at: Duration) -> Vec<u8> {
|
fn signature_bytes(pk: &PublicKey, revoked_at: Duration) -> Vec<u8> {
|
||||||
let mut msg = Vec::with_capacity(PK_LEN + EXPIRATION_LEN);
|
let mut msg = Vec::with_capacity(PK_LEN + EXPIRATION_LEN);
|
||||||
msg.extend_from_slice(&pk.encode());
|
msg.extend_from_slice(&pk.to_bytes());
|
||||||
msg.extend_from_slice(&(revoked_at.as_secs() as u64).to_le_bytes());
|
msg.extend_from_slice(&(revoked_at.as_secs() as u64).to_le_bytes());
|
||||||
|
|
||||||
msg
|
msg
|
||||||
@ -71,14 +71,10 @@ impl Revoke {
|
|||||||
pub fn verify(revoke: &Revoke) -> Result<(), String> {
|
pub fn verify(revoke: &Revoke) -> Result<(), String> {
|
||||||
let msg = Revoke::signature_bytes(&revoke.pk, revoke.revoked_at);
|
let msg = Revoke::signature_bytes(&revoke.pk, revoke.revoked_at);
|
||||||
|
|
||||||
if !revoke
|
revoke
|
||||||
.revoked_by
|
.revoked_by
|
||||||
.verify(msg.as_slice(), revoke.signature.as_slice())
|
.verify_strict(msg.as_slice(), &revoke.signature)
|
||||||
{
|
.map_err(|err| format!("Revoke has incorrect signature: {:?}", err))
|
||||||
return Err("Revoke has incorrect signature.".to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
35
src/trust.rs
35
src/trust.rs
@ -14,9 +14,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::ed25519::PublicKey;
|
|
||||||
use crate::key_pair::{KeyPair, Signature};
|
|
||||||
use derivative::Derivative;
|
use derivative::Derivative;
|
||||||
|
use ed25519_dalek::PublicKey;
|
||||||
|
use fluence_identity::key_pair::{KeyPair, Signature};
|
||||||
|
use signature::Signature as SigSignature;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
@ -46,11 +47,14 @@ pub struct Trust {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn show_pubkey(key: &PublicKey, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
fn show_pubkey(key: &PublicKey, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||||
write!(f, "{}", bs58::encode(key.encode()).into_string())
|
write!(f, "{}", bs58::encode(&key.to_bytes()).into_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_sig(sig: &[u8], f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
fn show_sig(
|
||||||
write!(f, "{}", bs58::encode(sig).into_string())
|
sig: &ed25519_dalek::Signature,
|
||||||
|
f: &mut std::fmt::Formatter<'_>,
|
||||||
|
) -> Result<(), std::fmt::Error> {
|
||||||
|
write!(f, "{}", bs58::encode(&sig.to_bytes()).into_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Trust {
|
impl Trust {
|
||||||
@ -96,13 +100,13 @@ impl Trust {
|
|||||||
let msg: &[u8] =
|
let msg: &[u8] =
|
||||||
&Self::metadata_bytes(&trust.issued_for, trust.expires_at, trust.issued_at);
|
&Self::metadata_bytes(&trust.issued_for, trust.expires_at, trust.issued_at);
|
||||||
|
|
||||||
KeyPair::verify(issued_by, msg, trust.signature.as_slice())?;
|
KeyPair::verify(issued_by, msg, trust.signature)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn metadata_bytes(pk: &PublicKey, expires_at: Duration, issued_at: Duration) -> [u8; 48] {
|
fn metadata_bytes(pk: &PublicKey, expires_at: Duration, issued_at: Duration) -> [u8; 48] {
|
||||||
let pk_encoded = pk.encode();
|
let pk_encoded = pk.to_bytes();
|
||||||
let expires_at_encoded: [u8; EXPIRATION_LEN] = (expires_at.as_secs() as u64).to_le_bytes();
|
let expires_at_encoded: [u8; EXPIRATION_LEN] = (expires_at.as_secs() as u64).to_le_bytes();
|
||||||
let issued_at_encoded: [u8; ISSUED_LEN] = (issued_at.as_secs() as u64).to_le_bytes();
|
let issued_at_encoded: [u8; ISSUED_LEN] = (issued_at.as_secs() as u64).to_le_bytes();
|
||||||
let mut metadata = [0; METADATA_LEN];
|
let mut metadata = [0; METADATA_LEN];
|
||||||
@ -120,8 +124,8 @@ impl Trust {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn encode(&self) -> Vec<u8> {
|
pub fn encode(&self) -> Vec<u8> {
|
||||||
let mut vec = Vec::with_capacity(TRUST_LEN);
|
let mut vec = Vec::with_capacity(TRUST_LEN);
|
||||||
vec.extend_from_slice(&self.issued_for.encode());
|
vec.extend_from_slice(&self.issued_for.to_bytes());
|
||||||
vec.extend_from_slice(&self.signature.as_slice());
|
vec.extend_from_slice(&self.signature.to_bytes());
|
||||||
vec.extend_from_slice(&(self.expires_at.as_secs() as u64).to_le_bytes());
|
vec.extend_from_slice(&(self.expires_at.as_secs() as u64).to_le_bytes());
|
||||||
vec.extend_from_slice(&(self.issued_at.as_secs() as u64).to_le_bytes());
|
vec.extend_from_slice(&(self.issued_at.as_secs() as u64).to_le_bytes());
|
||||||
|
|
||||||
@ -137,8 +141,10 @@ impl Trust {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let pk = PublicKey::decode(&arr[0..PK_LEN]).map_err(|err| err.to_string())?;
|
let pk = PublicKey::from_bytes(&arr[0..PK_LEN]).map_err(|err| err.to_string())?;
|
||||||
|
|
||||||
let signature = &arr[PK_LEN..PK_LEN + SIG_LEN];
|
let signature = &arr[PK_LEN..PK_LEN + SIG_LEN];
|
||||||
|
let signature = Signature::from_bytes(signature).map_err(|err| err.to_string())?;
|
||||||
|
|
||||||
let expiration_bytes = &arr[PK_LEN + SIG_LEN..PK_LEN + SIG_LEN + EXPIRATION_LEN];
|
let expiration_bytes = &arr[PK_LEN + SIG_LEN..PK_LEN + SIG_LEN + EXPIRATION_LEN];
|
||||||
let expiration_date = u64::from_le_bytes(expiration_bytes.try_into().unwrap());
|
let expiration_date = u64::from_le_bytes(expiration_bytes.try_into().unwrap());
|
||||||
@ -150,7 +156,7 @@ impl Trust {
|
|||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
issued_for: pk,
|
issued_for: pk,
|
||||||
signature: signature.to_vec(),
|
signature: signature,
|
||||||
expires_at: expiration_date,
|
expires_at: expiration_date,
|
||||||
issued_at: issued_date,
|
issued_at: issued_date,
|
||||||
})
|
})
|
||||||
@ -183,7 +189,7 @@ impl Trust {
|
|||||||
) -> Result<Self, String> {
|
) -> Result<Self, String> {
|
||||||
// PublicKey
|
// PublicKey
|
||||||
let issued_for_bytes = Self::bs58_str_to_vec(issued_for, "issued_for")?;
|
let issued_for_bytes = Self::bs58_str_to_vec(issued_for, "issued_for")?;
|
||||||
let issued_for = PublicKey::decode(issued_for_bytes.as_slice()).map_err(|e| {
|
let issued_for = PublicKey::from_bytes(issued_for_bytes.as_slice()).map_err(|e| {
|
||||||
format!(
|
format!(
|
||||||
"Cannot decode the public key: {} in the trust '{}'",
|
"Cannot decode the public key: {} in the trust '{}'",
|
||||||
issued_for, e
|
issued_for, e
|
||||||
@ -192,6 +198,7 @@ impl Trust {
|
|||||||
|
|
||||||
// 64 bytes signature
|
// 64 bytes signature
|
||||||
let signature = Self::bs58_str_to_vec(signature, "signature")?;
|
let signature = Self::bs58_str_to_vec(signature, "signature")?;
|
||||||
|
let signature = Signature::from_bytes(&signature).map_err(|err| err.to_string())?;
|
||||||
|
|
||||||
// Duration
|
// Duration
|
||||||
let expires_at = Self::str_to_duration(expires_at, "expires_at")?;
|
let expires_at = Self::str_to_duration(expires_at, "expires_at")?;
|
||||||
@ -205,8 +212,8 @@ impl Trust {
|
|||||||
|
|
||||||
impl ToString for Trust {
|
impl ToString for Trust {
|
||||||
fn to_string(&self) -> String {
|
fn to_string(&self) -> String {
|
||||||
let issued_for = bs58::encode(self.issued_for.encode()).into_string();
|
let issued_for = bs58::encode(self.issued_for.to_bytes()).into_string();
|
||||||
let signature = bs58::encode(self.signature.as_slice()).into_string();
|
let signature = bs58::encode(self.signature.to_bytes()).into_string();
|
||||||
let expires_at = (self.expires_at.as_secs() as u64).to_string();
|
let expires_at = (self.expires_at.as_secs() as u64).to_string();
|
||||||
let issued_at = (self.issued_at.as_secs() as u64).to_string();
|
let issued_at = (self.issued_at.as_secs() as u64).to_string();
|
||||||
|
|
||||||
|
@ -15,54 +15,41 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::certificate::Certificate;
|
use crate::certificate::Certificate;
|
||||||
use crate::ed25519::PublicKey;
|
|
||||||
use crate::public_key_hashable::PublicKeyHashable;
|
use crate::public_key_hashable::PublicKeyHashable;
|
||||||
use crate::revoke::Revoke;
|
use crate::revoke::Revoke;
|
||||||
use crate::trust::Trust;
|
use crate::trust::Trust;
|
||||||
|
use crate::trust_graph_storage::Storage;
|
||||||
use crate::trust_node::{Auth, TrustNode};
|
use crate::trust_node::{Auth, TrustNode};
|
||||||
|
use ed25519_dalek::PublicKey;
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::{HashSet, VecDeque};
|
||||||
use std::collections::hash_map::Entry::Occupied;
|
|
||||||
use std::collections::{HashMap, HashSet, VecDeque};
|
|
||||||
use std::fmt::Debug;
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
/// for simplicity, we store `n` where Weight = 1/n^2
|
/// for simplicity, we store `n` where Weight = 1/n^2
|
||||||
type Weight = u32;
|
pub type Weight = u32;
|
||||||
|
|
||||||
/// Graph to efficiently calculate weights of certificates and get chains of certificates.
|
/// Graph to efficiently calculate weights of certificates and get chains of certificates.
|
||||||
/// TODO serialization/deserialization
|
/// TODO serialization/deserialization
|
||||||
/// TODO export a certificate from graph
|
/// TODO export a certificate from graph
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[derive(Debug, Default)]
|
|
||||||
pub struct TrustGraph {
|
pub struct TrustGraph {
|
||||||
// TODO abstract this into a trait with key access methods
|
storage: Box<dyn Storage>,
|
||||||
// TODO: add docs on fields
|
|
||||||
nodes: HashMap<PublicKeyHashable, TrustNode>,
|
|
||||||
root_weights: HashMap<PublicKeyHashable, Weight>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
impl TrustGraph {
|
impl TrustGraph {
|
||||||
pub fn new(root_weights: Vec<(PublicKey, Weight)>) -> Self {
|
pub fn new(storage: Box<dyn Storage>) -> Self {
|
||||||
Self {
|
Self { storage: storage }
|
||||||
nodes: HashMap::new(),
|
|
||||||
root_weights: root_weights
|
|
||||||
.into_iter()
|
|
||||||
.map(|(k, w)| (k.into(), w))
|
|
||||||
.collect(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert new root weights
|
/// Insert new root weight
|
||||||
pub fn add_root_weights<P: Into<PublicKeyHashable>>(&mut self, weights: Vec<(P, Weight)>) {
|
pub fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight) {
|
||||||
self.root_weights
|
self.storage.add_root_weight(pk, weight)
|
||||||
.extend(weights.into_iter().map(|(k, w)| (k.into(), w)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get trust by public key
|
/// Get trust by public key
|
||||||
pub fn get(&self, pk: PublicKey) -> Option<&TrustNode> {
|
pub fn get(&self, pk: PublicKey) -> Option<&TrustNode> {
|
||||||
self.nodes.get(&pk.into())
|
self.storage.get(&pk.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove cur_time from api, leave it for tests only
|
// TODO: remove cur_time from api, leave it for tests only
|
||||||
@ -71,7 +58,13 @@ impl TrustGraph {
|
|||||||
where
|
where
|
||||||
C: Borrow<Certificate>,
|
C: Borrow<Certificate>,
|
||||||
{
|
{
|
||||||
let roots: Vec<PublicKey> = self.root_weights.keys().cloned().map(Into::into).collect();
|
let roots: Vec<PublicKey> = self
|
||||||
|
.storage
|
||||||
|
.root_keys()
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.map(Into::into)
|
||||||
|
.collect();
|
||||||
// Check that certificate is valid and converges to one of the known roots
|
// Check that certificate is valid and converges to one of the known roots
|
||||||
Certificate::verify(cert.borrow(), roots.as_slice(), cur_time)?;
|
Certificate::verify(cert.borrow(), roots.as_slice(), cur_time)?;
|
||||||
|
|
||||||
@ -80,14 +73,14 @@ impl TrustGraph {
|
|||||||
let root_pk: PublicKeyHashable = root_trust.issued_for.clone().into();
|
let root_pk: PublicKeyHashable = root_trust.issued_for.clone().into();
|
||||||
|
|
||||||
// Insert new TrustNode for this root_pk if there wasn't one
|
// Insert new TrustNode for this root_pk if there wasn't one
|
||||||
if self.nodes.get_mut(&root_pk).is_none() {
|
if self.storage.get(&root_pk).is_none() {
|
||||||
let mut trust_node = TrustNode::new(root_trust.issued_for.clone(), cur_time);
|
let mut trust_node = TrustNode::new(root_trust.issued_for.clone(), cur_time);
|
||||||
let root_auth = Auth {
|
let root_auth = Auth {
|
||||||
trust: root_trust.clone(),
|
trust: root_trust.clone(),
|
||||||
issued_by: root_trust.issued_for.clone(),
|
issued_by: root_trust.issued_for.clone(),
|
||||||
};
|
};
|
||||||
trust_node.update_auth(root_auth);
|
trust_node.update_auth(root_auth);
|
||||||
self.nodes.insert(root_pk, trust_node);
|
self.storage.insert(root_pk, trust_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert remaining trusts to the graph
|
// Insert remaining trusts to the graph
|
||||||
@ -100,16 +93,8 @@ impl TrustGraph {
|
|||||||
issued_by: previous_trust.issued_for.clone(),
|
issued_by: previous_trust.issued_for.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
match self.nodes.get_mut(&pk) {
|
self.storage
|
||||||
Some(trust_node) => {
|
.update_auth(&pk, auth, &root_trust.issued_for, cur_time);
|
||||||
trust_node.update_auth(auth);
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
let mut trust_node = TrustNode::new(root_trust.issued_for.clone(), cur_time);
|
|
||||||
trust_node.update_auth(auth);
|
|
||||||
self.nodes.insert(pk, trust_node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
previous_trust = trust;
|
previous_trust = trust;
|
||||||
}
|
}
|
||||||
@ -122,13 +107,14 @@ impl TrustGraph {
|
|||||||
where
|
where
|
||||||
P: Borrow<PublicKey>,
|
P: Borrow<PublicKey>,
|
||||||
{
|
{
|
||||||
if let Some(weight) = self.root_weights.get(pk.borrow().as_ref()) {
|
if let Some(weight) = self.storage.get_root_weight(pk.borrow().as_ref()) {
|
||||||
return Some(*weight);
|
return Some(*weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
let roots: Vec<PublicKey> = self
|
let roots: Vec<PublicKey> = self
|
||||||
.root_weights
|
.storage
|
||||||
.keys()
|
.root_keys()
|
||||||
|
.iter()
|
||||||
.map(|pk| pk.clone().into())
|
.map(|pk| pk.clone().into())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
@ -157,8 +143,8 @@ impl TrustGraph {
|
|||||||
let cert = cert.borrow();
|
let cert = cert.borrow();
|
||||||
|
|
||||||
let root_weight = *self
|
let root_weight = *self
|
||||||
.root_weights
|
.storage
|
||||||
.get(cert.chain.first()?.issued_for.as_ref())
|
.get_root_weight(cert.chain.first()?.issued_for.as_ref())
|
||||||
// This panic shouldn't happen // TODO: why?
|
// This panic shouldn't happen // TODO: why?
|
||||||
.expect("first trust in chain must be in root_weights");
|
.expect("first trust in chain must be in root_weights");
|
||||||
|
|
||||||
@ -200,7 +186,7 @@ impl TrustGraph {
|
|||||||
.expect("`cur_chain` always has at least one element");
|
.expect("`cur_chain` always has at least one element");
|
||||||
|
|
||||||
let auths: Vec<Auth> = self
|
let auths: Vec<Auth> = self
|
||||||
.nodes
|
.storage
|
||||||
.get(&last.issued_by.clone().into())
|
.get(&last.issued_by.clone().into())
|
||||||
.expect(
|
.expect(
|
||||||
"there cannot be paths without any nodes after adding verified certificates",
|
"there cannot be paths without any nodes after adding verified certificates",
|
||||||
@ -226,7 +212,8 @@ impl TrustGraph {
|
|||||||
// - that trust must converge to one of the root weights
|
// - that trust must converge to one of the root weights
|
||||||
// - there should be more than 1 trust in the chain
|
// - there should be more than 1 trust in the chain
|
||||||
let self_signed = last.issued_by == last.trust.issued_for;
|
let self_signed = last.issued_by == last.trust.issued_for;
|
||||||
let converges_to_root = roots.contains(last.issued_by.as_ref());
|
let issued_by: &PublicKeyHashable = last.issued_by.as_ref();
|
||||||
|
let converges_to_root = roots.contains(issued_by);
|
||||||
|
|
||||||
if self_signed && converges_to_root && cur_chain.len() > 1 {
|
if self_signed && converges_to_root && cur_chain.len() > 1 {
|
||||||
terminated_chains.push(cur_chain);
|
terminated_chains.push(cur_chain);
|
||||||
@ -244,14 +231,15 @@ impl TrustGraph {
|
|||||||
P: Borrow<PublicKey>,
|
P: Borrow<PublicKey>,
|
||||||
{
|
{
|
||||||
// get all auths (edges) for issued public key
|
// get all auths (edges) for issued public key
|
||||||
let issued_for_node = self.nodes.get(issued_for.borrow().as_ref());
|
let issued_for_node = self.storage.get(issued_for.borrow().as_ref());
|
||||||
|
|
||||||
let roots = roots.iter().map(|pk| pk.as_ref());
|
let roots = roots.iter().map(|pk| pk.as_ref());
|
||||||
let roots = self.root_weights.keys().chain(roots).collect();
|
let keys = self.storage.root_keys();
|
||||||
|
let roots = keys.iter().chain(roots).collect();
|
||||||
|
|
||||||
match issued_for_node {
|
match issued_for_node {
|
||||||
Some(node) => self
|
Some(node) => self
|
||||||
.bf_search_paths(node, roots)
|
.bf_search_paths(&node, roots)
|
||||||
.iter()
|
.iter()
|
||||||
.map(|auths| {
|
.map(|auths| {
|
||||||
// TODO: can avoid cloning here by returning &Certificate
|
// TODO: can avoid cloning here by returning &Certificate
|
||||||
@ -279,13 +267,7 @@ impl TrustGraph {
|
|||||||
|
|
||||||
let pk: PublicKeyHashable = revoke.pk.clone().into();
|
let pk: PublicKeyHashable = revoke.pk.clone().into();
|
||||||
|
|
||||||
match self.nodes.entry(pk) {
|
self.storage.revoke(&pk, revoke)
|
||||||
Occupied(mut entry) => {
|
|
||||||
entry.get_mut().update_revoke(revoke);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
Entry::Vacant(_) => Err("There is no trust with such PublicKey".to_string()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check information about new certificates and about revoked certificates.
|
/// Check information about new certificates and about revoked certificates.
|
||||||
@ -297,9 +279,11 @@ impl TrustGraph {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::key_pair::KeyPair;
|
|
||||||
use crate::misc::current_time;
|
use crate::misc::current_time;
|
||||||
|
use crate::trust_graph_storage::InMemoryStorage;
|
||||||
use failure::_core::time::Duration;
|
use failure::_core::time::Duration;
|
||||||
|
use fluence_identity::key_pair::KeyPair;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub fn one_minute() -> Duration {
|
pub fn one_minute() -> Duration {
|
||||||
Duration::new(60, 0)
|
Duration::new(60, 0)
|
||||||
@ -375,7 +359,8 @@ mod tests {
|
|||||||
|
|
||||||
let cur_time = current_time();
|
let cur_time = current_time();
|
||||||
|
|
||||||
let mut graph = TrustGraph::default();
|
let st = Box::new(InMemoryStorage::new());
|
||||||
|
let mut graph = TrustGraph::new(st);
|
||||||
let addition = graph.add(cert, cur_time);
|
let addition = graph.add(cert, cur_time);
|
||||||
assert_eq!(addition.is_ok(), false);
|
assert_eq!(addition.is_ok(), false);
|
||||||
}
|
}
|
||||||
@ -384,8 +369,9 @@ mod tests {
|
|||||||
fn test_add_cert() {
|
fn test_add_cert() {
|
||||||
let (root, _, cert) = generate_root_cert();
|
let (root, _, cert) = generate_root_cert();
|
||||||
|
|
||||||
let mut graph = TrustGraph::default();
|
let st = Box::new(InMemoryStorage::new());
|
||||||
graph.root_weights.insert(root.key_pair.public().into(), 0);
|
let mut graph = TrustGraph::new(st);
|
||||||
|
graph.add_root_weight(root.key_pair.public.into(), 0);
|
||||||
|
|
||||||
let addition = graph.add(cert, current_time());
|
let addition = graph.add(cert, current_time());
|
||||||
assert_eq!(addition.is_ok(), true);
|
assert_eq!(addition.is_ok(), true);
|
||||||
@ -414,11 +400,12 @@ mod tests {
|
|||||||
let (key_pairs2, cert2) =
|
let (key_pairs2, cert2) =
|
||||||
generate_cert_with(10, chain_keys, far_far_future * 2, far_far_future);
|
generate_cert_with(10, chain_keys, far_far_future * 2, far_far_future);
|
||||||
|
|
||||||
let mut graph = TrustGraph::default();
|
let st = Box::new(InMemoryStorage::new());
|
||||||
|
let mut graph = TrustGraph::new(st);
|
||||||
let root1_pk = key_pairs1[0].public_key();
|
let root1_pk = key_pairs1[0].public_key();
|
||||||
let root2_pk = key_pairs2[0].public_key();
|
let root2_pk = key_pairs2[0].public_key();
|
||||||
graph.root_weights.insert(root1_pk.into(), 1);
|
graph.add_root_weight(root1_pk.into(), 1);
|
||||||
graph.root_weights.insert(root2_pk.into(), 0);
|
graph.add_root_weight(root2_pk.into(), 0);
|
||||||
graph.add(cert1, cur_time).unwrap();
|
graph.add(cert1, cur_time).unwrap();
|
||||||
|
|
||||||
let node2 = graph.get(key_pair2.public_key()).unwrap();
|
let node2 = graph.get(key_pair2.public_key()).unwrap();
|
||||||
@ -445,10 +432,11 @@ mod tests {
|
|||||||
let (key_pairs, cert1) = generate_cert_with_len(10, HashMap::new());
|
let (key_pairs, cert1) = generate_cert_with_len(10, HashMap::new());
|
||||||
let last_trust = cert1.chain[9].clone();
|
let last_trust = cert1.chain[9].clone();
|
||||||
|
|
||||||
let mut graph = TrustGraph::default();
|
let st = Box::new(InMemoryStorage::new());
|
||||||
|
let mut graph = TrustGraph::new(st);
|
||||||
|
|
||||||
let root_pk = key_pairs[0].public_key();
|
let root_pk = key_pairs[0].public_key();
|
||||||
graph.root_weights.insert(root_pk.into(), 1);
|
graph.add_root_weight(root_pk.into(), 1);
|
||||||
|
|
||||||
graph.add(cert1, current_time()).unwrap();
|
graph.add(cert1, current_time()).unwrap();
|
||||||
|
|
||||||
@ -488,11 +476,12 @@ mod tests {
|
|||||||
|
|
||||||
let (key_pairs2, cert2) = generate_cert_with_len(10, chain_keys);
|
let (key_pairs2, cert2) = generate_cert_with_len(10, chain_keys);
|
||||||
|
|
||||||
let mut graph = TrustGraph::default();
|
let st = Box::new(InMemoryStorage::new());
|
||||||
|
let mut graph = TrustGraph::new(st);
|
||||||
let root1_pk = key_pairs1[0].public_key();
|
let root1_pk = key_pairs1[0].public_key();
|
||||||
let root2_pk = key_pairs2[0].public_key();
|
let root2_pk = key_pairs2[0].public_key();
|
||||||
graph.root_weights.insert(root1_pk.into(), 1);
|
graph.add_root_weight(root1_pk.into(), 1);
|
||||||
graph.root_weights.insert(root2_pk.into(), 0);
|
graph.add_root_weight(root2_pk.into(), 0);
|
||||||
|
|
||||||
let last_pk1 = cert1.chain[9].issued_for.clone();
|
let last_pk1 = cert1.chain[9].issued_for.clone();
|
||||||
let last_pk2 = cert2.chain[9].issued_for.clone();
|
let last_pk2 = cert2.chain[9].issued_for.clone();
|
||||||
@ -523,9 +512,10 @@ mod tests {
|
|||||||
fn test_get_one_cert() {
|
fn test_get_one_cert() {
|
||||||
let (key_pairs, cert) = generate_cert_with_len(5, HashMap::new());
|
let (key_pairs, cert) = generate_cert_with_len(5, HashMap::new());
|
||||||
|
|
||||||
let mut graph = TrustGraph::default();
|
let st = Box::new(InMemoryStorage::new());
|
||||||
|
let mut graph = TrustGraph::new(st);
|
||||||
let root1_pk = key_pairs[0].public_key();
|
let root1_pk = key_pairs[0].public_key();
|
||||||
graph.root_weights.insert(root1_pk.clone().into(), 1);
|
graph.add_root_weight(root1_pk.clone().into(), 1);
|
||||||
|
|
||||||
graph.add(cert.clone(), current_time()).unwrap();
|
graph.add(cert.clone(), current_time()).unwrap();
|
||||||
|
|
||||||
@ -539,17 +529,12 @@ mod tests {
|
|||||||
fn test_chain_from_root_to_another_root() {
|
fn test_chain_from_root_to_another_root() {
|
||||||
let (_, cert) = generate_cert_with_len(6, HashMap::new());
|
let (_, cert) = generate_cert_with_len(6, HashMap::new());
|
||||||
|
|
||||||
let mut graph = TrustGraph::default();
|
let st = Box::new(InMemoryStorage::new());
|
||||||
|
let mut graph = TrustGraph::new(st);
|
||||||
// add first and last trusts as roots
|
// add first and last trusts as roots
|
||||||
graph
|
graph.add_root_weight(cert.chain[0].clone().issued_for.into(), 1);
|
||||||
.root_weights
|
graph.add_root_weight(cert.chain[3].clone().issued_for.into(), 1);
|
||||||
.insert(cert.chain[0].clone().issued_for.into(), 1);
|
graph.add_root_weight(cert.chain[5].clone().issued_for.into(), 1);
|
||||||
graph
|
|
||||||
.root_weights
|
|
||||||
.insert(cert.chain[3].clone().issued_for.into(), 1);
|
|
||||||
graph
|
|
||||||
.root_weights
|
|
||||||
.insert(cert.chain[5].clone().issued_for.into(), 1);
|
|
||||||
|
|
||||||
graph.add(cert.clone(), current_time()).unwrap();
|
graph.add(cert.clone(), current_time()).unwrap();
|
||||||
|
|
||||||
@ -586,13 +571,14 @@ mod tests {
|
|||||||
|
|
||||||
let (key_pairs3, cert3) = generate_cert_with_len(5, chain_keys);
|
let (key_pairs3, cert3) = generate_cert_with_len(5, chain_keys);
|
||||||
|
|
||||||
let mut graph = TrustGraph::default();
|
let st = Box::new(InMemoryStorage::new());
|
||||||
|
let mut graph = TrustGraph::new(st);
|
||||||
let root1_pk = key_pairs1[0].public_key();
|
let root1_pk = key_pairs1[0].public_key();
|
||||||
let root2_pk = key_pairs2[0].public_key();
|
let root2_pk = key_pairs2[0].public_key();
|
||||||
let root3_pk = key_pairs3[0].public_key();
|
let root3_pk = key_pairs3[0].public_key();
|
||||||
graph.root_weights.insert(root1_pk.clone().into(), 1);
|
graph.add_root_weight(root1_pk.clone().into(), 1);
|
||||||
graph.root_weights.insert(root2_pk.clone().into(), 0);
|
graph.add_root_weight(root2_pk.clone().into(), 0);
|
||||||
graph.root_weights.insert(root3_pk.clone().into(), 0);
|
graph.add_root_weight(root3_pk.clone().into(), 0);
|
||||||
|
|
||||||
graph.add(cert1, current_time()).unwrap();
|
graph.add(cert1, current_time()).unwrap();
|
||||||
graph.add(cert2, current_time()).unwrap();
|
graph.add(cert2, current_time()).unwrap();
|
||||||
|
103
src/trust_graph_storage.rs
Normal file
103
src/trust_graph_storage.rs
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
use crate::public_key_hashable::PublicKeyHashable;
|
||||||
|
use crate::revoke::Revoke;
|
||||||
|
use crate::trust_graph::Weight;
|
||||||
|
use crate::trust_node::{Auth, TrustNode};
|
||||||
|
use ed25519_dalek::PublicKey;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
pub trait Storage {
|
||||||
|
fn get(&self, pk: &PublicKeyHashable) -> Option<&TrustNode>;
|
||||||
|
fn insert(&mut self, pk: PublicKeyHashable, node: TrustNode);
|
||||||
|
|
||||||
|
fn get_root_weight(&self, pk: &PublicKeyHashable) -> Option<&Weight>;
|
||||||
|
fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight);
|
||||||
|
fn root_keys(&self) -> Vec<PublicKeyHashable>;
|
||||||
|
fn revoke(&mut self, pk: &PublicKeyHashable, revoke: Revoke) -> Result<(), String>;
|
||||||
|
fn update_auth(
|
||||||
|
&mut self,
|
||||||
|
pk: &PublicKeyHashable,
|
||||||
|
auth: Auth,
|
||||||
|
issued_for: &PublicKey,
|
||||||
|
cur_time: Duration,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct InMemoryStorage {
|
||||||
|
nodes: HashMap<PublicKeyHashable, TrustNode>,
|
||||||
|
root_weights: HashMap<PublicKeyHashable, Weight>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InMemoryStorage {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn new_in_memory(root_weights: Vec<(PublicKey, Weight)>) -> Self {
|
||||||
|
let root_weights = root_weights
|
||||||
|
.into_iter()
|
||||||
|
.map(|(k, w)| (k.into(), w))
|
||||||
|
.collect();
|
||||||
|
Self {
|
||||||
|
nodes: HashMap::new(),
|
||||||
|
root_weights: root_weights,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
InMemoryStorage {
|
||||||
|
nodes: HashMap::new(),
|
||||||
|
root_weights: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Storage for InMemoryStorage {
|
||||||
|
fn get(&self, pk: &PublicKeyHashable) -> Option<&TrustNode> {
|
||||||
|
self.nodes.get(pk)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert(&mut self, pk: PublicKeyHashable, node: TrustNode) {
|
||||||
|
&self.nodes.insert(pk, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_root_weight(&self, pk: &PublicKeyHashable) -> Option<&Weight> {
|
||||||
|
self.root_weights.get(pk)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_root_weight(&mut self, pk: PublicKeyHashable, weight: Weight) {
|
||||||
|
&self.root_weights.insert(pk, weight);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn root_keys(&self) -> Vec<PublicKeyHashable> {
|
||||||
|
self.root_weights.keys().cloned().map(Into::into).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn revoke(&mut self, pk: &PublicKeyHashable, revoke: Revoke) -> Result<(), String> {
|
||||||
|
match self.nodes.get_mut(&pk) {
|
||||||
|
Some(trust_node) => {
|
||||||
|
trust_node.update_revoke(revoke);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
None => Err("There is no trust with such PublicKey".to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_auth(
|
||||||
|
&mut self,
|
||||||
|
pk: &PublicKeyHashable,
|
||||||
|
auth: Auth,
|
||||||
|
issued_for: &PublicKey,
|
||||||
|
cur_time: Duration,
|
||||||
|
) {
|
||||||
|
match self.nodes.get_mut(&pk) {
|
||||||
|
Some(trust_node) => {
|
||||||
|
trust_node.update_auth(auth);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let mut trust_node = TrustNode::new(issued_for.clone(), cur_time);
|
||||||
|
trust_node.update_auth(auth);
|
||||||
|
self.nodes.insert(pk.clone(), trust_node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -14,10 +14,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::ed25519::PublicKey;
|
|
||||||
use crate::public_key_hashable::PublicKeyHashable;
|
use crate::public_key_hashable::PublicKeyHashable;
|
||||||
use crate::revoke::Revoke;
|
use crate::revoke::Revoke;
|
||||||
use crate::trust::Trust;
|
use crate::trust::Trust;
|
||||||
|
use ed25519_dalek::PublicKey;
|
||||||
use failure::_core::time::Duration;
|
use failure::_core::time::Duration;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
@ -150,7 +150,7 @@ impl TrustNode {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::key_pair::KeyPair;
|
use fluence_identity::key_pair::KeyPair;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user