Identity rework (#6)

This commit is contained in:
Aleksey Proshutisnkiy 2021-04-15 14:00:27 +03:00 committed by GitHub
parent 443e9af784
commit 1d451379b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 1589 additions and 558 deletions

189
Cargo.lock generated
View File

@ -18,10 +18,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "anyhow"
version = "1.0.38"
name = "aho-corasick"
version = "0.7.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1"
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
dependencies = [
"memchr",
]
[[package]]
name = "anyhow"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b"
[[package]]
name = "arrayref"
@ -130,9 +139,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
[[package]]
name = "byteorder"
version = "1.4.2"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "bytes"
@ -189,9 +198,9 @@ dependencies = [
[[package]]
name = "darling"
version = "0.12.2"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06d4a9551359071d1890820e3571252b91229e0712e7c36b08940e603c5a8fc"
checksum = "e9d6ddad5866bb2170686ed03f6839d31a76e5407d80b1c334a2c24618543ffa"
dependencies = [
"darling_core",
"darling_macro",
@ -199,9 +208,9 @@ dependencies = [
[[package]]
name = "darling_core"
version = "0.12.2"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b443e5fb0ddd56e0c9bfa47dc060c5306ee500cb731f2b91432dd65589a77684"
checksum = "a9ced1fd13dc386d5a8315899de465708cf34ee2a6d9394654515214e67bb846"
dependencies = [
"fnv",
"ident_case",
@ -213,9 +222,9 @@ dependencies = [
[[package]]
name = "darling_macro"
version = "0.12.2"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0220073ce504f12a70efc4e7cdaea9e9b1b324872e7ad96a208056d7a638b81"
checksum = "0a7a1445d54b2f9792e3b31a3e715feabbace393f38dc4ffd49d94ee9bc487d5"
dependencies = [
"darling_core",
"quote",
@ -288,6 +297,16 @@ version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "env_logger"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
dependencies = [
"log",
"regex",
]
[[package]]
name = "failure"
version = "0.1.8"
@ -325,8 +344,7 @@ checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
[[package]]
name = "fluence-fork-libp2p-core"
version = "0.27.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "735c96afd9c133fead34204dff9df0b9f0a86e1bb8e6c32faf8b9f60427ce0cd"
source = "git+https://github.com/fluencelabs/rust-libp2p?branch=identity_rework#2d785558cfc9908cbfe54c0750e660c001cb2c3b"
dependencies = [
"asn1_der",
"bs58 0.4.0",
@ -342,7 +360,7 @@ dependencies = [
"log",
"multihash",
"parking_lot",
"pin-project 1.0.5",
"pin-project 1.0.6",
"prost",
"prost-build",
"rand 0.7.3",
@ -360,13 +378,12 @@ dependencies = [
[[package]]
name = "fluence-fork-multistream-select"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08cb5798accfd52dc9a104d7928f379e93d8432ac03201f5a16ed6dc2af1520d"
source = "git+https://github.com/fluencelabs/rust-libp2p?branch=identity_rework#2d785558cfc9908cbfe54c0750e660c001cb2c3b"
dependencies = [
"bytes",
"futures",
"log",
"pin-project 1.0.5",
"pin-project 1.0.6",
"smallvec",
"unsigned-varint 0.7.0",
]
@ -374,8 +391,7 @@ dependencies = [
[[package]]
name = "fluence-fork-parity-multiaddr"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e42d11a2d1e7b50e91c947f1a480004ed5f207bb6c8f8a69dbc083588f8419c1"
source = "git+https://github.com/fluencelabs/rust-libp2p?branch=identity_rework#2d785558cfc9908cbfe54c0750e660c001cb2c3b"
dependencies = [
"arrayref",
"bs58 0.4.0",
@ -393,16 +409,24 @@ dependencies = [
name = "fluence-identity"
version = "0.2.7"
dependencies = [
"asn1_der",
"bs58 0.3.1",
"ed25519",
"ed25519-dalek",
"fluence-fork-libp2p-core",
"lazy_static",
"libsecp256k1",
"quickcheck",
"rand 0.7.3",
"ring",
"serde",
"serde_bytes",
"serde_json",
"serde_with",
"sha2 0.9.3",
"signature",
"thiserror",
"zeroize",
]
[[package]]
@ -631,9 +655,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "1.6.1"
version = "1.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b"
checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"
dependencies = [
"autocfg",
"hashbrown",
@ -665,9 +689,9 @@ checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
[[package]]
name = "js-sys"
version = "0.3.48"
version = "0.3.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc9f84f9b115ce7843d60706df1422a916680bfdfcbdb0447c5614ff9d7e4d78"
checksum = "2d99f9e3e84b8f67f846ef5b4cbbc3b1c29f6c759fcbce6f01aa0e73d932a24c"
dependencies = [
"wasm-bindgen",
]
@ -680,9 +704,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.87"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "265d751d31d6780a3f956bb5b8022feba2d94eeee5a84ba64f4212eedca42213"
checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41"
[[package]]
name = "libsecp256k1"
@ -702,9 +726,9 @@ dependencies = [
[[package]]
name = "lock_api"
version = "0.4.2"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312"
checksum = "5a3c91c24eae6777794bb1997ad98bbb87daf92890acab859f7eaa4320333176"
dependencies = [
"scopeguard",
]
@ -769,9 +793,9 @@ dependencies = [
[[package]]
name = "multimap"
version = "0.8.2"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1255076139a83bb467426e7f8d0134968a8118844faa755985e077cf31850333"
checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
[[package]]
name = "num_cpus"
@ -850,27 +874,27 @@ dependencies = [
[[package]]
name = "pin-project"
version = "0.4.27"
version = "0.4.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ffbc8e94b38ea3d2d8ba92aea2983b503cd75d0888d75b86bb37970b5698e15"
checksum = "918192b5c59119d51e0cd221f4d49dde9112824ba717369e903c97d076083d0f"
dependencies = [
"pin-project-internal 0.4.27",
"pin-project-internal 0.4.28",
]
[[package]]
name = "pin-project"
version = "1.0.5"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96fa8ebb90271c4477f144354485b8068bd8f6b78b428b01ba892ca26caf0b63"
checksum = "bc174859768806e91ae575187ada95c91a29e96a98dc5d2cd9a1fed039501ba6"
dependencies = [
"pin-project-internal 1.0.5",
"pin-project-internal 1.0.6",
]
[[package]]
name = "pin-project-internal"
version = "0.4.27"
version = "0.4.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895"
checksum = "3be26700300be6d9d23264c73211d8190e755b6b5ca7a1b28230025511b52a5e"
dependencies = [
"proc-macro2",
"quote",
@ -879,9 +903,9 @@ dependencies = [
[[package]]
name = "pin-project-internal"
version = "1.0.5"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "758669ae3558c6f74bd2a18b41f7ac0b5a195aea6639d6a9b5e5d1ad5ba24c0b"
checksum = "a490329918e856ed1b083f244e3bfe2d8c4f336407e4ea9e1a9f479ff09049e5"
dependencies = [
"proc-macro2",
"quote",
@ -953,9 +977,9 @@ checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
[[package]]
name = "proc-macro2"
version = "1.0.24"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
dependencies = [
"unicode-xid",
]
@ -1011,6 +1035,18 @@ dependencies = [
"prost",
]
[[package]]
name = "quickcheck"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a44883e74aa97ad63db83c4bf8ca490f02b2fc02f92575e720c8551e843c945f"
dependencies = [
"env_logger",
"log",
"rand 0.7.3",
"rand_core 0.5.1",
]
[[package]]
name = "quote"
version = "1.0.9"
@ -1130,6 +1166,23 @@ dependencies = [
"syn",
]
[[package]]
name = "regex"
version = "1.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
[[package]]
name = "remove_dir_all"
version = "0.5.3"
@ -1167,7 +1220,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4da5fcb054c46f5a5dff833b129285a93d3f0179531735e6c866e8cc307d2020"
dependencies = [
"futures",
"pin-project 0.4.27",
"pin-project 0.4.28",
"static_assertions",
]
@ -1320,9 +1373,9 @@ checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2"
[[package]]
name = "syn"
version = "1.0.61"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed22b90a0e734a23a7610f4283ac9e5acfb96cbb30dfefa540d66f866f1c09c5"
checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb"
dependencies = [
"proc-macro2",
"quote",
@ -1377,9 +1430,9 @@ dependencies = [
[[package]]
name = "tinyvec"
version = "1.1.1"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "317cca572a0e89c3ce0ca1f1bdc9369547fe318a683418e42ac8f59d14701023"
checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342"
dependencies = [
"tinyvec_macros",
]
@ -1409,9 +1462,11 @@ dependencies = [
"failure",
"fluence-fork-libp2p-core",
"fluence-identity",
"libsecp256k1",
"log",
"rand 0.7.3",
"ref-cast",
"ring",
"serde",
"serde_json",
"serde_with",
@ -1421,15 +1476,15 @@ dependencies = [
[[package]]
name = "typenum"
version = "1.12.0"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06"
[[package]]
name = "unicode-bidi"
version = "0.3.4"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0"
dependencies = [
"matches",
]
@ -1487,9 +1542,9 @@ dependencies = [
[[package]]
name = "version_check"
version = "0.9.2"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
[[package]]
name = "void"
@ -1511,9 +1566,9 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]]
name = "wasm-bindgen"
version = "0.2.71"
version = "0.2.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ee1280240b7c461d6a0071313e08f34a60b0365f14260362e5a2b17d1d31aa7"
checksum = "83240549659d187488f91f33c0f8547cbfef0b2088bc470c116d1d260ef623d9"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@ -1521,9 +1576,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.71"
version = "0.2.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b7d8b6942b8bb3a9b0e73fc79b98095a27de6fa247615e59d096754a3bc2aa8"
checksum = "ae70622411ca953215ca6d06d3ebeb1e915f0f6613e3b495122878d7ebec7dae"
dependencies = [
"bumpalo",
"lazy_static",
@ -1536,9 +1591,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.71"
version = "0.2.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5ac38da8ef716661f0f36c0d8320b89028efe10c7c0afde65baffb496ce0d3b"
checksum = "3e734d91443f177bfdb41969de821e15c516931c3c3db3d318fa1b68975d0f6f"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@ -1546,9 +1601,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.71"
version = "0.2.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc053ec74d454df287b9374ee8abb36ffd5acb95ba87da3ba5b7d3fe20eb401e"
checksum = "d53739ff08c8a68b0fdbcd54c372b8ab800b1449ab3c9d706503bc7dd1621b2c"
dependencies = [
"proc-macro2",
"quote",
@ -1559,15 +1614,15 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.71"
version = "0.2.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d6f8ec44822dd71f5f221a5847fb34acd9060535c1211b70a05844c0f6383b1"
checksum = "d9a543ae66aa233d14bb765ed9af4a33e81b8b58d1584cf1b47ff8cd0b9e4489"
[[package]]
name = "web-sys"
version = "0.3.48"
version = "0.3.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec600b26223b2948cedfde2a0aa6756dcf1fef616f43d7b3097aaf53a6c4d92b"
checksum = "a905d57e488fec8861446d3393670fb50d27a262344013181c2cdf9fff5481be"
dependencies = [
"js-sys",
"wasm-bindgen",
@ -1575,12 +1630,12 @@ dependencies = [
[[package]]
name = "which"
version = "4.0.2"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87c14ef7e1b8b8ecfc75d5eca37949410046e66f15d185c01d70824f1f8111ef"
checksum = "b55551e42cbdf2ce2bedd2203d0cc08dba002c27510f86dab6d0ce304cba3dfe"
dependencies = [
"either",
"libc",
"thiserror",
]
[[package]]

View File

@ -8,10 +8,10 @@ license = "Apache-2.0"
repository = "https://github.com/fluencelabs/trust-graph"
[dependencies]
libp2p-core = { package = "fluence-fork-libp2p-core", version = "0.27.1" }
libp2p-core = { git = "https://github.com/fluencelabs/rust-libp2p", branch = "identity_rework", package = "fluence-fork-libp2p-core" }
serde = { version = "=1.0.118", features = ["derive"] }
fluence-identity = { version = "0.2", path = "identity" }
fluence-identity = {path = "./identity"}
serde_json = "1.0.58"
bs58 = "0.3.1"
failure = "0.1.6"
@ -23,3 +23,10 @@ rand = "0.7.0"
signature = "1.3.0"
serde_with = "1.6.0"
thiserror = "1.0.23"
libsecp256k1 = "0.3.5"
ring = "0.16.20"
[workspace]
members = [
"identity"
]

View File

@ -8,13 +8,23 @@ license = "Apache-2.0"
repository = "https://github.com/fluencelabs/trust-graph"
[dependencies]
libp2p-core = { package = "fluence-fork-libp2p-core", version = "0.27.1" }
serde = { version = "=1.0.118", features = ["derive"] }
serde_json = "1.0.58"
bs58 = "0.3.1"
ed25519-dalek = { version = "1.0.1", features = ["serde"] }
ed25519-dalek = { version = "1.0.1", features = ["serde", "std"] }
rand = "0.7.0"
signature = "1.3.0"
ed25519 = "1.0.3"
serde_with = "1.6.0"
thiserror = "1.0.23"
lazy_static = "1.2"
libsecp256k1 = "0.3.5"
ring = { version = "0.16.9", features = ["alloc", "std"], default-features = false }
asn1_der = "0.6.1"
sha2 = "0.9.1"
zeroize = "1"
serde_bytes = "0.11"
libp2p-core = { git = "https://github.com/fluencelabs/rust-libp2p", branch = "identity_rework", package = "fluence-fork-libp2p-core" }
[dev-dependencies]
quickcheck = "0.9.0"

239
identity/src/ed25519.rs Normal file
View File

@ -0,0 +1,239 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//! Ed25519 keys.
use crate::error::{DecodingError, SigningError};
use ed25519_dalek::{self as ed25519, Signer as _, Verifier as _};
use rand::RngCore;
use std::convert::TryFrom;
use zeroize::Zeroize;
use core::fmt;
use serde::{Deserialize, Serialize};
/// An Ed25519 keypair.
pub struct Keypair(ed25519::Keypair);
impl Keypair {
/// Generate a new Ed25519 keypair.
pub fn generate() -> Self {
Keypair::from(SecretKey::generate())
}
/// Encode the keypair into a byte array by concatenating the bytes
/// of the secret scalar and the compressed public point,
/// an informal standard for encoding Ed25519 keypairs.
pub fn encode(&self) -> [u8; 64] {
self.0.to_bytes()
}
/// Decode a keypair from the format produced by `encode`,
/// zeroing the input on success.
pub fn decode(kp: &mut [u8]) -> Result<Self, DecodingError> {
ed25519::Keypair::from_bytes(kp)
.map(|k| {
kp.zeroize();
Keypair(k)
})
.map_err(DecodingError::Ed25519)
}
/// Sign a message using the private key of this keypair.
pub fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, SigningError> {
Ok(self.0.try_sign(msg)?.to_bytes().to_vec())
}
/// Get the public key of this keypair.
pub fn public(&self) -> PublicKey {
PublicKey(self.0.public)
}
/// Get the secret key of this keypair.
pub fn secret(&self) -> SecretKey {
SecretKey::from_bytes(&mut self.0.secret.to_bytes())
.expect("ed25519::SecretKey::from_bytes(to_bytes(k)) != k")
}
}
impl fmt::Debug for Keypair {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Keypair").field("public", &self.0.public).finish()
}
}
impl Clone for Keypair {
fn clone(&self) -> Self {
let mut sk_bytes = self.0.secret.to_bytes();
let secret = SecretKey::from_bytes(&mut sk_bytes)
.expect("ed25519::SecretKey::from_bytes(to_bytes(k)) != k").0;
let public = ed25519::PublicKey::from_bytes(&self.0.public.to_bytes())
.expect("ed25519::PublicKey::from_bytes(to_bytes(k)) != k");
Keypair(ed25519::Keypair { secret, public })
}
}
/// Build keypair from existing ed25519 keypair
impl From<ed25519::Keypair> for Keypair {
fn from(kp: ed25519::Keypair) -> Self {
Keypair(kp)
}
}
/// Demote an Ed25519 keypair to a secret key.
impl From<Keypair> for SecretKey {
fn from(kp: Keypair) -> Self {
SecretKey(kp.0.secret)
}
}
/// Promote an Ed25519 secret key into a keypair.
impl From<SecretKey> for Keypair {
fn from(sk: SecretKey) -> Self {
let secret: ed25519::ExpandedSecretKey = (&sk.0).into();
let public = ed25519::PublicKey::from(&secret);
Keypair(ed25519::Keypair { secret: sk.0, public })
}
}
/// An Ed25519 public key.
#[derive(PartialEq, Eq, Debug, Clone, Deserialize, Serialize)]
pub struct PublicKey(ed25519::PublicKey);
impl PublicKey {
/// Verify the Ed25519 signature on a message using the public key.
pub fn verify(&self, msg: &[u8], sig: &[u8]) -> Result<(), SigningError> {
ed25519::Signature::try_from(sig).and_then(|s| self.0.verify(msg, &s)).map_err(SigningError::Ed25519)
}
/// Encode the public key into a byte array in compressed form, i.e.
/// where one coordinate is represented by a single bit.
pub fn encode(&self) -> [u8; 32] {
self.0.to_bytes()
}
/// Decode a public key from a byte array as produced by `encode`.
pub fn decode(bytes: &[u8]) -> Result<Self, DecodingError> {
ed25519::PublicKey::from_bytes(bytes)
.map_err(DecodingError::Ed25519)
.map(PublicKey)
}
}
/// An Ed25519 secret key.
pub struct SecretKey(ed25519::SecretKey);
/// View the bytes of the secret key.
impl AsRef<[u8]> for SecretKey {
fn as_ref(&self) -> &[u8] {
self.0.as_bytes()
}
}
impl Clone for SecretKey {
fn clone(&self) -> Self {
let mut sk_bytes = self.0.to_bytes();
Self::from_bytes(&mut sk_bytes)
.expect("ed25519::SecretKey::from_bytes(to_bytes(k)) != k")
}
}
impl fmt::Debug for SecretKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "SecretKey")
}
}
impl SecretKey {
/// Generate a new Ed25519 secret key.
pub fn generate() -> Self {
let mut bytes = [0u8; 32];
rand::thread_rng().fill_bytes(&mut bytes);
SecretKey(ed25519::SecretKey::from_bytes(&bytes)
.expect("this returns `Err` only if the length is wrong; the length is correct; qed"))
}
/// Create an Ed25519 secret key from a byte slice, zeroing the input on success.
/// If the bytes do not constitute a valid Ed25519 secret key, an error is
/// returned.
pub fn from_bytes(mut sk_bytes: impl AsMut<[u8]>) -> Result<Self, DecodingError> {
let sk_bytes = sk_bytes.as_mut();
let secret = ed25519::SecretKey::from_bytes(&*sk_bytes)
.map_err(DecodingError::Ed25519)?;
sk_bytes.zeroize();
Ok(SecretKey(secret))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub struct Signature(pub Vec<u8>);
#[cfg(test)]
mod tests {
use super::*;
use quickcheck::*;
fn eq_keypairs(kp1: &Keypair, kp2: &Keypair) -> bool {
kp1.public() == kp2.public()
&&
kp1.0.secret.as_bytes() == kp2.0.secret.as_bytes()
}
#[test]
fn ed25519_keypair_encode_decode() {
fn prop() -> bool {
let kp1 = Keypair::generate();
let mut kp1_enc = kp1.encode();
let kp2 = Keypair::decode(&mut kp1_enc).unwrap();
eq_keypairs(&kp1, &kp2)
&&
kp1_enc.iter().all(|b| *b == 0)
}
QuickCheck::new().tests(10).quickcheck(prop as fn() -> _);
}
#[test]
fn ed25519_keypair_from_secret() {
fn prop() -> bool {
let kp1 = Keypair::generate();
let mut sk = kp1.0.secret.to_bytes();
let kp2 = Keypair::from(SecretKey::from_bytes(&mut sk).unwrap());
eq_keypairs(&kp1, &kp2)
&&
sk == [0u8; 32]
}
QuickCheck::new().tests(10).quickcheck(prop as fn() -> _);
}
#[test]
fn ed25519_signature() {
let kp = Keypair::generate();
let pk = kp.public();
let msg = "hello world".as_bytes();
let sig = kp.sign(msg).unwrap();
assert!(pk.verify(msg, &sig).is_ok());
let mut invalid_sig = sig.clone();
invalid_sig[3..6].copy_from_slice(&[10, 23, 42]);
assert!(pk.verify(msg, &invalid_sig).is_err());
let invalid_msg = "h3ll0 w0rld".as_bytes();
assert!(pk.verify(invalid_msg, &sig).is_err());
}
}

69
identity/src/error.rs Normal file
View File

@ -0,0 +1,69 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//! Errors during identity key operations.
use thiserror::Error as ThisError;
/// An error during decoding of key material.
#[derive(ThisError, Debug)]
pub enum Error {
#[error("{0} Key format is not supported")]
InvalidKeyFormat(String),
}
/// An error during decoding of key material.
#[derive(ThisError, Debug)]
pub enum DecodingError {
#[error("Failed to decode with ed25519: {0}")]
Ed25519(
#[from]
#[source]
ed25519_dalek::ed25519::Error
),
#[error("Failed to decode with RSA")]
Rsa,
#[error("Failed to decode with secp256k1")]
Secp256k1,
#[error("RSA keypair decoding is not supported yet")]
KeypairDecodingIsNotSupported,
#[error("Invalid type prefix")]
InvalidTypeByte,
#[error("Cannot decode public key from base58 :{0}")]
Base58DecodeError(#[source] bs58::decode::Error),
}
/// An error during signing of a message.
#[derive(ThisError, Debug)]
pub enum SigningError {
#[error("Failed to sign with ed25519: {0}")]
Ed25519(
#[from]
#[source]
ed25519_dalek::ed25519::Error
),
#[error("Failed to sign with RSA")]
Rsa,
#[error("Failed to sign with secp256k1: {0}")]
Secp256k1(
#[from]
#[source]
secp256k1::Error
),
}

View File

@ -1,168 +1,224 @@
/*
* 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.
*/
// Copyright 2019 Parity Technologies (UK) Ltd.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
use crate::ed25519::Keypair as Libp2pKeyPair;
//! A node's network identity keys.
use crate::ed25519;
#[cfg(not(target_arch = "wasm32"))]
use crate::rsa;
use crate::secp256k1;
use crate::public_key::PublicKey;
use crate::secret_key::SecretKey;
use crate::signature::Signature;
use ed25519_dalek::SignatureError;
use ed25519_dalek::Signer;
use crate::error::{Error, DecodingError, SigningError};
use std::str::FromStr;
use std::convert::TryFrom;
use rand::rngs::OsRng;
use std::fmt;
/// Identity keypair of a node.
///
/// # Example: Generating RSA keys with OpenSSL
///
/// ```text
/// openssl genrsa -out private.pem 2048
/// openssl pkcs8 -in private.pem -inform PEM -topk8 -out private.pk8 -outform DER -nocrypt
/// rm private.pem # optional
/// ```
///
/// Loading the keys:
///
/// ```text
/// let mut bytes = std::fs::read("private.pk8").unwrap();
/// let keypair = Keypair::rsa_from_pkcs8(&mut bytes);
/// ```
///
/// An Ed25519 keypair.
#[derive(Debug)]
pub struct KeyPair {
key_pair: ed25519_dalek::Keypair,
pub enum KeyFormat {
Ed25519,
#[cfg(not(target_arch = "wasm32"))]
Rsa,
Secp256k1,
}
impl FromStr for KeyFormat {
type Err = Error;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"ed25519" => Ok(KeyFormat::Ed25519),
"secp256k1" => Ok(KeyFormat::Secp256k1),
#[cfg(not(target_arch = "wasm32"))]
"rsa" => Ok(KeyFormat::Rsa),
_ => Err(Error::InvalidKeyFormat(s.to_string()))
}
}
}
impl TryFrom<u8> for KeyFormat {
type Error = DecodingError;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(KeyFormat::Ed25519),
#[cfg(not(target_arch = "wasm32"))]
1 => Ok(KeyFormat::Rsa),
2 => Ok(KeyFormat::Secp256k1),
_ => Err(DecodingError::InvalidTypeByte)
}
}
}
impl From<KeyFormat> for u8 {
fn from(kf: KeyFormat) -> Self {
match kf {
KeyFormat::Ed25519 => 0,
#[cfg(not(target_arch = "wasm32"))]
KeyFormat::Rsa => 1,
KeyFormat::Secp256k1 => 2,
}
}
}
#[derive(Clone)]
pub enum KeyPair {
/// An Ed25519 keypair.
Ed25519(ed25519::Keypair),
#[cfg(not(target_arch = "wasm32"))]
/// An RSA keypair.
Rsa(rsa::Keypair),
/// A Secp256k1 keypair.
Secp256k1(secp256k1::Keypair),
}
impl KeyPair {
pub fn generate(format: KeyFormat) -> KeyPair {
match format {
KeyFormat::Ed25519 => KeyPair::generate_ed25519(),
KeyFormat::Secp256k1 => KeyPair::generate_secp256k1(),
#[cfg(not(target_arch = "wasm32"))]
KeyFormat::Rsa => todo!("rsa generation is not supported yet!"),
}
}
/// Generate a new Ed25519 keypair.
#[allow(dead_code)]
pub fn generate() -> Self {
let mut csprng = OsRng {};
let kp = ed25519_dalek::Keypair::generate(&mut csprng);
kp.into()
pub fn generate_ed25519() -> KeyPair {
KeyPair::Ed25519(ed25519::Keypair::generate())
}
pub fn public(&self) -> PublicKey {
PublicKey(self.key_pair.public)
/// Generate a new Secp256k1 keypair.
pub fn generate_secp256k1() -> KeyPair {
KeyPair::Secp256k1(secp256k1::Keypair::generate())
}
pub fn secret(&self) -> SecretKey {
let b = self.key_pair.secret.to_bytes();
SecretKey::from_bytes(&b).expect("SecretKey::from_bytes(to_bytes(k)) != k")
/// Decode an keypair from a DER-encoded secret key in PKCS#8 PrivateKeyInfo
/// format (i.e. unencrypted) as defined in [RFC5208].
///
/// [RFC5208]: https://tools.ietf.org/html/rfc5208#section-5
#[cfg(not(target_arch = "wasm32"))]
pub fn rsa_from_pkcs8(pkcs8_der: &mut [u8]) -> Result<KeyPair, DecodingError> {
rsa::Keypair::from_pkcs8(pkcs8_der).map(KeyPair::Rsa)
}
pub fn from_bytes(sk_bytes: &[u8]) -> Result<Self, SignatureError> {
let kp = ed25519_dalek::Keypair::from_bytes(sk_bytes)?;
Ok(KeyPair { key_pair: kp })
/// Decode a keypair from a DER-encoded Secp256k1 secret key in an ECPrivateKey
/// structure as defined in [RFC5915].
///
/// [RFC5915]: https://tools.ietf.org/html/rfc5915
pub fn secp256k1_from_der(der: &mut [u8]) -> Result<KeyPair, DecodingError> {
secp256k1::SecretKey::from_der(der)
.map(|sk| KeyPair::Secp256k1(secp256k1::Keypair::from(sk)))
}
/// Encode the keypair into a byte array by concatenating the bytes
/// of the secret scalar and the compressed public point/
#[allow(dead_code)]
pub fn encode(&self) -> [u8; 64] {
self.key_pair.to_bytes()
}
/// Decode a keypair from the format produced by `encode`.
#[allow(dead_code)]
pub fn decode(kp: &[u8]) -> Result<KeyPair, SignatureError> {
let kp = ed25519_dalek::Keypair::from_bytes(kp)?;
Ok(Self { key_pair: kp })
/// Sign a message using the private key of this keypair, producing
/// a signature that can be verified using the corresponding public key.
pub fn sign(&self, msg: &[u8]) -> Result<Signature, SigningError> {
use KeyPair::*;
match self {
Ed25519(ref pair) => Ok(Signature::Ed25519(ed25519::Signature(pair.sign(msg)?))),
#[cfg(not(target_arch = "wasm32"))]
Rsa(ref pair) => Ok(Signature::Rsa(rsa::Signature(pair.sign(msg)?))),
Secp256k1(ref pair) => Ok(Signature::Secp256k1(secp256k1::Signature(pair.secret().sign(msg)?)))
}
}
/// Get the public key of this keypair.
#[allow(dead_code)]
pub fn public_key(&self) -> PublicKey {
PublicKey(self.key_pair.public)
}
/// Sign a message using the private key of this keypair.
pub fn sign(&self, msg: &[u8]) -> Signature {
Signature(self.key_pair.sign(msg))
}
/// Verify the Ed25519 signature on a message using the public key.
pub fn verify(pk: &PublicKey, msg: &[u8], signature: &Signature) -> Result<(), SignatureError> {
// let signature = ed25519_dalek::Signature::from_bytes(signature)
// .map_err(|err| format!("Cannot convert bytes to a signature: {:?}", err))?;
pk.verify_strict(msg, signature)
}
}
impl From<Libp2pKeyPair> for KeyPair {
fn from(kp: Libp2pKeyPair) -> Self {
// TODO: this is a hack. Convert directly. Maybe use mem::transmute?
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 }
}
}
impl From<KeyPair> for ed25519_dalek::Keypair {
fn from(kp: KeyPair) -> Self {
kp.key_pair
}
}
impl From<KeyPair> for Libp2pKeyPair {
fn from(kp: KeyPair) -> Self {
Libp2pKeyPair::from(kp.key_pair)
}
}
/// Implement serde::Deserialize for KeyPair
impl<'de> serde::Deserialize<'de> for KeyPair {
fn deserialize<D>(deserializer: D) -> Result<KeyPair, D::Error>
where
D: serde::Deserializer<'de>,
{
use serde::de::{Error, Unexpected, Visitor};
struct KeyPairVisitor;
impl<'de> Visitor<'de> for KeyPairVisitor {
type Value = KeyPair;
/// Error message stating what was expected
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("byte array or base58 string")
}
/// Implement deserialization from base58 string
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: Error,
{
bs58::decode(s)
.into_vec()
.map_err(|_| Error::invalid_value(Unexpected::Str(s), &self))
.and_then(|v| self.visit_bytes(v.as_slice()))
}
/// Implement deserialization from bytes
fn visit_bytes<E>(self, b: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
KeyPair::decode(b).map_err(|_| Error::invalid_value(Unexpected::Bytes(b), &self))
}
pub fn public(&self) -> PublicKey {
use KeyPair::*;
match self {
Ed25519(pair) => PublicKey::Ed25519(pair.public()),
#[cfg(not(target_arch = "wasm32"))]
Rsa(pair) => PublicKey::Rsa(pair.public()),
Secp256k1(pair) => PublicKey::Secp256k1(pair.public().clone()),
}
deserializer.deserialize_str(KeyPairVisitor)
}
}
impl Clone for KeyPair {
fn clone(&self) -> KeyPair {
let sk_bytes = self.key_pair.secret.to_bytes();
let secret = ed25519_dalek::SecretKey::from_bytes(&sk_bytes)
.expect("ed25519::SecretKey::from_bytes(to_bytes(k)) != k");
let public = ed25519_dalek::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 },
/// Verify the signature on a message using the public key.
pub fn verify(pk: &PublicKey, msg: &[u8], signature: &Signature) -> Result<(), SigningError> {
pk.verify(msg, signature)
}
pub fn to_vec(&self) -> Vec<u8> {
use KeyPair::*;
match self {
Ed25519(kp) => kp.encode().to_vec(),
#[cfg(not(target_arch = "wasm32"))]
Rsa(_) => todo!("rsa encoding is not supported yet!"),
Secp256k1(kp) => kp.secret().to_bytes().to_vec(),
}
}
pub fn from_vec(mut bytes: Vec<u8>, format: KeyFormat) -> Result<Self, DecodingError> {
use KeyPair::*;
match format {
KeyFormat::Ed25519 => Ok(Ed25519(ed25519::Keypair::decode(&mut bytes)?)),
KeyFormat::Secp256k1 => Ok(Secp256k1(secp256k1::SecretKey::from_bytes(bytes)?.into())),
#[cfg(not(target_arch = "wasm32"))]
KeyFormat::Rsa => Err(DecodingError::KeypairDecodingIsNotSupported)
}
}
}
impl From<libp2p_core::identity::Keypair> for KeyPair {
fn from(key: libp2p_core::identity::Keypair) -> Self {
use libp2p_core::identity::Keypair::*;
match key {
Ed25519(kp) => KeyPair::Ed25519(ed25519::Keypair::decode(&mut kp.encode()).unwrap()),
#[cfg(not(target_arch = "wasm32"))]
// safety: these Keypair structures are identical
Rsa(kp) => KeyPair::Rsa(unsafe { std::mem::transmute::<libp2p_core::identity::rsa::Keypair, rsa::Keypair>(kp) }),
Secp256k1(kp) => KeyPair::Secp256k1(secp256k1::Keypair::from(secp256k1::SecretKey::from_bytes(kp.secret().to_bytes()).unwrap())),
}
}
}
impl From<KeyPair> for libp2p_core::identity::Keypair {
fn from(key: KeyPair) -> Self {
use KeyPair::*;
use libp2p_core::identity::Keypair;
use libp2p_core::identity;
match key {
Ed25519(kp) => Keypair::Ed25519(identity::ed25519::Keypair::decode(kp.encode().to_vec().as_mut_slice()).unwrap()),
#[cfg(not(target_arch = "wasm32"))]
Rsa(kp) => Keypair::Rsa(unsafe { std::mem::transmute::<rsa::Keypair, libp2p_core::identity::rsa::Keypair>(kp) }),
Secp256k1(kp) => Keypair::Secp256k1(identity::secp256k1::Keypair::from(identity::secp256k1::SecretKey::from_bytes(kp.secret().to_bytes()).unwrap())),
}
}
}

View File

@ -26,14 +26,16 @@
unreachable_patterns
)]
mod secp256k1;
mod ed25519;
#[cfg(not(target_arch = "wasm32"))]
mod rsa;
pub mod key_pair;
pub mod error;
pub mod public_key;
pub mod secret_key;
pub mod signature;
pub use crate::key_pair::KeyPair;
pub use key_pair::KeyPair;
pub use key_pair::KeyFormat;
pub use crate::public_key::PublicKey;
pub use crate::secret_key::SecretKey;
pub use crate::signature::Signature;
pub(crate) use libp2p_core::identity::ed25519;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2020 Fluence Labs Limited
* Copyright 2021 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.
@ -13,63 +13,125 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
use crate::public_key::PKError::{FromBase58Error, FromBytesError};
use crate::ed25519;
#[cfg(not(target_arch = "wasm32"))]
use crate::rsa;
use crate::secp256k1;
use crate::error::{DecodingError, SigningError};
use crate::signature::Signature;
use core::fmt::Debug;
use ed25519_dalek::SignatureError;
use serde::{Deserialize, Serialize};
use thiserror::Error as ThisError;
use libp2p_core::identity;
use crate::key_pair::KeyFormat;
use std::convert::TryFrom;
#[derive(ThisError, Debug)]
pub enum PKError {
#[error("Cannot decode public key from bytes: {0}")]
FromBytesError(#[source] SignatureError),
#[error("Cannot decode public key from base58 format: {0}")]
FromBase58Error(#[source] bs58::decode::Error),
}
#[derive(Copy, Clone, Default, Eq, PartialEq, Serialize, Deserialize)]
pub struct PublicKey(pub(crate) ed25519_dalek::PublicKey);
impl Debug for PublicKey {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
write!(f, "{:?}", self.0)
}
/// The public key of a node's identity keypair.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum PublicKey {
/// A public Ed25519 key.
Ed25519(ed25519::PublicKey),
#[cfg(not(target_arch = "wasm32"))]
/// A public RSA key.
Rsa(rsa::PublicKey),
/// A public Secp256k1 key.
Secp256k1(secp256k1::PublicKey),
}
impl PublicKey {
pub fn verify_strict(
&self,
message: &[u8],
signature: &Signature,
) -> Result<(), SignatureError> {
self.0.verify_strict(message, &signature.0)
/// Verify a signature for a message using this public key, i.e. check
/// that the signature has been produced by the corresponding
/// private key (authenticity), and that the message has not been
/// tampered with (integrity).
pub fn verify(&self, msg: &[u8], sig: &Signature) -> Result<(), SigningError> {
use PublicKey::*;
match self {
Ed25519(pk) => pk.verify(msg, sig.to_vec()),
#[cfg(not(target_arch = "wasm32"))]
Rsa(pk) => pk.verify(msg, sig.to_vec()),
Secp256k1(pk) => pk.verify(msg, sig.to_vec())
}
}
pub fn from_base58(str: &str) -> Result<PublicKey, PKError> {
let bytes = bs58::decode(str).into_vec().map_err(FromBase58Error)?;
Self::from_bytes(&bytes)
pub fn encode(&self) -> Vec<u8> {
use PublicKey::*;
let mut result: Vec<u8> = vec![self.get_prefix()];
match self {
Ed25519(pk) => result.extend(pk.encode().to_vec()),
#[cfg(not(target_arch = "wasm32"))]
Rsa(pk) => result.extend(pk.to_pkcs1()),
Secp256k1(pk) => result.extend(pk.encode().to_vec()),
};
result
}
pub fn from_bytes(bytes: &[u8]) -> Result<PublicKey, PKError> {
let pk = ed25519_dalek::PublicKey::from_bytes(bytes).map_err(FromBytesError)?;
Ok(PublicKey(pk))
pub fn decode(bytes: &[u8]) -> Result<PublicKey, DecodingError> {
match KeyFormat::try_from(bytes[0])? {
KeyFormat::Ed25519 => Ok(PublicKey::Ed25519(ed25519::PublicKey::decode(&bytes[1..])?)),
#[cfg(not(target_arch = "wasm32"))]
KeyFormat::Rsa => Ok(PublicKey::Rsa(rsa::PublicKey::from_pkcs1(bytes[1..].to_owned())?)),
KeyFormat::Secp256k1 => Ok(PublicKey::Secp256k1(secp256k1::PublicKey::decode(&bytes[1..])?)),
}
}
pub fn to_bytes(&self) -> [u8; ed25519_dalek::PUBLIC_KEY_LENGTH] {
self.0.to_bytes()
fn get_prefix(&self) -> u8 {
use PublicKey::*;
match self {
Ed25519(_) => KeyFormat::Ed25519.into(),
#[cfg(not(target_arch = "wasm32"))]
Rsa(_) => KeyFormat::Rsa.into(),
Secp256k1(_) => KeyFormat::Secp256k1.into()
}
}
pub fn from_libp2p(pk: &identity::ed25519::PublicKey) -> Result<Self, PKError> {
Self::from_bytes(&pk.encode())
pub fn from_base58(str: &str) -> Result<PublicKey, DecodingError> {
let bytes = bs58::decode(str).into_vec().map_err(DecodingError::Base58DecodeError)?;
Self::decode(&bytes)
}
pub fn to_vec(&self) -> Vec<u8> {
use PublicKey::*;
match self {
Ed25519(pk) => pk.encode().to_vec(),
#[cfg(not(target_arch = "wasm32"))]
Rsa(pk) => pk.to_pkcs1().to_vec(),
Secp256k1(pk) => pk.encode().to_vec(),
}
}
}
impl From<PublicKey> for ed25519_dalek::PublicKey {
fn from(key: PublicKey) -> Self {
key.0
impl From<libp2p_core::identity::PublicKey> for PublicKey {
fn from(key: libp2p_core::identity::PublicKey) -> Self {
use libp2p_core::identity::PublicKey::*;
match key {
Ed25519(key) => PublicKey::Ed25519(ed25519::PublicKey::decode(&key.encode()[..]).unwrap()),
#[cfg(not(target_arch = "wasm32"))]
Rsa(key) => PublicKey::Rsa(rsa::PublicKey::from_pkcs1(key.encode_pkcs1()).unwrap()),
Secp256k1(key) => PublicKey::Secp256k1(secp256k1::PublicKey::decode(&key.encode()[..]).unwrap()),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::KeyPair;
#[test]
fn public_key_encode_decode_ed25519() {
let kp = KeyPair::generate_ed25519();
let pk = kp.public();
let encoded_pk = pk.encode();
assert_eq!(pk, PublicKey::decode(&encoded_pk).unwrap());
}
#[test]
fn public_key_encode_decode_secp256k1() {
let kp = KeyPair::generate_secp256k1();
let pk = kp.public();
let encoded_pk = pk.encode();
assert_eq!(pk, PublicKey::decode(&encoded_pk).unwrap());
}
}

278
identity/src/rsa.rs Normal file
View File

@ -0,0 +1,278 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//! RSA keys.
use crate::error::{DecodingError, SigningError};
use asn1_der::{Asn1Der, FromDerObject, IntoDerObject, DerObject, DerTag, DerValue, Asn1DerError};
use lazy_static::lazy_static;
use ring::rand::SystemRandom;
use ring::signature::{self, RsaKeyPair, RSA_PKCS1_SHA256, RSA_PKCS1_2048_8192_SHA256};
use ring::signature::KeyPair;
use std::{fmt::{self, Write}, sync::Arc};
use zeroize::Zeroize;
use serde::{Deserialize, Serialize};
/// An RSA keypair.
#[derive(Clone)]
pub struct Keypair(Arc<RsaKeyPair>);
impl Keypair {
/// Decode an RSA keypair from a DER-encoded private key in PKCS#8 PrivateKeyInfo
/// format (i.e. unencrypted) as defined in [RFC5208].
///
/// [RFC5208]: https://tools.ietf.org/html/rfc5208#section-5
pub fn from_pkcs8(der: &mut [u8]) -> Result<Self, DecodingError> {
let kp = RsaKeyPair::from_pkcs8(&der)
.map_err(|_| DecodingError::Rsa)?;
der.zeroize();
Ok(Keypair(Arc::new(kp)))
}
/// Get the public key from the keypair.
pub fn public(&self) -> PublicKey {
PublicKey(self.0.public_key().as_ref().to_vec())
}
/// Sign a message with this keypair.
pub fn sign(&self, data: &[u8]) -> Result<Vec<u8>, SigningError> {
let mut signature = vec![0; self.0.public_modulus_len()];
let rng = SystemRandom::new();
match self.0.sign(&RSA_PKCS1_SHA256, &rng, &data, &mut signature) {
Ok(()) => Ok(signature),
Err(_) => Err(SigningError::Rsa)
}
}
}
/// An RSA public key.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PublicKey(Vec<u8>);
impl PublicKey {
/// Verify an RSA signature on a message using the public key.
pub fn verify(&self, msg: &[u8], sig: &[u8]) -> Result<(), SigningError> {
let key = signature::UnparsedPublicKey::new(&RSA_PKCS1_2048_8192_SHA256, &self.0);
key.verify(msg, sig).map_err(|_| SigningError::Rsa)
}
/// Encode the RSA public key in DER as a PKCS#1 RSAPublicKey structure,
/// as defined in [RFC3447].
///
/// [RFC3447]: https://tools.ietf.org/html/rfc3447#appendix-A.1.1
pub fn to_pkcs1(&self) -> &[u8] {
// This is the encoding currently used in-memory, so it is trivial.
&self.0
}
pub fn from_pkcs1(pk: Vec<u8>) -> Result<Self, DecodingError> {
Ok(PublicKey(pk))
}
/// Encode the RSA public key in DER as a X.509 SubjectPublicKeyInfo structure,
/// as defined in [RFC5280].
///
/// [RFC5280]: https://tools.ietf.org/html/rfc5280#section-4.1
pub fn encode_x509(&self) -> Vec<u8> {
let spki = Asn1SubjectPublicKeyInfo {
algorithmIdentifier: Asn1RsaEncryption {
algorithm: Asn1OidRsaEncryption(),
parameters: (),
},
subjectPublicKey: Asn1SubjectPublicKey(self.clone()),
};
let mut buf = vec![0u8; spki.serialized_len()];
spki.serialize(buf.iter_mut()).map(|_| buf)
.expect("RSA X.509 public key encoding failed.")
}
/// Decode an RSA public key from a DER-encoded X.509 SubjectPublicKeyInfo
/// structure. See also `encode_x509`.
pub fn decode_x509(pk: &[u8]) -> Result<Self, DecodingError> {
Asn1SubjectPublicKeyInfo::deserialize(pk.iter())
.map_err(|_| DecodingError::Rsa)
.map(|spki| spki.subjectPublicKey.0)
}
}
impl fmt::Debug for PublicKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let bytes = &self.0;
let mut hex = String::with_capacity(bytes.len() * 2);
for byte in bytes {
write!(hex, "{:02x}", byte).expect("Can't fail on writing to string");
}
f.debug_struct("PublicKey")
.field("pkcs1", &hex)
.finish()
}
}
//////////////////////////////////////////////////////////////////////////////
// DER encoding / decoding of public keys
//
// Primer: http://luca.ntop.org/Teaching/Appunti/asn1.html
// Playground: https://lapo.it/asn1js/
lazy_static! {
/// The DER encoding of the object identifier (OID) 'rsaEncryption' for
/// RSA public keys defined for X.509 in [RFC-3279] and used in
/// SubjectPublicKeyInfo structures defined in [RFC-5280].
///
/// [RFC-3279]: https://tools.ietf.org/html/rfc3279#section-2.3.1
/// [RFC-5280]: https://tools.ietf.org/html/rfc5280#section-4.1
static ref OID_RSA_ENCRYPTION_DER: DerObject =
DerObject {
tag: DerTag::x06,
value: DerValue {
data: vec![ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 ]
}
};
}
/// The ASN.1 OID for "rsaEncryption".
#[derive(Clone)]
struct Asn1OidRsaEncryption();
impl IntoDerObject for Asn1OidRsaEncryption {
fn into_der_object(self) -> DerObject {
OID_RSA_ENCRYPTION_DER.clone()
}
fn serialized_len(&self) -> usize {
OID_RSA_ENCRYPTION_DER.serialized_len()
}
}
impl FromDerObject for Asn1OidRsaEncryption {
fn from_der_object(o: DerObject) -> Result<Self, Asn1DerError> {
if o.tag != DerTag::x06 {
return Err(Asn1DerError::InvalidTag);
}
if o.value != OID_RSA_ENCRYPTION_DER.value {
return Err(Asn1DerError::InvalidEncoding);
}
Ok(Asn1OidRsaEncryption())
}
}
/// The ASN.1 AlgorithmIdentifier for "rsaEncryption".
#[derive(Asn1Der)]
struct Asn1RsaEncryption {
algorithm: Asn1OidRsaEncryption,
parameters: (),
}
/// The ASN.1 SubjectPublicKey inside a SubjectPublicKeyInfo,
/// i.e. encoded as a DER BIT STRING.
struct Asn1SubjectPublicKey(PublicKey);
impl IntoDerObject for Asn1SubjectPublicKey {
fn into_der_object(self) -> DerObject {
let pk_der = (self.0).0;
let mut bit_string = Vec::with_capacity(pk_der.len() + 1);
// The number of bits in pk_der is trivially always a multiple of 8,
// so there are always 0 "unused bits" signaled by the first byte.
bit_string.push(0u8);
bit_string.extend(pk_der);
DerObject::new(DerTag::x03, bit_string.into())
}
fn serialized_len(&self) -> usize {
DerObject::compute_serialized_len((self.0).0.len() + 1)
}
}
impl FromDerObject for Asn1SubjectPublicKey {
fn from_der_object(o: DerObject) -> Result<Self, Asn1DerError> {
if o.tag != DerTag::x03 {
return Err(Asn1DerError::InvalidTag);
}
let pk_der: Vec<u8> = o.value.data.into_iter().skip(1).collect();
// We don't parse pk_der further as an ASN.1 RsaPublicKey, since
// we only need the DER encoding for `verify`.
Ok(Asn1SubjectPublicKey(PublicKey(pk_der)))
}
}
/// ASN.1 SubjectPublicKeyInfo
#[derive(Asn1Der)]
#[allow(non_snake_case)]
struct Asn1SubjectPublicKeyInfo {
algorithmIdentifier: Asn1RsaEncryption,
subjectPublicKey: Asn1SubjectPublicKey,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Signature(pub Vec<u8>);
#[cfg(test)]
mod tests {
use super::*;
use quickcheck::*;
use rand::seq::SliceRandom;
use std::fmt;
const KEY1: &'static [u8] = include_bytes!("test/rsa-2048.pk8");
const KEY2: &'static [u8] = include_bytes!("test/rsa-3072.pk8");
const KEY3: &'static [u8] = include_bytes!("test/rsa-4096.pk8");
#[derive(Clone)]
struct SomeKeypair(Keypair);
impl fmt::Debug for SomeKeypair {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "SomeKeypair")
}
}
impl Arbitrary for SomeKeypair {
fn arbitrary<G: Gen>(g: &mut G) -> SomeKeypair {
let mut key = [KEY1, KEY2, KEY3].choose(g).unwrap().to_vec();
SomeKeypair(Keypair::from_pkcs8(&mut key).unwrap())
}
}
#[test]
fn rsa_from_pkcs8() {
assert!(Keypair::from_pkcs8(&mut KEY1.to_vec()).is_ok());
assert!(Keypair::from_pkcs8(&mut KEY2.to_vec()).is_ok());
assert!(Keypair::from_pkcs8(&mut KEY3.to_vec()).is_ok());
}
#[test]
fn rsa_x509_encode_decode() {
fn prop(SomeKeypair(kp): SomeKeypair) -> Result<bool, String> {
let pk = kp.public();
PublicKey::decode_x509(&pk.encode_x509())
.map_err(|e| e.to_string())
.map(|pk2| pk2 == pk)
}
QuickCheck::new().tests(10).quickcheck(prop as fn(_) -> _);
}
#[test]
fn rsa_sign_verify() {
fn prop(SomeKeypair(kp): SomeKeypair, msg: Vec<u8>) -> Result<bool, SigningError> {
kp.sign(&msg).map(|s| kp.public().verify(&msg, &s).is_ok())
}
QuickCheck::new().tests(10).quickcheck(prop as fn(_, _) -> _);
}
}

230
identity/src/secp256k1.rs Normal file
View File

@ -0,0 +1,230 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//! Secp256k1 keys.
use crate::error::{DecodingError, SigningError};
use asn1_der::{FromDerObject, DerObject};
use rand::RngCore;
use sha2::{Digest as ShaDigestTrait, Sha256};
use secp256k1::Message;
use zeroize::Zeroize;
use core::fmt;
use serde::{Deserialize, Serialize, Serializer, Deserializer};
use serde::de::Error as SerdeError;
use serde_bytes::{Bytes as SerdeBytes, ByteBuf as SerdeByteBuf};
/// A Secp256k1 keypair.
#[derive(Clone)]
pub struct Keypair {
secret: SecretKey,
public: PublicKey,
}
impl Keypair {
/// Generate a new sec256k1 `Keypair`.
pub fn generate() -> Self {
Keypair::from(SecretKey::generate())
}
/// Get the public key of this keypair.
pub fn public(&self) -> &PublicKey {
&self.public
}
/// Get the secret key of this keypair.
pub fn secret(&self) -> &SecretKey {
&self.secret
}
}
impl fmt::Debug for Keypair {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Keypair").field("public", &self.public).finish()
}
}
/// Promote a Secp256k1 secret key into a keypair.
impl From<SecretKey> for Keypair {
fn from(secret: SecretKey) -> Self {
let public = PublicKey(secp256k1::PublicKey::from_secret_key(&secret.0));
Keypair { secret, public }
}
}
/// Demote a Secp256k1 keypair into a secret key.
impl From<Keypair> for SecretKey {
fn from(kp: Keypair) -> Self {
kp.secret
}
}
/// A Secp256k1 secret key.
#[derive(Clone)]
pub struct SecretKey(secp256k1::SecretKey);
impl fmt::Debug for SecretKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "SecretKey")
}
}
impl SecretKey {
/// Generate a new Secp256k1 secret key.
pub fn generate() -> Self {
let mut r = rand::thread_rng();
let mut b = [0; secp256k1::util::SECRET_KEY_SIZE];
// This is how it is done in `secp256k1::SecretKey::random` which
// we do not use here because it uses `rand::Rng` from rand-0.4.
loop {
r.fill_bytes(&mut b);
if let Ok(k) = secp256k1::SecretKey::parse(&b) {
return SecretKey(k);
}
}
}
/// Create a secret key from a byte slice, zeroing the slice on success.
/// If the bytes do not constitute a valid Secp256k1 secret key, an
/// error is returned.
pub fn from_bytes(mut sk: impl AsMut<[u8]>) -> Result<Self, DecodingError> {
let sk_bytes = sk.as_mut();
let secret = secp256k1::SecretKey::parse_slice(&*sk_bytes)
.map_err(|_| DecodingError::Secp256k1)?;
sk_bytes.zeroize();
Ok(SecretKey(secret))
}
/// Decode a DER-encoded Secp256k1 secret key in an ECPrivateKey
/// structure as defined in [RFC5915].
///
/// [RFC5915]: https://tools.ietf.org/html/rfc5915
pub fn from_der(mut der: impl AsMut<[u8]>) -> Result<SecretKey, DecodingError> {
// TODO: Stricter parsing.
let der_obj = der.as_mut();
let obj: Vec<DerObject> = FromDerObject::deserialize((&*der_obj).iter())
.map_err(|_| DecodingError::Secp256k1)?;
der_obj.zeroize();
let sk_obj = obj.into_iter().nth(1)
.ok_or(DecodingError::Secp256k1)?;
let mut sk_bytes: Vec<u8> = FromDerObject::from_der_object(sk_obj)
.map_err(|_| DecodingError::Secp256k1)?;
let sk = SecretKey::from_bytes(&mut sk_bytes)?;
sk_bytes.zeroize();
Ok(sk)
}
/// Sign a message with this secret key, producing a DER-encoded
/// ECDSA signature, as defined in [RFC3278].
///
/// [RFC3278]: https://tools.ietf.org/html/rfc3278#section-8.2
pub fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, SigningError> {
self.sign_hashed(Sha256::digest(msg).as_ref())
}
/// Returns the raw bytes of the secret key.
pub fn to_bytes(&self) -> [u8; 32] {
self.0.serialize()
}
/// Sign a raw message of length 256 bits with this secret key, produces a DER-encoded
/// ECDSA signature.
pub fn sign_hashed(&self, msg: &[u8]) -> Result<Vec<u8>, SigningError> {
let m = Message::parse_slice(msg)
.map_err(SigningError::Secp256k1)?;
Ok(secp256k1::sign(&m, &self.0).0.serialize_der().as_ref().into())
}
}
/// A Secp256k1 public key.
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct PublicKey(secp256k1::PublicKey);
impl PublicKey {
/// Verify the Secp256k1 signature on a message using the public key.
pub fn verify(&self, msg: &[u8], sig: &[u8]) -> Result<(), SigningError> {
self.verify_hashed(Sha256::digest(msg).as_ref(), sig)
}
/// Verify the Secp256k1 DER-encoded signature on a raw 256-bit message using the public key.
pub fn verify_hashed(&self, msg: &[u8], sig: &[u8]) -> Result<(), SigningError> {
Message::parse_slice(msg)
.and_then(|m| secp256k1::Signature::parse_der(sig).map(|s| secp256k1::verify(&m, &s, &self.0)))
.map_err(SigningError::Secp256k1).map(|_| ())
}
/// Encode the public key in compressed form, i.e. with one coordinate
/// represented by a single bit.
pub fn encode(&self) -> [u8; 33] {
self.0.serialize_compressed()
}
/// Encode the public key in uncompressed form.
pub fn encode_uncompressed(&self) -> [u8; 65] {
self.0.serialize()
}
/// Decode a public key from a byte slice in the the format produced
/// by `encode`.
pub fn decode(bytes: &[u8]) -> Result<Self, DecodingError> {
secp256k1::PublicKey::parse_slice(bytes, Some(secp256k1::PublicKeyFormat::Compressed))
.map_err(|_| DecodingError::Secp256k1)
.map(PublicKey)
}
}
impl Serialize for PublicKey {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
SerdeBytes::new(self.encode().to_vec().as_slice()).serialize(serializer)
}
}
impl<'d> Deserialize<'d> for PublicKey {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'d>,
{
let bytes = <SerdeByteBuf>::deserialize(deserializer)?;
PublicKey::decode(bytes.as_slice()).map_err(SerdeError::custom)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Signature(pub Vec<u8>);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn secp256k1_secret_from_bytes() {
let sk1 = SecretKey::generate();
let mut sk_bytes = [0; 32];
sk_bytes.copy_from_slice(&sk1.0.serialize()[..]);
let sk2 = SecretKey::from_bytes(&mut sk_bytes).unwrap();
assert_eq!(sk1.0.serialize(), sk2.0.serialize());
assert_eq!(sk_bytes, [0; 32]);
}
}

View File

@ -1,35 +0,0 @@
/*
* 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.
*/
use ed25519_dalek::SignatureError;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub struct SecretKey(ed25519_dalek::SecretKey);
impl SecretKey {
pub fn from_bytes(bytes: &[u8]) -> Result<SecretKey, SignatureError> {
let pk = ed25519_dalek::SecretKey::from_bytes(bytes)?;
Ok(SecretKey(pk))
}
}
impl AsRef<[u8]> for SecretKey {
fn as_ref(&self) -> &[u8] {
self.0.as_bytes()
}
}

View File

@ -13,40 +13,88 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
use crate::ed25519;
use crate::secp256k1;
#[cfg(not(target_arch = "wasm32"))]
use crate::rsa;
use crate::error::DecodingError;
use serde::{Deserialize, Serialize};
use signature::Error as SigError;
use signature::Signature as SigSignature;
use thiserror::Error as ThisError;
use crate::key_pair::KeyFormat;
use std::convert::TryFrom;
#[derive(ThisError, Debug)]
pub enum SignatureError {
#[error("{0}")]
Error(
#[from]
#[source]
SigError,
),
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub enum Signature {
Ed25519(ed25519::Signature),
#[cfg(not(target_arch = "wasm32"))]
Rsa(rsa::Signature),
Secp256k1(secp256k1::Signature),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct Signature(pub ed25519_dalek::Signature);
pub const SIGNATURE_LENGTH: usize = 64;
impl Signature {
/// Create a new signature from a byte array
pub fn new(bytes: [u8; SIGNATURE_LENGTH]) -> Self {
Signature(ed25519_dalek::Signature::from(bytes))
fn get_prefix(&self) -> u8 {
use Signature::*;
match self {
Ed25519(_) => KeyFormat::Ed25519.into(),
#[cfg(not(target_arch = "wasm32"))]
Rsa(_) => KeyFormat::Rsa.into(),
Secp256k1(_) => KeyFormat::Secp256k1.into()
}
}
/// Return the inner byte array
pub fn to_bytes(&self) -> [u8; SIGNATURE_LENGTH] {
self.0.to_bytes()
/// encode keypair type in first byte and signature as byte array
pub fn encode(&self) -> Vec<u8> {
use Signature::*;
let mut result: Vec<u8> = vec![self.get_prefix()];
match self {
Ed25519(sig) => result.extend(sig.0.clone()),
#[cfg(not(target_arch = "wasm32"))]
Rsa(sig) => result.extend(sig.0.clone()),
Secp256k1(sig) => result.extend(sig.0.clone()),
}
result
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, SignatureError> {
let sig = ed25519_dalek::Signature::from_bytes(bytes)?;
Ok(Signature(sig))
/// decode with first byte set as keypair type
pub fn decode(bytes: Vec<u8>) -> Result<Self, DecodingError> {
match KeyFormat::try_from(bytes[0])? {
KeyFormat::Ed25519 => Ok(Signature::Ed25519(ed25519::Signature(bytes[1..].to_vec()))),
#[cfg(not(target_arch = "wasm32"))]
KeyFormat::Rsa => Ok(Signature::Rsa(rsa::Signature(bytes[1..].to_vec()))),
KeyFormat::Secp256k1 => Ok(Signature::Secp256k1(secp256k1::Signature(bytes[1..].to_vec()))),
}
}
pub fn to_vec(&self) -> &[u8] {
use Signature::*;
match self {
Ed25519(sig) => &sig.0,
#[cfg(not(target_arch = "wasm32"))]
Rsa(sig) => &sig.0,
Secp256k1(sig) => &sig.0,
}
}
}
#[cfg(test)]
mod tests {
use crate::*;
#[test]
fn signature_encode_decode() {
let bytes: Vec<u8> = (0..10).collect();
let ed25519_sig = Signature::Ed25519(crate::ed25519::Signature(bytes.clone()));
let secp256k1_sig = Signature::Secp256k1(crate::secp256k1::Signature(bytes.clone()));
#[cfg(not(target_arch = "wasm32"))]
let rsa_sig = Signature::Rsa(crate::rsa::Signature(bytes.clone()));
assert_eq!(Signature::decode(ed25519_sig.encode()).unwrap(), ed25519_sig);
assert_eq!(Signature::decode(secp256k1_sig.encode()).unwrap(), secp256k1_sig);
#[cfg(not(target_arch = "wasm32"))]
assert_eq!(Signature::decode(rsa_sig.encode()).unwrap(), rsa_sig);
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -15,11 +15,11 @@
*/
use crate::certificate::CertificateError::{
CertificateLengthError, DecodeError, DecodeTrustError, ExpirationError, IncorrectByteLength,
CertificateLengthError, DecodeError, DecodeTrustError, ExpirationError,
IncorrectCertificateFormat, KeyInCertificateError, MalformedRoot, NoTrustedRoot,
VerificationError,
};
use crate::trust::{Trust, TrustError, TRUST_LEN};
use crate::trust::{Trust, TrustError};
use fluence_identity::key_pair::KeyPair;
use fluence_identity::public_key::PublicKey;
use std::str::FromStr;
@ -32,6 +32,7 @@ const FORMAT: &[u8; 2] = &[0, 0];
/// Serialization format version of a certificate.
/// TODO
const VERSION: &[u8; 4] = &[0, 0, 0, 0];
const TRUST_NUMBER_LEN: usize = 1;
/// Chain of trusts started from self-signed root trust.
#[derive(Debug, Clone, PartialEq, Eq)]
@ -83,7 +84,7 @@ impl Certificate {
) -> Self {
let root_expiration = Duration::from_secs(u64::max_value());
let root_trust = Trust::create(root_kp, root_kp.public_key(), root_expiration, issued_at);
let root_trust = Trust::create(root_kp, root_kp.public(), root_expiration, issued_at);
let trust = Trust::create(root_kp, for_pk, expires_at, issued_at);
@ -109,9 +110,9 @@ impl Certificate {
}
// first, verify given certificate
Certificate::verify(extend_cert, &[extend_cert.chain[0].issued_for], cur_time)?;
Certificate::verify(extend_cert, &[extend_cert.chain[0].issued_for.clone()], cur_time)?;
let issued_by_pk = issued_by.public_key();
let issued_by_pk = issued_by.public();
// check if `issued_by_pk` is allowed to issue a certificate (i.e., theres a trust for it in a chain)
let mut previous_trust_num: i32 = -1;
@ -172,46 +173,60 @@ impl Certificate {
}
/// Convert certificate to byte format
/// 2 format + 4 version + (64 signature + 32 public key + 8 expiration) * number of trusts
/// 2 format + 4 version + 1 trusts number + ((1 trust size byte + trust) for each trust)
#[allow(dead_code)]
pub fn encode(&self) -> Vec<u8> {
let mut encoded =
Vec::with_capacity(FORMAT.len() + VERSION.len() + TRUST_LEN * self.chain.len());
let mut encoded = Vec::new();
encoded.extend_from_slice(FORMAT);
encoded.extend_from_slice(VERSION);
encoded.push(self.chain.len() as u8);
for t in &self.chain {
encoded.extend(t.encode());
let trust = t.encode();
encoded.push(trust.len() as u8);
encoded.extend(trust);
}
encoded
}
fn check_arr_len(arr: &[u8], check_len: usize) -> Result<(), CertificateError> {
if arr.len() < check_len {
Err(CertificateLengthError)
} else {
Ok(())
}
}
#[allow(dead_code)]
pub fn decode(arr: &[u8]) -> Result<Self, CertificateError> {
let trusts_offset = arr.len() - 2 - 4;
if trusts_offset % TRUST_LEN != 0 {
return Err(IncorrectByteLength);
}
// TODO do match different formats and versions
Self::check_arr_len(arr, FORMAT.len() + VERSION.len() + TRUST_NUMBER_LEN)?;
let mut offset = 0;
let _format = &arr[offset..offset + FORMAT.len()];
offset += FORMAT.len();
let number_of_trusts = trusts_offset / TRUST_LEN;
let _version = &arr[offset..offset + VERSION.len()];
offset += VERSION.len();
let number_of_trusts = arr[offset] as usize;
offset += TRUST_NUMBER_LEN;
if number_of_trusts < 2 {
return Err(CertificateLengthError);
}
// TODO do match different formats and versions
let _format = &arr[0..1];
let _version = &arr[2..5];
let mut chain = Vec::with_capacity(number_of_trusts);
for i in 0..number_of_trusts {
let from = i * TRUST_LEN + 6;
let to = (i + 1) * TRUST_LEN + 6;
for _ in 0..number_of_trusts {
Self::check_arr_len(arr, offset + 1)?;
let trust_len = arr[offset] as usize;
let from = offset + 1;
let to = from + trust_len;
Self::check_arr_len(arr, to)?;
let slice = &arr[from..to];
let t = Trust::decode(slice).map_err(DecodeError)?;
chain.push(t);
offset += 1 + trust_len;
}
Ok(Self { chain })
@ -253,7 +268,7 @@ impl FromStr for Certificate {
str_lines[i + 2],
str_lines[i + 3],
)
.map_err(|e| DecodeTrustError(i, e))?;
.map_err(|e| DecodeTrustError(i, e))?;
trusts.push(trust);
}
@ -282,12 +297,12 @@ mod tests {
}
#[test]
pub fn test_string_encoding_decoding() {
pub fn test_string_encoding_decoding_ed25519() {
let (_root_kp, second_kp, cert) = generate_root_cert();
let cur_time = current_time();
let third_kp = KeyPair::generate();
let third_kp = KeyPair::generate_ed25519();
let new_cert = Certificate::issue(
&second_kp,
@ -297,7 +312,7 @@ mod tests {
cur_time,
cur_time,
)
.unwrap();
.unwrap();
let serialized = new_cert.to_string();
let deserialized = Certificate::from_str(&serialized);
@ -309,12 +324,12 @@ mod tests {
}
#[test]
pub fn test_serialization_deserialization() {
pub fn test_serialization_deserialization_ed25519() {
let (_root_kp, second_kp, cert) = generate_root_cert();
let cur_time = current_time();
let third_kp = KeyPair::generate();
let third_kp = KeyPair::generate_ed25519();
let new_cert = Certificate::issue(
&second_kp,
@ -324,7 +339,7 @@ mod tests {
cur_time,
cur_time,
)
.unwrap();
.unwrap();
let serialized = new_cert.encode();
let deserialized = Certificate::decode(serialized.as_slice());
@ -336,7 +351,7 @@ mod tests {
}
#[test]
fn test_small_chain() {
fn test_small_chain_ed25519() {
let bad_cert = Certificate { chain: Vec::new() };
let check = Certificate::verify(&bad_cert, &[], current_time());
@ -344,8 +359,8 @@ mod tests {
}
fn generate_root_cert() -> (KeyPair, KeyPair, Certificate) {
let root_kp = KeyPair::generate();
let second_kp = KeyPair::generate();
let root_kp = KeyPair::generate_ed25519();
let second_kp = KeyPair::generate_ed25519();
let cur_time = current_time();
@ -354,7 +369,7 @@ mod tests {
second_kp.clone(),
Certificate::issue_root(
&root_kp,
second_kp.public_key(),
second_kp.public(),
cur_time.checked_add(one_year()).unwrap(),
cur_time,
),
@ -362,9 +377,9 @@ mod tests {
}
#[test]
fn test_issue_cert() {
fn test_issue_cert_ed25519() {
let (root_kp, second_kp, cert) = generate_root_cert();
let trusted_roots = [root_kp.public_key()];
let trusted_roots = [root_kp.public()];
// we don't need nanos for serialization, etc
let cur_time = Duration::from_secs(
@ -374,7 +389,7 @@ mod tests {
.as_secs() as u64,
);
let third_kp = KeyPair::generate();
let third_kp = KeyPair::generate_ed25519();
let new_cert = Certificate::issue(
&second_kp,
@ -387,37 +402,22 @@ mod tests {
assert_eq!(new_cert.is_ok(), true);
let new_cert = new_cert.unwrap();
println!(
"root_kp:\n\tprivate: {}\n\tpublic: {}",
bs58::encode(root_kp.clone().secret()).into_string(),
bs58::encode(&root_kp.public().to_bytes().to_vec()).into_string()
);
println!(
"second_kp:\n\tprivate: {}\n\tpublic: {}",
bs58::encode(second_kp.clone().secret()).into_string(),
bs58::encode(&second_kp.public().to_bytes().to_vec()).into_string()
);
println!(
"third_kp:\n\tprivate: {}\n\tpublic: {}",
bs58::encode(third_kp.clone().secret()).into_string(),
bs58::encode(&third_kp.public().to_bytes().to_vec()).into_string()
);
println!("cert is\n{}", new_cert.to_string());
assert_eq!(new_cert.chain.len(), 3);
assert_eq!(new_cert.chain[0].issued_for, root_kp.public_key());
assert_eq!(new_cert.chain[1].issued_for, second_kp.public_key());
assert_eq!(new_cert.chain[2].issued_for, third_kp.public_key());
assert_eq!(new_cert.chain[0].issued_for, root_kp.public());
assert_eq!(new_cert.chain[1].issued_for, second_kp.public());
assert_eq!(new_cert.chain[2].issued_for, third_kp.public());
assert!(Certificate::verify(&new_cert, &trusted_roots, cur_time).is_ok());
}
#[test]
fn test_cert_expiration() {
fn test_cert_expiration_ed25519() {
let (root_kp, second_kp, cert) = generate_root_cert();
let trusted_roots = [root_kp.public_key()];
let trusted_roots = [root_kp.public()];
let cur_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
let third_kp = KeyPair::generate();
let third_kp = KeyPair::generate_ed25519();
let new_cert = Certificate::issue(
&second_kp,
@ -427,19 +427,19 @@ mod tests {
cur_time.checked_sub(one_minute()).unwrap(),
cur_time,
)
.unwrap();
.unwrap();
assert!(Certificate::verify(&new_cert, &trusted_roots, cur_time).is_err());
}
#[test]
fn test_issue_in_chain_tail() {
fn test_issue_in_chain_tail_ed25519() {
let (root_kp, second_kp, cert) = generate_root_cert();
let trusted_roots = [root_kp.public_key()];
let trusted_roots = [root_kp.public()];
let cur_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
let third_kp = KeyPair::generate();
let fourth_kp = KeyPair::generate();
let third_kp = KeyPair::generate_ed25519();
let fourth_kp = KeyPair::generate_ed25519();
let new_cert = Certificate::issue(
&second_kp,
@ -449,7 +449,7 @@ mod tests {
cur_time,
cur_time,
)
.unwrap();
.unwrap();
let new_cert = Certificate::issue(
&third_kp,
fourth_kp.public(),
@ -463,21 +463,21 @@ mod tests {
let new_cert = new_cert.unwrap();
assert_eq!(new_cert.chain.len(), 4);
assert_eq!(new_cert.chain[0].issued_for, root_kp.public_key());
assert_eq!(new_cert.chain[1].issued_for, second_kp.public_key());
assert_eq!(new_cert.chain[2].issued_for, third_kp.public_key());
assert_eq!(new_cert.chain[3].issued_for, fourth_kp.public_key());
assert_eq!(new_cert.chain[0].issued_for, root_kp.public());
assert_eq!(new_cert.chain[1].issued_for, second_kp.public());
assert_eq!(new_cert.chain[2].issued_for, third_kp.public());
assert_eq!(new_cert.chain[3].issued_for, fourth_kp.public());
assert!(Certificate::verify(&new_cert, &trusted_roots, cur_time).is_ok());
}
#[test]
fn test_issue_in_chain_body() {
fn test_issue_in_chain_body_ed25519() {
let (root_kp, second_kp, cert) = generate_root_cert();
let trusted_roots = [root_kp.public_key()];
let trusted_roots = [root_kp.public()];
let cur_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
let third_kp = KeyPair::generate();
let fourth_kp = KeyPair::generate();
let third_kp = KeyPair::generate_ed25519();
let fourth_kp = KeyPair::generate_ed25519();
let new_cert = Certificate::issue(
&second_kp,
@ -487,7 +487,7 @@ mod tests {
cur_time,
cur_time,
)
.unwrap();
.unwrap();
let new_cert = Certificate::issue(
&second_kp,
fourth_kp.public(),
@ -501,18 +501,18 @@ mod tests {
let new_cert = new_cert.unwrap();
assert_eq!(new_cert.chain.len(), 3);
assert_eq!(new_cert.chain[0].issued_for, root_kp.public_key());
assert_eq!(new_cert.chain[1].issued_for, second_kp.public_key());
assert_eq!(new_cert.chain[2].issued_for, fourth_kp.public_key());
assert_eq!(new_cert.chain[0].issued_for, root_kp.public());
assert_eq!(new_cert.chain[1].issued_for, second_kp.public());
assert_eq!(new_cert.chain[2].issued_for, fourth_kp.public());
assert!(Certificate::verify(&new_cert, &trusted_roots, cur_time).is_ok());
}
#[test]
fn test_no_cert_in_chain() {
fn test_no_cert_in_chain_ed25519() {
let (_root_kp, _second_kp, cert) = generate_root_cert();
let cur_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
let bad_kp = KeyPair::generate();
let bad_kp = KeyPair::generate_ed25519();
let new_cert_bad = Certificate::issue(
&bad_kp,
bad_kp.public(),
@ -529,7 +529,7 @@ mod tests {
let (_root_kp, second_kp, cert) = generate_root_cert();
let cur_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
let trusted_roots = [second_kp.public_key()];
let trusted_roots = [second_kp.public()];
assert!(Certificate::verify(&cert, &trusted_roots, cur_time).is_err());
assert!(Certificate::verify(&cert, &[], cur_time).is_err());
}
@ -538,7 +538,7 @@ mod tests {
fn test_forged_cert() {
let (root_kp, _second_kp, cert) = generate_root_cert();
let cur_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
let trusted_roots = [root_kp.public_key()];
let trusted_roots = [root_kp.public()];
// forged cert
let mut bad_chain = cert.chain;
@ -553,11 +553,11 @@ mod tests {
let (root_kp, second_kp, cert) = generate_root_cert();
let cur_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
let trusted_roots = [root_kp.public_key()];
let trusted_roots = [root_kp.public()];
assert_eq!(cert.chain.len(), 2);
assert_eq!(cert.chain[0].issued_for, root_kp.public_key());
assert_eq!(cert.chain[1].issued_for, second_kp.public_key());
assert_eq!(cert.chain[0].issued_for, root_kp.public());
assert_eq!(cert.chain[1].issued_for, second_kp.public());
assert!(Certificate::verify(&cert, &trusted_roots, cur_time).is_ok());
}
}

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
use fluence_identity::public_key::{PKError, PublicKey};
use fluence_identity::public_key::PublicKey;
use core::fmt;
use ref_cast::RefCast;
@ -33,7 +33,7 @@ pub struct PublicKeyHashable(PublicKey);
#[allow(clippy::derive_hash_xor_eq)]
impl Hash for PublicKeyHashable {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write(&self.0.to_bytes());
state.write(&self.0.encode());
state.finish();
}
@ -44,7 +44,7 @@ impl Hash for PublicKeyHashable {
// TODO check for overflow
let mut bytes: Vec<u8> = Vec::with_capacity(data.len() * 32);
for d in data {
bytes.extend_from_slice(&d.0.to_bytes())
bytes.extend_from_slice(&d.0.encode())
}
state.write(bytes.as_slice());
state.finish();
@ -77,12 +77,12 @@ impl AsRef<PublicKeyHashable> for PublicKey {
impl Display for PublicKeyHashable {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", bs58::encode(self.0.to_bytes()).into_string())
write!(f, "{}", bs58::encode(self.0.encode()).into_string())
}
}
impl FromStr for PublicKeyHashable {
type Err = PKError;
type Err = fluence_identity::error::DecodingError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let pk = PublicKey::from_base58(s)?;
@ -95,7 +95,7 @@ impl serde::Serialize for PublicKeyHashable {
where
S: Serializer,
{
serializer.serialize_bytes(&self.0.to_bytes())
serializer.serialize_bytes(&self.0.encode())
}
}
@ -132,7 +132,7 @@ impl<'de> serde::Deserialize<'de> for PublicKeyHashable {
where
E: Error,
{
let pk = PublicKey::from_bytes(b)
let pk = PublicKey::decode(b)
.map_err(|err| Error::custom(format!("Invalid bytes {:?}: {}", b, err)))?;
Ok(PublicKeyHashable::from(pk))
}

View File

@ -15,8 +15,6 @@
*/
use crate::revoke::RevokeError::IncorrectSignature;
use crate::trust::{EXPIRATION_LEN, PK_LEN};
use ed25519_dalek::SignatureError;
use fluence_identity::key_pair::KeyPair;
use fluence_identity::public_key::PublicKey;
use fluence_identity::signature::Signature;
@ -27,12 +25,16 @@ use thiserror::Error as ThisError;
#[derive(ThisError, Debug)]
pub enum RevokeError {
#[error("Signature is incorrect: {0}")]
IncorrectSignature(#[source] SignatureError),
IncorrectSignature(
#[from]
#[source]
fluence_identity::error::SigningError
),
}
/// "A document" that cancels trust created before.
/// TODO delete pk from Revoke (it is already in a trust node)
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Revoke {
/// who is revoked
pub pk: PublicKey,
@ -64,14 +66,16 @@ impl Revoke {
#[allow(dead_code)]
pub fn create(revoker: &KeyPair, to_revoke: PublicKey, revoked_at: Duration) -> Self {
let msg = Revoke::signature_bytes(&to_revoke, revoked_at);
let signature = revoker.sign(&msg);
let signature = revoker.sign(&msg).unwrap();
Revoke::new(to_revoke, revoker.public_key(), revoked_at, signature)
Revoke::new(to_revoke, revoker.public(), revoked_at, signature)
}
fn signature_bytes(pk: &PublicKey, revoked_at: Duration) -> Vec<u8> {
let mut msg = Vec::with_capacity(PK_LEN + EXPIRATION_LEN);
msg.extend_from_slice(&pk.to_bytes());
let mut msg = Vec::new();
let pk_bytes = &pk.encode();
msg.push(pk_bytes.len() as u8);
msg.extend(pk_bytes);
msg.extend_from_slice(&(revoked_at.as_secs() as u64).to_le_bytes());
msg
@ -83,41 +87,39 @@ impl Revoke {
revoke
.revoked_by
.verify_strict(msg.as_slice(), &revoke.signature)
.map_err(IncorrectSignature)
.verify(msg.as_slice(), &revoke.signature).map_err(IncorrectSignature)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_gen_revoke_and_validate() {
let revoker = KeyPair::generate();
let to_revoke = KeyPair::generate();
fn test_gen_revoke_and_validate_ed25519() {
let revoker = KeyPair::generate_ed25519();
let to_revoke = KeyPair::generate_ed25519();
let duration = Duration::new(100, 0);
let revoke = Revoke::create(&revoker, to_revoke.public_key(), duration);
let revoke = Revoke::create(&revoker, to_revoke.public(), duration);
assert_eq!(Revoke::verify(&revoke).is_ok(), true);
}
#[test]
fn test_validate_corrupted_revoke() {
let revoker = KeyPair::generate();
let to_revoke = KeyPair::generate();
fn test_validate_corrupted_revoke_ed25519() {
let revoker = KeyPair::generate_ed25519();
let to_revoke = KeyPair::generate_ed25519();
let duration = Duration::new(100, 0);
let revoke = Revoke::create(&revoker, to_revoke.public_key(), duration);
let revoke = Revoke::create(&revoker, to_revoke.public(), duration);
let duration2 = Duration::new(95, 0);
let corrupted_revoke = Revoke::new(
to_revoke.public_key(),
revoker.public_key(),
to_revoke.public(),
revoker.public(),
duration2,
revoke.signature,
);

View File

@ -14,29 +14,23 @@
* limitations under the License.
*/
use crate::trust::TrustError::{
Base58DecodeError, DecodePublicKeyError, IncorrectTrustLength, ParseError, SignatureError,
};
use crate::trust::TrustError::{Base58DecodeError, DecodePublicKeyError, ParseError, SignatureError, DecodeErrorInvalidSize};
use derivative::Derivative;
use fluence_identity::key_pair::KeyPair;
use fluence_identity::public_key::{PKError, PublicKey};
use fluence_identity::signature::{Signature, SignatureError as SigError};
use serde::{Deserialize, Serialize};
use fluence_identity::public_key::PublicKey;
use fluence_identity::signature::Signature;
use std::convert::TryInto;
use std::num::ParseIntError;
use std::time::Duration;
use thiserror::Error as ThisError;
use serde::{Deserialize, Serialize};
pub const SIG_LEN: usize = 64;
pub const PK_LEN: usize = 32;
pub const EXPIRATION_LEN: usize = 8;
pub const ISSUED_LEN: usize = 8;
pub const METADATA_LEN: usize = PK_LEN + EXPIRATION_LEN + ISSUED_LEN;
pub const TRUST_LEN: usize = SIG_LEN + PK_LEN + EXPIRATION_LEN + ISSUED_LEN;
/// One element in chain of trust in a certificate.
/// TODO delete pk from Trust (it is already in a trust node)
#[derive(Clone, PartialEq, Derivative, Eq, Serialize, Deserialize)]
#[derive(Clone, PartialEq, Derivative, Eq, Deserialize, Serialize)]
#[derivative(Debug)]
pub struct Trust {
/// For whom this certificate is issued
@ -53,11 +47,11 @@ pub struct Trust {
}
fn show_pubkey(key: &PublicKey, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
write!(f, "{}", bs58::encode(&key.to_bytes()).into_string())
write!(f, "{}", bs58::encode(&key.encode()).into_string())
}
fn show_sig(sig: &Signature, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
write!(f, "{}", bs58::encode(&sig.to_bytes()).into_string())
write!(f, "{}", bs58::encode(&sig.encode()).into_string())
}
#[derive(ThisError, Debug)]
@ -66,17 +60,17 @@ pub enum TrustError {
#[error("Trust is expired at: '{0:?}', current time: '{1:?}'")]
Expired(Duration, Duration),
/// Errors occured on signature verification
/// Errors occurred on signature verification
#[error("{0}")]
SignatureError(
#[from]
#[source]
ed25519_dalek::SignatureError,
fluence_identity::error::SigningError,
),
/// Errors occured on trust decoding from differrent formats
/// Errors occurred on trust decoding from different formats
#[error("Cannot decode the public key: {0} in the trust: {1}")]
DecodePublicKeyError(String, #[source] PKError),
DecodePublicKeyError(String, #[source] fluence_identity::error::DecodingError),
#[error("Cannot parse `{0}` field in the trust '{1}': {2}")]
ParseError(String, String, #[source] ParseIntError),
@ -84,20 +78,15 @@ pub enum TrustError {
#[error("Cannot decode `{0}` from base58 format in the trust '{1}': {2}")]
Base58DecodeError(String, String, #[source] bs58::decode::Error),
#[error("Cannot decode a signature from bytes: {0}")]
SignatureFromBytesError(#[from] SigError),
#[error("{0}")]
PublicKeyError(
#[from]
#[source]
PKError,
fluence_identity::error::DecodingError,
),
#[error(
"Trust length should be 104: public key(32) + signature(64) + expiration date(8), was: {0}"
)]
IncorrectTrustLength(usize),
#[error("Cannot decode `{0}` field in the trust: invalid size")]
DecodeErrorInvalidSize(String),
}
impl Trust {
@ -124,7 +113,7 @@ impl Trust {
) -> Self {
let msg = Self::metadata_bytes(&issued_for, expires_at, issued_at);
let signature = issued_by.sign(&msg);
let signature = issued_by.sign(msg.as_slice()).unwrap();
Self {
issued_for,
@ -147,22 +136,18 @@ impl Trust {
let msg: &[u8] =
&Self::metadata_bytes(&trust.issued_for, trust.expires_at, trust.issued_at);
KeyPair::verify(issued_by, msg, &trust.signature).map_err(SignatureError)?;
Ok(())
KeyPair::verify(issued_by, msg, &trust.signature).map_err(SignatureError)
}
fn metadata_bytes(pk: &PublicKey, expires_at: Duration, issued_at: Duration) -> [u8; 48] {
let pk_encoded = pk.to_bytes();
fn metadata_bytes(pk: &PublicKey, expires_at: Duration, issued_at: Duration) -> Vec<u8> {
let pk_encoded = pk.encode();
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 mut metadata = [0; METADATA_LEN];
let mut metadata = Vec::new();
metadata[..PK_LEN].clone_from_slice(&pk_encoded[..PK_LEN]);
metadata[PK_LEN..PK_LEN + EXPIRATION_LEN]
.clone_from_slice(&expires_at_encoded[0..EXPIRATION_LEN]);
metadata[PK_LEN + EXPIRATION_LEN..METADATA_LEN]
.clone_from_slice(&issued_at_encoded[0..ISSUED_LEN]);
metadata.extend(pk_encoded);
metadata.extend_from_slice(&expires_at_encoded[0..EXPIRATION_LEN]);
metadata.extend_from_slice(&issued_at_encoded[0..ISSUED_LEN]);
metadata
}
@ -170,32 +155,55 @@ impl Trust {
/// Encode the trust into a byte array
#[allow(dead_code)]
pub fn encode(&self) -> Vec<u8> {
let mut vec = Vec::with_capacity(TRUST_LEN);
vec.extend_from_slice(&self.issued_for.to_bytes());
vec.extend_from_slice(&self.signature.to_bytes());
let mut vec = Vec::new();
let mut issued_for = self.issued_for.encode();
let mut signature = self.signature.encode();
vec.push(issued_for.len() as u8);
vec.append(&mut issued_for);
vec.push(signature.len() as u8);
vec.append(&mut signature);
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
}
fn check_arr_len(arr: &[u8], field_name: &str, check_len: usize) -> Result<(), TrustError> {
if arr.len() < check_len {
Err(DecodeErrorInvalidSize(field_name.to_string()))
} else {
Ok(())
}
}
/// Decode a trust from a byte array as produced by `encode`.
#[allow(dead_code)]
pub fn decode(arr: &[u8]) -> Result<Self, TrustError> {
if arr.len() != TRUST_LEN {
return Err(IncorrectTrustLength(arr.len()));
}
Self::check_arr_len(arr, "public_key_len", 1)?;
let pk_len = arr[0] as usize;
let mut offset = 1;
let pk = PublicKey::from_bytes(&arr[0..PK_LEN])?;
Self::check_arr_len(arr, "public_key", offset + pk_len)?;
let pk = PublicKey::decode(&arr[offset..offset + pk_len])?;
offset += pk_len;
let signature = &arr[PK_LEN..PK_LEN + SIG_LEN];
let signature = Signature::from_bytes(signature)?;
Self::check_arr_len(arr, "signature_size", offset + 1)?;
let signature_len = arr[offset] as usize;
offset += 1;
let expiration_bytes = &arr[PK_LEN + SIG_LEN..PK_LEN + SIG_LEN + EXPIRATION_LEN];
Self::check_arr_len(arr, "signature", offset + signature_len)?;
let signature = &arr[offset..offset + signature_len];
let signature = Signature::decode(signature.to_vec())?;
offset += signature_len;
Self::check_arr_len(arr, "expiration", offset + EXPIRATION_LEN)?;
let expiration_bytes = &arr[offset..offset + EXPIRATION_LEN];
let expiration_date = u64::from_le_bytes(expiration_bytes.try_into().unwrap());
let expiration_date = Duration::from_secs(expiration_date);
offset += EXPIRATION_LEN;
let issued_bytes = &arr[PK_LEN + SIG_LEN + EXPIRATION_LEN..TRUST_LEN];
Self::check_arr_len(arr, "issued", offset + ISSUED_LEN)?;
let issued_bytes = &arr[offset..];
let issued_date = u64::from_le_bytes(issued_bytes.try_into().unwrap());
let issued_date = Duration::from_secs(issued_date);
@ -228,12 +236,12 @@ impl Trust {
) -> Result<Self, TrustError> {
// PublicKey
let issued_for_bytes = Self::bs58_str_to_vec(issued_for, "issued_for")?;
let issued_for = PublicKey::from_bytes(issued_for_bytes.as_slice())
let issued_for = PublicKey::decode(&issued_for_bytes)
.map_err(|e| DecodePublicKeyError(issued_for.to_string(), e))?;
// 64 bytes signature
let signature = Self::bs58_str_to_vec(signature, "signature")?;
let signature = Signature::from_bytes(&signature)?;
let signature = Signature::decode(signature.to_vec())?;
// Duration
let expires_at = Self::str_to_duration(expires_at, "expires_at")?;
@ -247,8 +255,8 @@ impl Trust {
impl ToString for Trust {
fn to_string(&self) -> String {
let issued_for = bs58::encode(self.issued_for.to_bytes()).into_string();
let signature = bs58::encode(self.signature.to_bytes()).into_string();
let issued_for = bs58::encode(self.issued_for.encode()).into_string();
let signature = bs58::encode(self.signature.encode()).into_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();
@ -264,31 +272,31 @@ mod tests {
use super::*;
#[test]
fn test_gen_revoke_and_validate() {
let truster = KeyPair::generate();
let trusted = KeyPair::generate();
fn test_gen_revoke_and_validate_ed25519() {
let truster = KeyPair::generate_ed25519();
let trusted = KeyPair::generate_ed25519();
let current = Duration::new(100, 0);
let duration = Duration::new(1000, 0);
let issued_at = Duration::new(10, 0);
let trust = Trust::create(&truster, trusted.public_key(), duration, issued_at);
let trust = Trust::create(&truster, trusted.public(), duration, issued_at);
assert_eq!(
Trust::verify(&trust, &truster.public_key(), current).is_ok(),
Trust::verify(&trust, &truster.public(), current).is_ok(),
true
);
}
#[test]
fn test_validate_corrupted_revoke() {
let truster = KeyPair::generate();
let trusted = KeyPair::generate();
fn test_validate_corrupted_revoke_ed25519() {
let truster = KeyPair::generate_ed25519();
let trusted = KeyPair::generate_ed25519();
let current = Duration::new(1000, 0);
let issued_at = Duration::new(10, 0);
let trust = Trust::create(&truster, trusted.public_key(), current, issued_at);
let trust = Trust::create(&truster, trusted.public(), current, issued_at);
let corrupted_duration = Duration::new(1234, 0);
let corrupted_trust = Trust::new(
@ -298,18 +306,18 @@ mod tests {
trust.signature,
);
assert!(Trust::verify(&corrupted_trust, &truster.public_key(), current).is_err());
assert!(Trust::verify(&corrupted_trust, &truster.public(), current).is_err());
}
#[test]
fn test_encode_decode() {
let truster = KeyPair::generate();
let trusted = KeyPair::generate();
fn test_encode_decode_ed25519() {
let truster = KeyPair::generate_ed25519();
let trusted = KeyPair::generate_ed25519();
let current = Duration::new(1000, 0);
let issued_at = Duration::new(10, 0);
let trust = Trust::create(&truster, trusted.public_key(), current, issued_at);
let trust = Trust::create(&truster, trusted.public(), current, issued_at);
let encoded = trust.encode();
let decoded = Trust::decode(encoded.as_slice()).unwrap();

View File

@ -123,10 +123,10 @@ where
// Insert new TrustNode for this root_pk if there wasn't one
if self.storage.get(&root_pk)?.is_none() {
let mut trust_node = TrustNode::new(root_trust.issued_for, cur_time);
let mut trust_node = TrustNode::new(root_trust.issued_for.clone(), cur_time);
let root_auth = Auth {
trust: root_trust.clone(),
issued_by: root_trust.issued_for,
issued_by: root_trust.issued_for.clone(),
};
trust_node.update_auth(root_auth);
self.storage.insert(root_pk, trust_node)?;
@ -139,7 +139,7 @@ where
let auth = Auth {
trust: trust.clone(),
issued_by: previous_trust.issued_for,
issued_by: previous_trust.issued_for.clone(),
};
self.storage
@ -169,7 +169,7 @@ where
// get all possible certificates from the given public key to all roots in the graph
let certs = self.get_all_certs(pk, roots.as_slice())?;
Ok(self.certificates_weight(certs)?)
self.certificates_weight(certs)
}
/// Calculate weight from given certificates
@ -347,8 +347,8 @@ mod tests {
}
fn generate_root_cert() -> (KeyPair, KeyPair, Certificate) {
let root_kp = KeyPair::generate();
let second_kp = KeyPair::generate();
let root_kp = KeyPair::generate_ed25519();
let second_kp = KeyPair::generate_ed25519();
let cur_time = current_time();
@ -357,7 +357,7 @@ mod tests {
second_kp.clone(),
Certificate::issue_root(
&root_kp,
second_kp.public_key(),
second_kp.public(),
cur_time.checked_add(one_minute()).unwrap(),
cur_time,
),
@ -373,20 +373,20 @@ mod tests {
) -> Result<(Vec<KeyPair>, Certificate), TrustGraphError> {
assert!(len > 2);
let root_kp = KeyPair::generate();
let second_kp = KeyPair::generate();
let root_kp = KeyPair::generate_ed25519();
let second_kp = KeyPair::generate_ed25519();
let mut cert =
Certificate::issue_root(&root_kp, second_kp.public_key(), expires_at, issued_at);
Certificate::issue_root(&root_kp, second_kp.public(), expires_at, issued_at);
let mut key_pairs = vec![root_kp, second_kp];
for idx in 2..len {
let kp = keys.get(&idx).unwrap_or(&KeyPair::generate()).clone();
let kp = keys.get(&idx).unwrap_or(&KeyPair::generate_ed25519()).clone();
let previous_kp = &key_pairs[idx - 1];
cert = Certificate::issue(
&previous_kp,
kp.public_key(),
kp.public(),
&cert,
expires_at,
// TODO: why `issued_at = issued_at - 60 seconds`?
@ -434,12 +434,12 @@ mod tests {
}
#[test]
fn test_add_certs_with_same_trusts_and_different_expirations() {
fn test_add_certs_with_same_trusts_and_different_expirations_ed25519() {
let cur_time = current_time();
let far_future = cur_time + Duration::from_secs(10);
let far_far_future = cur_time + Duration::from_secs(900);
let key_pair1 = KeyPair::generate();
let key_pair2 = KeyPair::generate();
let key_pair1 = KeyPair::generate_ed25519();
let key_pair2 = KeyPair::generate_ed25519();
// Use key_pair1 and key_pair2 for 5th and 6th trust in the cert chain
let mut chain_keys = HashMap::new();
@ -459,26 +459,26 @@ mod tests {
let st = InMemoryStorage::new();
let mut graph = TrustGraph::new(st);
let root1_pk = key_pairs1[0].public_key();
let root2_pk = key_pairs2[0].public_key();
let root1_pk = key_pairs1[0].public();
let root2_pk = key_pairs2[0].public();
graph.add_root_weight(root1_pk.into(), 1).unwrap();
graph.add_root_weight(root2_pk.into(), 0).unwrap();
graph.add(cert1, cur_time).unwrap();
let node2 = graph.get(key_pair2.public_key()).unwrap().unwrap();
let node2 = graph.get(key_pair2.public()).unwrap().unwrap();
let auth_by_kp1 = node2
.authorizations()
.find(|a| a.issued_by == key_pair1.public_key())
.find(|a| a.issued_by == key_pair1.public())
.unwrap();
assert_eq!(auth_by_kp1.trust.expires_at, far_future * 2);
graph.add(cert2, cur_time).unwrap();
let node2 = graph.get(key_pair2.public_key()).unwrap().unwrap();
let node2 = graph.get(key_pair2.public()).unwrap().unwrap();
let auth_by_kp1 = node2
.authorizations()
.find(|a| a.issued_by == key_pair1.public_key())
.find(|a| a.issued_by == key_pair1.public())
.unwrap();
assert_eq!(auth_by_kp1.trust.expires_at, far_far_future * 2);
@ -492,21 +492,21 @@ mod tests {
let st = InMemoryStorage::new();
let mut graph = TrustGraph::new(st);
let root_pk = key_pairs[0].public_key();
let root_pk = key_pairs[0].public();
graph.add_root_weight(root_pk.into(), 1).unwrap();
graph.add(cert1, current_time()).unwrap();
let w1 = graph.weight(key_pairs[0].public_key()).unwrap().unwrap();
let w1 = graph.weight(key_pairs[0].public()).unwrap().unwrap();
assert_eq!(w1, 1);
let w2 = graph.weight(key_pairs[1].public_key()).unwrap().unwrap();
let w2 = graph.weight(key_pairs[1].public()).unwrap().unwrap();
assert_eq!(w2, 2);
let w3 = graph.weight(key_pairs[9].public_key()).unwrap().unwrap();
let w3 = graph.weight(key_pairs[9].public()).unwrap().unwrap();
assert_eq!(w3, 10);
let node = graph.get(key_pairs[9].public_key()).unwrap().unwrap();
let node = graph.get(key_pairs[9].public()).unwrap().unwrap();
let auths: Vec<&Auth> = node.authorizations().collect();
assert_eq!(auths.len(), 1);
@ -515,9 +515,9 @@ mod tests {
#[test]
fn test_cycles_in_graph() {
let key_pair1 = KeyPair::generate();
let key_pair2 = KeyPair::generate();
let key_pair3 = KeyPair::generate();
let key_pair1 = KeyPair::generate_ed25519();
let key_pair2 = KeyPair::generate_ed25519();
let key_pair3 = KeyPair::generate_ed25519();
let mut chain_keys = HashMap::new();
chain_keys.insert(3, key_pair1.clone());
@ -535,8 +535,8 @@ mod tests {
let st = InMemoryStorage::new();
let mut graph = TrustGraph::new(st);
let root1_pk = key_pairs1[0].public_key();
let root2_pk = key_pairs2[0].public_key();
let root1_pk = key_pairs1[0].public();
let root2_pk = key_pairs2[0].public();
graph.add_root_weight(root1_pk.into(), 1).unwrap();
graph.add_root_weight(root2_pk.into(), 0).unwrap();
@ -546,15 +546,15 @@ mod tests {
graph.add(cert1, current_time()).unwrap();
graph.add(cert2, current_time()).unwrap();
let revoke1 = Revoke::create(&key_pairs1[3], key_pairs1[4].public_key(), current_time());
let revoke1 = Revoke::create(&key_pairs1[3], key_pairs1[4].public(), current_time());
graph.revoke(revoke1).unwrap();
let revoke2 = Revoke::create(&key_pairs2[5], key_pairs2[6].public_key(), current_time());
let revoke2 = Revoke::create(&key_pairs2[5], key_pairs2[6].public(), current_time());
graph.revoke(revoke2).unwrap();
let w1 = graph.weight(key_pair1.public_key()).unwrap().unwrap();
let w1 = graph.weight(key_pair1.public()).unwrap().unwrap();
// all upper trusts are revoked for this public key
let w2 = graph.weight(key_pair2.public_key()).unwrap();
let w3 = graph.weight(key_pair3.public_key()).unwrap().unwrap();
let w2 = graph.weight(key_pair2.public()).unwrap();
let w3 = graph.weight(key_pair3.public()).unwrap().unwrap();
let w_last1 = graph.weight(last_pk1).unwrap().unwrap();
let w_last2 = graph.weight(last_pk2).unwrap().unwrap();
@ -571,13 +571,13 @@ mod tests {
let st = InMemoryStorage::new();
let mut graph = TrustGraph::new(st);
let root1_pk = key_pairs[0].public_key();
let root1_pk = key_pairs[0].public();
graph.add_root_weight(root1_pk.clone().into(), 1).unwrap();
graph.add(cert.clone(), current_time()).unwrap();
let certs = graph
.get_all_certs(key_pairs.last().unwrap().public_key(), &[root1_pk])
.get_all_certs(key_pairs.last().unwrap().public(), &[root1_pk])
.unwrap();
assert_eq!(certs.len(), 1);
@ -605,9 +605,9 @@ mod tests {
#[test]
fn test_find_certs() {
let key_pair1 = KeyPair::generate();
let key_pair2 = KeyPair::generate();
let key_pair3 = KeyPair::generate();
let key_pair1 = KeyPair::generate_ed25519();
let key_pair2 = KeyPair::generate_ed25519();
let key_pair3 = KeyPair::generate_ed25519();
let mut chain_keys = HashMap::new();
chain_keys.insert(2, key_pair1.clone());
@ -632,9 +632,9 @@ mod tests {
let st = InMemoryStorage::new();
let mut graph = TrustGraph::new(st);
let root1_pk = key_pairs1[0].public_key();
let root2_pk = key_pairs2[0].public_key();
let root3_pk = key_pairs3[0].public_key();
let root1_pk = key_pairs1[0].public();
let root2_pk = key_pairs2[0].public();
let root3_pk = key_pairs3[0].public();
graph.add_root_weight(root1_pk.clone().into(), 1).unwrap();
graph.add_root_weight(root2_pk.clone().into(), 0).unwrap();
graph.add_root_weight(root3_pk.clone().into(), 0).unwrap();
@ -646,21 +646,21 @@ mod tests {
let roots_values = [root1_pk, root2_pk, root3_pk];
let certs1 = graph
.get_all_certs(key_pair1.public_key(), &roots_values)
.get_all_certs(key_pair1.public(), &roots_values)
.unwrap();
let lenghts1: Vec<usize> = certs1.iter().map(|c| c.chain.len()).collect();
let check_lenghts1: Vec<usize> = vec![3, 4, 4, 5, 5];
assert_eq!(lenghts1, check_lenghts1);
let certs2 = graph
.get_all_certs(key_pair2.public_key(), &roots_values)
.get_all_certs(key_pair2.public(), &roots_values)
.unwrap();
let lenghts2: Vec<usize> = certs2.iter().map(|c| c.chain.len()).collect();
let check_lenghts2: Vec<usize> = vec![4, 4, 4, 5, 5];
assert_eq!(lenghts2, check_lenghts2);
let certs3 = graph
.get_all_certs(key_pair3.public_key(), &roots_values)
.get_all_certs(key_pair3.public(), &roots_values)
.unwrap();
let lenghts3: Vec<usize> = certs3.iter().map(|c| c.chain.len()).collect();
let check_lenghts3: Vec<usize> = vec![3, 3, 5];

View File

@ -116,7 +116,7 @@ impl Storage for InMemoryStorage {
Ok(())
}
None => {
let mut trust_node = TrustNode::new(*issued_for, cur_time);
let mut trust_node = TrustNode::new(issued_for.clone(), cur_time);
trust_node.update_auth(auth);
self.nodes.insert(pk.clone(), trust_node);
Ok(())

View File

@ -160,47 +160,47 @@ mod tests {
#[test]
fn test_auth_and_revoke_trust_node() {
let kp = KeyPair::generate();
let kp = KeyPair::generate_ed25519();
let now = Duration::new(50, 0);
let past = Duration::new(5, 0);
let future = Duration::new(500, 0);
let mut trust_node = TrustNode {
pk: kp.public_key(),
pk: kp.public(),
trust_relations: HashMap::new(),
verified_at: now,
};
let truster = KeyPair::generate();
let truster = KeyPair::generate_ed25519();
let revoke = Revoke::create(&truster, kp.public_key(), now);
let revoke = Revoke::create(&truster, kp.public(), now);
trust_node.update_revoke(revoke);
assert!(trust_node.get_revoke(truster.public_key()).is_some());
assert!(trust_node.get_revoke(truster.public()).is_some());
let old_trust = Trust::create(&truster, kp.public_key(), Duration::new(60, 0), past);
let old_trust = Trust::create(&truster, kp.public(), Duration::new(60, 0), past);
let old_auth = Auth {
trust: old_trust,
issued_by: truster.public_key(),
issued_by: truster.public(),
};
trust_node.update_auth(old_auth);
assert!(trust_node.get_revoke(truster.public_key()).is_some());
assert!(trust_node.get_auth(truster.public_key()).is_none());
assert!(trust_node.get_revoke(truster.public()).is_some());
assert!(trust_node.get_auth(truster.public()).is_none());
let trust = Trust::create(&truster, kp.public_key(), Duration::new(60, 0), future);
let trust = Trust::create(&truster, kp.public(), Duration::new(60, 0), future);
let auth = Auth {
trust,
issued_by: truster.public_key(),
issued_by: truster.public(),
};
trust_node.update_auth(auth);
assert!(trust_node.get_auth(truster.public_key()).is_some());
assert!(trust_node.get_revoke(truster.public_key()).is_none());
assert!(trust_node.get_auth(truster.public()).is_some());
assert!(trust_node.get_revoke(truster.public()).is_none());
}
}