Fix revocations logic (#34)

This commit is contained in:
Aleksey Proshutisnkiy 2021-12-13 19:40:16 +03:00 committed by GitHub
parent c4019127e8
commit 8214b1cc5c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 320 additions and 382 deletions

130
Cargo.lock generated
View File

@ -39,9 +39,9 @@ dependencies = [
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.45" version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee10e43ae4a853c0a3591d4e2ada1719e553be18199d9da9d4a83f5927c2f5c7" checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203"
[[package]] [[package]]
name = "arrayref" name = "arrayref"
@ -529,9 +529,9 @@ dependencies = [
[[package]] [[package]]
name = "ed25519" name = "ed25519"
version = "1.2.0" version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4620d40f6d2601794401d6dd95a5cf69b6c157852539470eeda433a99b3c0efc" checksum = "74e1069e39f1454367eb2de793ed062fac4c35c2934b76a81d90dd9abcd28816"
dependencies = [ dependencies = [
"serde", "serde",
"signature", "signature",
@ -656,9 +656,9 @@ checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
[[package]] [[package]]
name = "fluence-app-service" name = "fluence-app-service"
version = "0.9.0" version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58d92fd37b7673513efafb0d1e0c366b8d6f297b74e9bfcda27c452f400af70a" checksum = "01c66660de99826038c5ec4ad0f5dccf10b1c8a15924aeaa5315ab49d718bfc9"
dependencies = [ dependencies = [
"fluence-faas", "fluence-faas",
"log", "log",
@ -819,9 +819,9 @@ dependencies = [
[[package]] [[package]]
name = "futures" name = "futures"
version = "0.3.17" version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca" checksum = "8cd0210d8c325c245ff06fd95a3b13689a1a276ac8cfa8e8720cb840bfb84b9e"
dependencies = [ dependencies = [
"futures-channel", "futures-channel",
"futures-core", "futures-core",
@ -834,9 +834,9 @@ dependencies = [
[[package]] [[package]]
name = "futures-channel" name = "futures-channel"
version = "0.3.17" version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888" checksum = "7fc8cd39e3dbf865f7340dce6a2d401d24fd37c6fe6c4f0ee0de8bfca2252d27"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-sink", "futures-sink",
@ -844,15 +844,15 @@ dependencies = [
[[package]] [[package]]
name = "futures-core" name = "futures-core"
version = "0.3.17" version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d" checksum = "629316e42fe7c2a0b9a65b47d159ceaa5453ab14e8f0a3c5eedbb8cd55b4a445"
[[package]] [[package]]
name = "futures-executor" name = "futures-executor"
version = "0.3.17" version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c" checksum = "7b808bf53348a36cab739d7e04755909b9fcaaa69b7d7e588b37b6ec62704c97"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-task", "futures-task",
@ -862,18 +862,16 @@ dependencies = [
[[package]] [[package]]
name = "futures-io" name = "futures-io"
version = "0.3.17" version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377" checksum = "e481354db6b5c353246ccf6a728b0c5511d752c08da7260546fc0933869daa11"
[[package]] [[package]]
name = "futures-macro" name = "futures-macro"
version = "0.3.17" version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb" checksum = "a89f17b21645bc4ed773c69af9c9a0effd4a3f1a3876eadd453469f8854e7fdd"
dependencies = [ dependencies = [
"autocfg",
"proc-macro-hack",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn",
@ -881,15 +879,15 @@ dependencies = [
[[package]] [[package]]
name = "futures-sink" name = "futures-sink"
version = "0.3.17" version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11" checksum = "996c6442437b62d21a32cd9906f9c41e7dc1e19a9579843fad948696769305af"
[[package]] [[package]]
name = "futures-task" name = "futures-task"
version = "0.3.17" version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99" checksum = "dabf1872aaab32c886832f2276d2f5399887e2bd613698a02359e4ea83f8de12"
[[package]] [[package]]
name = "futures-timer" name = "futures-timer"
@ -899,11 +897,10 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c"
[[package]] [[package]]
name = "futures-util" name = "futures-util"
version = "0.3.17" version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481" checksum = "41d22213122356472061ac0f1ab2cee28d2bac8491410fd68c2af53d1cedb83e"
dependencies = [ dependencies = [
"autocfg",
"futures-channel", "futures-channel",
"futures-core", "futures-core",
"futures-io", "futures-io",
@ -913,8 +910,6 @@ dependencies = [
"memchr", "memchr",
"pin-project-lite", "pin-project-lite",
"pin-utils", "pin-utils",
"proc-macro-hack",
"proc-macro-nested",
"slab", "slab",
] ]
@ -1147,9 +1142,9 @@ dependencies = [
[[package]] [[package]]
name = "itertools" name = "itertools"
version = "0.10.1" version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
dependencies = [ dependencies = [
"either", "either",
] ]
@ -1196,9 +1191,9 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.107" version = "0.2.109"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbe5e23404da5b4f555ef85ebed98fb4083e55a00c317800bc2a50ede9f3d219" checksum = "f98a04dce437184842841303488f70d0188c5f51437d2a834dc097eafa909a01"
[[package]] [[package]]
name = "libsecp256k1" name = "libsecp256k1"
@ -1261,9 +1256,9 @@ checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
[[package]] [[package]]
name = "marine-build-rs-generator" name = "marine-build-rs-generator"
version = "0.4.0" version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c81d725ea49f554e23d3a0eb9464fcdad0bc190e42bb5a5a27699fb56557177c" checksum = "0108407ef0528984cd5b226e6d69552b1658b205f60c83305ca33179d6e9eee1"
dependencies = [ dependencies = [
"marine-test-macro-impl", "marine-test-macro-impl",
] ]
@ -1303,7 +1298,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edd97bd85072fc540763769be153a7c8ee83391e668b37ef96d6c48decec2cd5" checksum = "edd97bd85072fc540763769be153a7c8ee83391e668b37ef96d6c48decec2cd5"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"itertools 0.10.1", "itertools 0.10.3",
"marine-it-interfaces", "marine-it-interfaces",
"marine-module-interface", "marine-module-interface",
"nom", "nom",
@ -1362,7 +1357,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06bc36ef268bf7436916f1fa9b0c84104692a717ea5eef3c90b9f25c3407f6b7" checksum = "06bc36ef268bf7436916f1fa9b0c84104692a717ea5eef3c90b9f25c3407f6b7"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"itertools 0.10.1", "itertools 0.10.3",
"marine-it-interfaces", "marine-it-interfaces",
"nom", "nom",
"semver 0.11.0", "semver 0.11.0",
@ -1398,9 +1393,9 @@ dependencies = [
[[package]] [[package]]
name = "marine-rs-sdk-test" name = "marine-rs-sdk-test"
version = "0.4.0" version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe77591c893dcfda3acd02b89ad42102a6739ead8200717e4cf325c52ba7001e" checksum = "03e286a347527936cf97456b928bd6271e0d39fc1c6b78e99461f00e6d74f018"
dependencies = [ dependencies = [
"fluence-app-service", "fluence-app-service",
"marine-build-rs-generator", "marine-build-rs-generator",
@ -1451,9 +1446,9 @@ dependencies = [
[[package]] [[package]]
name = "marine-test-macro" name = "marine-test-macro"
version = "0.4.0" version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c73a012946439eb619375cc825f008ac74489092f826fe596e465d355542cf" checksum = "bf4d0463358f6c2459089ef8f130983dc911fd0c2aa4cb7c6b59de206f4a816e"
dependencies = [ dependencies = [
"marine-test-macro-impl", "marine-test-macro-impl",
"proc-macro-error", "proc-macro-error",
@ -1464,13 +1459,13 @@ dependencies = [
[[package]] [[package]]
name = "marine-test-macro-impl" name = "marine-test-macro-impl"
version = "0.4.0" version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa833b78d05abb43ca46c2c85cce1e664bde4b8b1926ae2bd420aba426a9b22a" checksum = "b8f4f1ae0ba20e9241e8882e6eb1b2302daa479d67eee5badb54b1520e17c0cb"
dependencies = [ dependencies = [
"darling 0.12.4", "darling 0.12.4",
"fluence-app-service", "fluence-app-service",
"itertools 0.10.1", "itertools 0.10.3",
"marine-it-parser", "marine-it-parser",
"proc-macro-error", "proc-macro-error",
"proc-macro2", "proc-macro2",
@ -1520,9 +1515,9 @@ dependencies = [
[[package]] [[package]]
name = "memoffset" name = "memoffset"
version = "0.6.4" version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
dependencies = [ dependencies = [
"autocfg", "autocfg",
] ]
@ -1597,6 +1592,12 @@ dependencies = [
"version_check", "version_check",
] ]
[[package]]
name = "nonempty"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7"
[[package]] [[package]]
name = "num-integer" name = "num-integer"
version = "0.1.44" version = "0.1.44"
@ -1803,9 +1804,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]] [[package]]
name = "pkg-config" name = "pkg-config"
version = "0.3.22" version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12295df4f294471248581bc09bef3c38a5e46f1e36d6a37353621a0c6c357e1f" checksum = "d1a3ea4f0dd7f1f3e512cf97bf100819aa547f36a6eccac8dbaae839eb92363e"
[[package]] [[package]]
name = "polyplets" name = "polyplets"
@ -1858,23 +1859,11 @@ dependencies = [
"version_check", "version_check",
] ]
[[package]]
name = "proc-macro-hack"
version = "0.5.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]]
name = "proc-macro-nested"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.32" version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" checksum = "fb37d2df5df740e582f28f8560cf425f52bb267d872fe58358eadb554909f07a"
dependencies = [ dependencies = [
"unicode-xid", "unicode-xid",
] ]
@ -2219,9 +2208,9 @@ dependencies = [
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.5" version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" checksum = "3c9613b5a66ab9ba26415184cfc41156594925a9cf3a2057e57f31ff145f6568"
[[package]] [[package]]
name = "safe-transmute" name = "safe-transmute"
@ -2319,9 +2308,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.69" version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e466864e431129c7e0d3476b92f20458e5879919a0596c6472738d9fa2d342f8" checksum = "d0ffa0837f2dfa6fb90868c2b5468cad482e175f7dad97e7421951e663f2b527"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@ -2425,9 +2414,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.81" version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966" checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2531,6 +2520,7 @@ dependencies = [
"fluence-fork-libp2p-core", "fluence-fork-libp2p-core",
"fluence-keypair", "fluence-keypair",
"log", "log",
"nonempty",
"rand 0.7.3", "rand 0.7.3",
"ref-cast", "ref-cast",
"serde", "serde",
@ -2543,7 +2533,7 @@ dependencies = [
[[package]] [[package]]
name = "trust-graph-wasm" name = "trust-graph-wasm"
version = "0.2.1" version = "0.3.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bincode", "bincode",
@ -2848,7 +2838,7 @@ dependencies = [
"fluence-it-types", "fluence-it-types",
"it-lilo", "it-lilo",
"it-to-bytes", "it-to-bytes",
"itertools 0.10.1", "itertools 0.10.3",
"log", "log",
"nom", "nom",
"safe-transmute", "safe-transmute",

View File

@ -23,6 +23,7 @@ serde_with = "1.6.0"
thiserror = "1.0.23" thiserror = "1.0.23"
sha2 = "0.9.5" sha2 = "0.9.5"
rand = "0.7.0" rand = "0.7.0"
nonempty = "0.7.0"
[workspace] [workspace]
members = [ members = [

View File

@ -1,6 +1,6 @@
{ {
"name": "@fluencelabs/trust-graph", "name": "@fluencelabs/trust-graph",
"version": "0.1.12", "version": "0.2.0",
"description": "Aqua Trust Graph API library", "description": "Aqua Trust Graph API library",
"files": [ "files": [
"*.aqua" "*.aqua"

View File

@ -67,10 +67,10 @@ func issue_revocation(node: string, revoked_peer_id: string, revoked_by_peer_id:
result <- TrustGraph.issue_revocation(revoked_peer_id, revoked_by_peer_id, revoked_at_sec, signature_bytes) result <- TrustGraph.issue_revocation(revoked_peer_id, revoked_by_peer_id, revoked_at_sec, signature_bytes)
<- result <- result
func revoke(node: string, revoke: Revoke) -> RevokeResult: func revoke(node: string, revocation: Revocation) -> RevokeResult:
on node: on node:
timestamp_sec <- Peer.timestamp_sec() timestamp_sec <- Peer.timestamp_sec()
result <- TrustGraph.revoke(revoke, timestamp_sec) result <- TrustGraph.revoke(revocation, timestamp_sec)
<- result <- result
service TrustOp("op"): service TrustOp("op"):

View File

@ -38,7 +38,7 @@ data InsertResult:
success: bool success: bool
error: string error: string
data Revoke: data Revocation:
revoked_peer_id: string revoked_peer_id: string
revoked_at: u64 revoked_at: u64
signature: string signature: string
@ -48,7 +48,7 @@ data Revoke:
data IssueRevocationResult: data IssueRevocationResult:
success: bool success: bool
error: string error: string
revoke: Revoke revocation: Revocation
data IssueTrustResult: data IssueTrustResult:
success: bool success: bool
@ -83,5 +83,5 @@ service TrustGraph("trust-graph"):
insert_cert_raw(certificate: string, timestamp_sec: u64) -> InsertResult insert_cert_raw(certificate: string, timestamp_sec: u64) -> InsertResult
issue_revocation(revoked_peer_id: string, revoked_by_peer_id: string, revoked_at_sec: u64, signature_bytes: []u8) -> IssueRevocationResult issue_revocation(revoked_peer_id: string, revoked_by_peer_id: string, revoked_at_sec: u64, signature_bytes: []u8) -> IssueRevocationResult
issue_trust(issued_for_peer_id: string, expires_at_sec: u64, issued_at_sec: u64, trust_bytes: []u8) -> IssueTrustResult issue_trust(issued_for_peer_id: string, expires_at_sec: u64, issued_at_sec: u64, trust_bytes: []u8) -> IssueTrustResult
revoke(revoke: Revoke, timestamp_sec: u64) -> RevokeResult revoke(revoke: Revocation, timestamp_sec: u64) -> RevokeResult
verify_trust(trust: Trust, issuer_peer_id: string, timestamp_sec: u64) -> VerifyTrustResult verify_trust(trust: Trust, issuer_peer_id: string, timestamp_sec: u64) -> VerifyTrustResult

View File

@ -65,7 +65,7 @@ async function revoke_helper(node: string, issuer_kp: KeyPair, revoked_by_peer_i
let revocation = await tg.issue_revocation(node, revoked_peer_id, revoked_by_peer_id, revoked_at_sec, Array.from(signed_metadata)); let revocation = await tg.issue_revocation(node, revoked_peer_id, revoked_by_peer_id, revoked_at_sec, Array.from(signed_metadata));
assert(revocation.success) assert(revocation.success)
let result_add = await tg.revoke(node, revocation.revoke); let result_add = await tg.revoke(node, revocation.revocation);
assert(result_add.success) assert(result_add.success)
} }

View File

@ -43,7 +43,7 @@ impl Keypair {
/// ///
/// [RFC5208]: https://tools.ietf.org/html/rfc5208#section-5 /// [RFC5208]: https://tools.ietf.org/html/rfc5208#section-5
pub fn from_pkcs8(der: &mut [u8]) -> Result<Self, DecodingError> { pub fn from_pkcs8(der: &mut [u8]) -> Result<Self, DecodingError> {
let kp = RsaKeyPair::from_pkcs8(&der).map_err(|_| DecodingError::Rsa)?; let kp = RsaKeyPair::from_pkcs8(der).map_err(|_| DecodingError::Rsa)?;
der.zeroize(); der.zeroize();
Ok(Keypair(Arc::new(kp))) Ok(Keypair(Arc::new(kp)))
} }
@ -57,7 +57,7 @@ impl Keypair {
pub fn sign(&self, data: &[u8]) -> Result<Vec<u8>, SigningError> { pub fn sign(&self, data: &[u8]) -> Result<Vec<u8>, SigningError> {
let mut signature = vec![0; self.0.public_modulus_len()]; let mut signature = vec![0; self.0.public_modulus_len()];
let rng = SystemRandom::new(); let rng = SystemRandom::new();
match self.0.sign(&RSA_PKCS1_SHA256, &rng, &data, &mut signature) { match self.0.sign(&RSA_PKCS1_SHA256, &rng, data, &mut signature) {
Ok(()) => Ok(signature), Ok(()) => Ok(signature),
Err(_) => Err(SigningError::Rsa), Err(_) => Err(SigningError::Rsa),
} }

View File

@ -98,7 +98,7 @@ impl Signature {
pub fn get_raw_signature(&self) -> RawSignature { pub fn get_raw_signature(&self) -> RawSignature {
RawSignature { RawSignature {
bytes: self.to_vec().clone().to_vec(), bytes: self.to_vec().to_vec(),
sig_type: self.get_signature_type(), sig_type: self.get_signature_type(),
} }
} }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "trust-graph-wasm" name = "trust-graph-wasm"
version = "0.2.1" version = "0.3.0"
authors = ["Fluence Labs"] authors = ["Fluence Labs"]
edition = "2018" edition = "2018"
description = "trust graph wasm" description = "trust graph wasm"

View File

@ -113,7 +113,7 @@ impl From<trust_graph::Trust> for Trust {
#[marine] #[marine]
#[derive(Default)] #[derive(Default)]
pub struct Revoke { pub struct Revocation {
/// who is revoked /// who is revoked
pub revoked_peer_id: String, pub revoked_peer_id: String,
/// date when revocation was created /// date when revocation was created
@ -126,10 +126,10 @@ pub struct Revoke {
pub revoked_by: String, pub revoked_by: String,
} }
impl TryFrom<Revoke> for trust_graph::Revoke { impl TryFrom<Revocation> for trust_graph::Revocation {
type Error = DtoConversionError; type Error = DtoConversionError;
fn try_from(r: Revoke) -> Result<Self, Self::Error> { fn try_from(r: Revocation) -> Result<Self, Self::Error> {
let revoked_pk = PublicKey::try_from( let revoked_pk = PublicKey::try_from(
PeerId::from_str(&r.revoked_peer_id) PeerId::from_str(&r.revoked_peer_id)
.map_err(|e| PeerIdDecodeError(format!("{:?}", e)))?, .map_err(|e| PeerIdDecodeError(format!("{:?}", e)))?,
@ -142,7 +142,7 @@ impl TryFrom<Revoke> for trust_graph::Revoke {
let signature = bs58::decode(&r.signature).into_vec()?; let signature = bs58::decode(&r.signature).into_vec()?;
let signature = Signature::from_bytes(KeyFormat::from_str(&r.sig_type)?, signature); let signature = Signature::from_bytes(KeyFormat::from_str(&r.sig_type)?, signature);
let revoked_at = Duration::from_secs(r.revoked_at); let revoked_at = Duration::from_secs(r.revoked_at);
return Ok(trust_graph::Revoke { return Ok(trust_graph::Revocation {
pk: revoked_pk, pk: revoked_pk,
revoked_at, revoked_at,
revoked_by: revoked_by_pk, revoked_by: revoked_by_pk,
@ -151,14 +151,14 @@ impl TryFrom<Revoke> for trust_graph::Revoke {
} }
} }
impl From<trust_graph::Revoke> for Revoke { impl From<trust_graph::Revocation> for Revocation {
fn from(r: trust_graph::Revoke) -> Self { fn from(r: trust_graph::Revocation) -> Self {
let revoked_by = r.revoked_by.to_peer_id().to_base58(); let revoked_by = r.revoked_by.to_peer_id().to_base58();
let revoked_peer_id = r.pk.to_peer_id().to_base58(); let revoked_peer_id = r.pk.to_peer_id().to_base58();
let raw_signature = r.signature.get_raw_signature(); let raw_signature = r.signature.get_raw_signature();
let signature = bs58::encode(raw_signature.bytes).into_string(); let signature = bs58::encode(raw_signature.bytes).into_string();
let revoked_at = r.revoked_at.as_secs(); let revoked_at = r.revoked_at.as_secs();
return Revoke { return Revocation {
revoked_peer_id, revoked_peer_id,
revoked_at, revoked_at,
signature, signature,

View File

@ -1,4 +1,4 @@
use crate::dto::{Certificate, Revoke, Trust}; use crate::dto::{Certificate, Revocation, Trust};
use crate::error::ServiceError; use crate::error::ServiceError;
use marine_rs_sdk::marine; use marine_rs_sdk::marine;
@ -216,21 +216,21 @@ impl From<Result<Vec<u8>, ServiceError>> for GetRevokeBytesResult {
pub struct IssueRevocationResult { pub struct IssueRevocationResult {
pub success: bool, pub success: bool,
pub error: String, pub error: String,
pub revoke: Revoke, pub revocation: Revocation,
} }
impl From<Result<Revoke, ServiceError>> for IssueRevocationResult { impl From<Result<Revocation, ServiceError>> for IssueRevocationResult {
fn from(result: Result<Revoke, ServiceError>) -> Self { fn from(result: Result<Revocation, ServiceError>) -> Self {
match result { match result {
Ok(revoke) => IssueRevocationResult { Ok(revocation) => IssueRevocationResult {
success: true, success: true,
error: "".to_string(), error: "".to_string(),
revoke, revocation,
}, },
Err(e) => IssueRevocationResult { Err(e) => IssueRevocationResult {
success: false, success: false,
error: format!("{}", e), error: format!("{}", e),
revoke: Revoke::default(), revocation: Revocation::default(),
}, },
} }
} }

View File

@ -1,4 +1,4 @@
use crate::dto::{Certificate, Revoke, Trust}; use crate::dto::{Certificate, Revocation, Trust};
use crate::error::ServiceError; use crate::error::ServiceError;
use crate::misc::{check_timestamp_tetraplets, extract_public_key, with_tg, wrapped_try}; use crate::misc::{check_timestamp_tetraplets, extract_public_key, with_tg, wrapped_try};
use crate::results::{ use crate::results::{
@ -201,7 +201,7 @@ fn add_trust(trust: Trust, issuer_peer_id: String, timestamp_sec: u64) -> AddTru
fn get_revoke_bytes(revoked_peer_id: String, revoked_at: u64) -> GetRevokeBytesResult { fn get_revoke_bytes(revoked_peer_id: String, revoked_at: u64) -> GetRevokeBytesResult {
wrapped_try(|| { wrapped_try(|| {
let public_key = extract_public_key(revoked_peer_id)?; let public_key = extract_public_key(revoked_peer_id)?;
Ok(trust_graph::Revoke::signature_bytes( Ok(trust_graph::Revocation::signature_bytes(
&public_key, &public_key,
Duration::from_secs(revoked_at), Duration::from_secs(revoked_at),
)) ))
@ -222,13 +222,13 @@ fn issue_revocation(
let revoked_at = Duration::from_secs(revoked_at_sec); let revoked_at = Duration::from_secs(revoked_at_sec);
let signature = Signature::from_bytes(revoked_by_pk.get_key_format(), signature_bytes); let signature = Signature::from_bytes(revoked_by_pk.get_key_format(), signature_bytes);
Ok(trust_graph::Revoke::new(revoked_pk, revoked_by_pk, revoked_at, signature).into()) Ok(trust_graph::Revocation::new(revoked_pk, revoked_by_pk, revoked_at, signature).into())
}) })
.into() .into()
} }
#[marine] #[marine]
fn revoke(revoke: Revoke, timestamp_sec: u64) -> RevokeResult { fn revoke(revoke: Revocation, timestamp_sec: u64) -> RevokeResult {
with_tg(|tg| { with_tg(|tg| {
check_timestamp_tetraplets(&marine_rs_sdk::get_call_parameters(), 1)?; check_timestamp_tetraplets(&marine_rs_sdk::get_call_parameters(), 1)?;

View File

@ -17,12 +17,12 @@ use std::str::FromStr;
use std::time::Duration; use std::time::Duration;
use thiserror::Error as ThisError; use thiserror::Error as ThisError;
use trust_graph::{ use trust_graph::{
Auth, PublicKeyHashable as PK, PublicKeyHashable, Revoke, Storage, StorageError, Trust, Auth, PublicKeyHashable as PK, PublicKeyHashable, Revocation, Storage, StorageError, Trust,
TrustRelation, WeightFactor, TrustRelation, WeightFactor,
}; };
static AUTH_TYPE: i64 = 0; static AUTH_TYPE: i64 = 0;
static REVOKE_TYPE: i64 = 1; static REVOCATION_TYPE: i64 = 1;
pub static DB_PATH: &str = "/tmp/trust-graph.sqlite"; pub static DB_PATH: &str = "/tmp/trust-graph.sqlite";
pub fn create_tables() { pub fn create_tables() {
@ -72,7 +72,7 @@ impl SQLiteStorage {
} }
} }
Some(TrustRelation::Revoke(revoke)) => { Some(TrustRelation::Revocation(revoke)) => {
if revoke.revoked_at < relation.issued_at() { if revoke.revoked_at < relation.issued_at() {
self.insert(relation)?; self.insert(relation)?;
} }
@ -85,6 +85,35 @@ impl SQLiteStorage {
Ok(()) Ok(())
} }
fn get_relations(
&self,
issued_for: &PublicKeyHashable,
relation_type: i64,
) -> Result<Vec<TrustRelation>, SQLiteStorageError> {
let mut cursor = self
.connection
.prepare(
"SELECT relation_type, issued_for, issued_by, issued_at, expires_at, signature \
FROM trust_relations WHERE issued_for = ? and relation_type = ?",
)?
.cursor();
cursor.bind(&[
Value::String(format!("{}", issued_for)),
Value::Integer(relation_type),
])?;
let mut relations: Vec<TrustRelation> = vec![];
while let Some(row) = cursor.next()? {
match parse_relation(row) {
Ok(r) => relations.push(r),
Err(e) => log::error!("parse_relation: {:?}", e),
}
}
Ok(relations)
}
} }
#[derive(ThisError, Debug)] #[derive(ThisError, Debug)]
@ -143,7 +172,7 @@ fn parse_relation(row: &[Value]) -> Result<TrustRelation, SQLiteStorageError> {
issued_by: issued_by.into(), issued_by: issued_by.into(),
})) }))
} else { } else {
Ok(TrustRelation::Revoke(Revoke { Ok(TrustRelation::Revocation(Revocation {
pk: issued_for.into(), pk: issued_for.into(),
revoked_at: issued_at, revoked_at: issued_at,
revoked_by: issued_by.into(), revoked_by: issued_by.into(),
@ -189,25 +218,34 @@ impl Storage for SQLiteStorage {
} }
/// return all auths issued for pk /// return all auths issued for pk
fn get_authorizations(&self, pk: &PublicKeyHashable) -> Result<Vec<Auth>, Self::Error> { fn get_authorizations(&self, issued_for: &PublicKeyHashable) -> Result<Vec<Auth>, Self::Error> {
let mut cursor = self Ok(self
.connection .get_relations(issued_for, AUTH_TYPE)?
.prepare( .into_iter()
"SELECT relation_type, issued_for, issued_by, issued_at, expires_at, signature \ .fold(vec![], |mut acc, r| {
FROM trust_relations WHERE issued_for = ? and relation_type = ?", if let TrustRelation::Auth(a) = r {
)? acc.push(a);
.cursor(); }
cursor.bind(&[Value::String(format!("{}", pk)), Value::Integer(AUTH_TYPE)])?; acc
let mut auths: Vec<Auth> = vec![]; }))
}
while let Some(row) = cursor.next()? { /// return all revocations issued for pk
if let TrustRelation::Auth(auth) = parse_relation(row)? { fn get_revocations(
auths.push(auth); &self,
} issued_for: &PublicKeyHashable,
} ) -> Result<Vec<Revocation>, Self::Error> {
Ok(self
.get_relations(issued_for, REVOCATION_TYPE)?
.into_iter()
.fold(vec![], |mut acc, r| {
if let TrustRelation::Revocation(revocation) = r {
acc.push(revocation);
}
Ok(auths) acc
}))
} }
fn insert(&mut self, relation: TrustRelation) -> Result<(), Self::Error> { fn insert(&mut self, relation: TrustRelation) -> Result<(), Self::Error> {
@ -217,7 +255,7 @@ impl Storage for SQLiteStorage {
let relation_type = match relation { let relation_type = match relation {
TrustRelation::Auth(_) => AUTH_TYPE, TrustRelation::Auth(_) => AUTH_TYPE,
TrustRelation::Revoke(_) => REVOKE_TYPE, TrustRelation::Revocation(_) => REVOCATION_TYPE,
}; };
statement.bind(1, &Value::Integer(relation_type))?; statement.bind(1, &Value::Integer(relation_type))?;
@ -293,8 +331,8 @@ impl Storage for SQLiteStorage {
Ok(roots) Ok(roots)
} }
fn revoke(&mut self, revoke: Revoke) -> Result<(), Self::Error> { fn revoke(&mut self, revoke: Revocation) -> Result<(), Self::Error> {
self.update_relation(TrustRelation::Revoke(revoke)) self.update_relation(TrustRelation::Revocation(revoke))
} }
fn update_auth(&mut self, auth: Auth, _cur_time: Duration) -> Result<(), Self::Error> { fn update_auth(&mut self, auth: Auth, _cur_time: Duration) -> Result<(), Self::Error> {

View File

@ -23,7 +23,7 @@ mod service_tests {
use fluence_keypair::KeyPair; use fluence_keypair::KeyPair;
use libp2p_core::PeerId; use libp2p_core::PeerId;
use marine_rs_sdk::{CallParameters, SecurityTetraplet}; use marine_rs_sdk::{CallParameters, SecurityTetraplet};
use marine_test_env::trust_graph::{Certificate, Revoke, ServiceInterface, Trust}; use marine_test_env::trust_graph::{Certificate, Revocation, ServiceInterface, Trust};
use rusqlite::Connection; use rusqlite::Connection;
use std::collections::HashMap; use std::collections::HashMap;
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
@ -200,7 +200,7 @@ mod service_tests {
issuer_kp: &KeyPair, issuer_kp: &KeyPair,
revoked_peer_id: &PeerId, revoked_peer_id: &PeerId,
revoked_at_sec: u64, revoked_at_sec: u64,
) -> Revoke { ) -> Revocation {
let result = trust_graph.get_revoke_bytes(revoked_peer_id.to_base58(), revoked_at_sec); let result = trust_graph.get_revoke_bytes(revoked_peer_id.to_base58(), revoked_at_sec);
assert!(result.success, "{}", result.error); assert!(result.success, "{}", result.error);
@ -214,14 +214,14 @@ mod service_tests {
assert!(issue_result.success, "{}", issue_result.error); assert!(issue_result.success, "{}", issue_result.error);
let revoke_result = trust_graph.revoke_cp( let revoke_result = trust_graph.revoke_cp(
issue_result.revoke.clone(), issue_result.revocation.clone(),
revoked_at_sec, revoked_at_sec,
get_correct_timestamp_cp(1), get_correct_timestamp_cp(1),
); );
assert!(revoke_result.success, "{}", revoke_result.error); assert!(revoke_result.success, "{}", revoke_result.error);
issue_result.revoke issue_result.revocation
} }
fn generate_trust_chain_with( fn generate_trust_chain_with(
@ -436,39 +436,98 @@ mod service_tests {
assert_eq!(certs.len(), 0); assert_eq!(certs.len(), 0);
} }
/// 1. peer `A` gives trusts to `B`
/// 2. weight of `B` is not 0
/// 3. peer `A` revokes `B`
/// 4. there is no path from `A` to `B`, weight of `A` is 0
#[test] #[test]
fn revoke_test() { fn trust_direct_revoke_test() {
let mut trust_graph = marine_test_env::trust_graph::ServiceInterface::new(); let mut trust_graph = marine_test_env::trust_graph::ServiceInterface::new();
clear_env(); clear_env();
let root_kp = KeyPair::generate_ed25519(); let peerA_kp = KeyPair::generate_ed25519();
let mut cur_time = 100u64; let mut cur_time = 100u64;
add_root_with_trust(&mut trust_graph, &root_kp, cur_time, cur_time + 9999, 4u32); add_root_with_trust(&mut trust_graph, &peerA_kp, cur_time, cur_time + 9999, 4u32);
let trust_kp = KeyPair::generate_ed25519(); let peerB_kp = KeyPair::generate_ed25519();
add_trust( add_trust(
&mut trust_graph, &mut trust_graph,
&root_kp, &peerA_kp,
&trust_kp.get_peer_id(), &peerB_kp.get_peer_id(),
cur_time, cur_time,
cur_time + 99999, cur_time + 99999,
); );
let weight = get_weight(&mut trust_graph, trust_kp.get_peer_id(), cur_time); let weight = get_weight(&mut trust_graph, peerB_kp.get_peer_id(), cur_time);
assert_ne!(weight, 0u32); assert_ne!(weight, 0u32);
cur_time += 1; cur_time += 1;
// A revokes B and cancels trust
revoke( revoke(
&mut trust_graph, &mut trust_graph,
&root_kp, &peerA_kp,
&trust_kp.get_peer_id(), &peerB_kp.get_peer_id(),
cur_time, cur_time,
); );
let weight = get_weight(&mut trust_graph, trust_kp.get_peer_id(), cur_time); let weight = get_weight(&mut trust_graph, peerB_kp.get_peer_id(), cur_time);
assert_eq!(weight, 0u32); assert_eq!(weight, 0u32);
} }
/// There is chain of trusts [0] -> [1] -> [2] -> [3] -> [4]
/// 1. [1] revokes [4]
/// 2. there is no path from [0] to [4], weight of [4] is 0
/// 3. [0] gives trust to [2]
/// 4. now there is path [0] -> [2] -> [3] -> [4]
/// 5. weight of [4] is not 0
#[test]
fn indirect_revoke_test() {
let mut trust_graph = marine_test_env::trust_graph::ServiceInterface::new();
clear_env();
let (key_pairs, trusts) =
generate_trust_chain_with_len(&mut trust_graph, 5, HashMap::new());
let mut cur_time = current_time();
let root_peer_id = key_pairs[0].get_peer_id();
add_root_peer_id(&mut trust_graph, root_peer_id, 2);
add_trusts(&mut trust_graph, &trusts, cur_time);
let target_peer_id = key_pairs[4].get_peer_id();
let revoked_by = &key_pairs[1];
let weight = get_weight(&mut trust_graph, target_peer_id, cur_time);
assert_ne!(weight, 0u32);
cur_time += 1;
// [1] revokes [4]
revoke(&mut trust_graph, &revoked_by, &target_peer_id, cur_time);
// now there are no path from root to [4]
let weight = get_weight(&mut trust_graph, target_peer_id, cur_time);
assert_eq!(weight, 0u32);
// [0] trusts [2]
add_trust(
&mut trust_graph,
&key_pairs[0],
&key_pairs[2].get_peer_id(),
cur_time,
cur_time + 99999,
);
// [2] trusts [4]
add_trust(
&mut trust_graph,
&key_pairs[2],
&target_peer_id,
cur_time,
cur_time + 99999,
);
// now we have [0] -> [2] -> [4] path
let weight = get_weight(&mut trust_graph, target_peer_id, cur_time);
assert_ne!(weight, 0u32);
}
#[test] #[test]
fn test_add_one_trust_to_cert_last() { fn test_add_one_trust_to_cert_last() {
let mut trust_graph = ServiceInterface::new(); let mut trust_graph = ServiceInterface::new();

47
src/chain.rs Normal file
View File

@ -0,0 +1,47 @@
/*
* 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.
* 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 crate::{Auth, PublicKeyHashable, Revocation};
use fluence_keypair::PublicKey;
use nonempty::NonEmpty;
use std::collections::HashSet;
#[derive(Clone)]
pub(crate) struct Chain {
pub(crate) auths: NonEmpty<Auth>,
revoked_by: HashSet<PublicKeyHashable>,
}
impl Chain {
pub(crate) fn new(auths: NonEmpty<Auth>, revocations: Vec<Revocation>) -> Self {
let mut chain = Self {
auths,
revoked_by: Default::default(),
};
chain.add_revocations(revocations);
chain
}
pub(crate) fn can_be_extended_by(&self, pk: &PublicKey) -> bool {
!self.revoked_by.contains(pk.as_ref())
&& !self.auths.iter().any(|a| a.trust.issued_for.eq(pk))
}
pub(crate) fn add_revocations(&mut self, revocations: Vec<Revocation>) {
revocations.into_iter().for_each(move |r| {
self.revoked_by.insert(r.revoked_by.into());
});
}
}

View File

@ -29,6 +29,7 @@
mod certificate; mod certificate;
pub mod certificate_serde; pub mod certificate_serde;
mod chain;
mod misc; mod misc;
mod public_key_hashable; mod public_key_hashable;
mod revoke; mod revoke;
@ -40,7 +41,7 @@ mod trust_relation;
pub use crate::certificate::{Certificate, CertificateError}; pub use crate::certificate::{Certificate, CertificateError};
pub use crate::misc::current_time; pub use crate::misc::current_time;
pub use crate::public_key_hashable::PublicKeyHashable; pub use crate::public_key_hashable::PublicKeyHashable;
pub use crate::revoke::Revoke; pub use crate::revoke::Revocation;
pub use crate::trust::{Trust, TrustError}; pub use crate::trust::{Trust, TrustError};
pub use crate::trust_graph::{TrustGraph, TrustGraphError, WeightFactor, MAX_WEIGHT_FACTOR}; pub use crate::trust_graph::{TrustGraph, TrustGraphError, WeightFactor, MAX_WEIGHT_FACTOR};
pub use crate::trust_graph_storage::{Storage, StorageError}; pub use crate::trust_graph_storage::{Storage, StorageError};

View File

@ -36,7 +36,7 @@ pub enum RevokeError {
/// "A document" that cancels trust created before. /// "A document" that cancels trust created before.
/// TODO delete pk from Revoke (it is already in a trust node) /// TODO delete pk from Revoke (it is already in a trust node)
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Revoke { pub struct Revocation {
/// who is revoked /// who is revoked
pub pk: PublicKey, pub pk: PublicKey,
/// date when revocation was created /// date when revocation was created
@ -47,7 +47,7 @@ pub struct Revoke {
pub signature: Signature, pub signature: Signature,
} }
impl Revoke { impl Revocation {
#[allow(dead_code)] #[allow(dead_code)]
pub fn new( pub fn new(
pk: PublicKey, pk: PublicKey,
@ -66,10 +66,10 @@ impl Revoke {
/// Creates new revocation signed by a revoker. /// Creates new revocation signed by a revoker.
#[allow(dead_code)] #[allow(dead_code)]
pub fn create(revoker: &KeyPair, to_revoke: PublicKey, revoked_at: Duration) -> Self { pub fn create(revoker: &KeyPair, to_revoke: PublicKey, revoked_at: Duration) -> Self {
let msg = Revoke::signature_bytes(&to_revoke, revoked_at); let msg = Revocation::signature_bytes(&to_revoke, revoked_at);
let signature = revoker.sign(&msg).unwrap(); let signature = revoker.sign(&msg).unwrap();
Revoke::new(to_revoke, revoker.public(), revoked_at, signature) Revocation::new(to_revoke, revoker.public(), revoked_at, signature)
} }
pub fn signature_bytes(pk: &PublicKey, revoked_at: Duration) -> Vec<u8> { pub fn signature_bytes(pk: &PublicKey, revoked_at: Duration) -> Vec<u8> {
@ -83,8 +83,8 @@ impl Revoke {
} }
/// Verifies that revocation is cryptographically correct. /// Verifies that revocation is cryptographically correct.
pub fn verify(revoke: &Revoke) -> Result<(), RevokeError> { pub fn verify(revoke: &Revocation) -> Result<(), RevokeError> {
let msg = Revoke::signature_bytes(&revoke.pk, revoke.revoked_at); let msg = Revocation::signature_bytes(&revoke.pk, revoke.revoked_at);
revoke revoke
.revoked_by .revoked_by
@ -104,9 +104,9 @@ mod tests {
let duration = Duration::new(100, 0); let duration = Duration::new(100, 0);
let revoke = Revoke::create(&revoker, to_revoke.public(), duration); let revoke = Revocation::create(&revoker, to_revoke.public(), duration);
assert_eq!(Revoke::verify(&revoke).is_ok(), true); assert_eq!(Revocation::verify(&revoke).is_ok(), true);
} }
#[test] #[test]
@ -116,16 +116,16 @@ mod tests {
let duration = Duration::new(100, 0); let duration = Duration::new(100, 0);
let revoke = Revoke::create(&revoker, to_revoke.public(), duration); let revoke = Revocation::create(&revoker, to_revoke.public(), duration);
let duration2 = Duration::new(95, 0); let duration2 = Duration::new(95, 0);
let corrupted_revoke = Revoke::new( let corrupted_revoke = Revocation::new(
to_revoke.public(), to_revoke.public(),
revoker.public(), revoker.public(),
duration2, duration2,
revoke.signature, revoke.signature,
); );
assert_eq!(Revoke::verify(&corrupted_revoke).is_ok(), false); assert_eq!(Revocation::verify(&corrupted_revoke).is_ok(), false);
} }
} }

View File

@ -16,8 +16,9 @@
use crate::certificate::CertificateError::CertificateLengthError; use crate::certificate::CertificateError::CertificateLengthError;
use crate::certificate::{Certificate, CertificateError}; use crate::certificate::{Certificate, CertificateError};
use crate::chain::Chain;
use crate::public_key_hashable::PublicKeyHashable as PK; use crate::public_key_hashable::PublicKeyHashable as PK;
use crate::revoke::Revoke; use crate::revoke::Revocation;
use crate::revoke::RevokeError; use crate::revoke::RevokeError;
use crate::trust::Trust; use crate::trust::Trust;
use crate::trust_graph::TrustGraphError::{ use crate::trust_graph::TrustGraphError::{
@ -27,6 +28,7 @@ use crate::trust_graph_storage::Storage;
use crate::trust_relation::Auth; use crate::trust_relation::Auth;
use crate::{StorageError, TrustError}; use crate::{StorageError, TrustError};
use fluence_keypair::public_key::PublicKey; use fluence_keypair::public_key::PublicKey;
use nonempty::NonEmpty;
use std::borrow::Borrow; use std::borrow::Borrow;
use std::collections::{HashSet, VecDeque}; use std::collections::{HashSet, VecDeque};
use std::convert::{From, Into}; use std::convert::{From, Into};
@ -93,7 +95,7 @@ impl From<TrustGraphError> for String {
} }
pub fn get_weight_from_factor(wf: WeightFactor) -> u32 { pub fn get_weight_from_factor(wf: WeightFactor) -> u32 {
2u32.pow(MAX_WEIGHT_FACTOR.checked_sub(wf).unwrap_or(0u32)) 2u32.pow(MAX_WEIGHT_FACTOR.saturating_sub(wf))
} }
impl<S> TrustGraph<S> impl<S> TrustGraph<S>
@ -245,12 +247,14 @@ where
roots: HashSet<&PK>, roots: HashSet<&PK>,
) -> Result<Vec<Vec<Auth>>, TrustGraphError> { ) -> Result<Vec<Vec<Auth>>, TrustGraphError> {
// queue to collect all chains in the trust graph (each chain is a path in the trust graph) // queue to collect all chains in the trust graph (each chain is a path in the trust graph)
let mut chains_queue: VecDeque<Vec<Auth>> = VecDeque::new(); let mut chains_queue: VecDeque<Chain> = VecDeque::new();
let node_auths: Vec<Auth> = self.storage.get_authorizations(pk)?; let node_auths: Vec<Auth> = self.storage.get_authorizations(pk)?;
let node_revocations = self.storage.get_revocations(pk)?;
// put all auth in the queue as the first possible paths through the graph // put all auth in the queue as the first possible paths through the graph
for auth in node_auths { for auth in node_auths {
chains_queue.push_back(vec![auth]); chains_queue.push_back(Chain::new(NonEmpty::new(auth), node_revocations.clone()));
} }
// List of all chains that converge (terminate) to known roots // List of all chains that converge (terminate) to known roots
@ -261,22 +265,21 @@ where
.pop_front() .pop_front()
.expect("`chains_queue` always has at least one element"); .expect("`chains_queue` always has at least one element");
let last = cur_chain let last = cur_chain.auths.last();
.last()
.expect("`cur_chain` always has at least one element");
let auths = self let auths = self
.storage .storage
.get_authorizations(&last.issued_by.clone().into())?; .get_authorizations(&last.issued_by.clone().into())?;
for auth in auths { for auth in auths {
// if there is auth, that we not visited in the current chain, copy chain and append this auth // if there is auth, that we not visited in the current chain and no revocations to any chain member -- copy chain and append this auth
if !cur_chain if cur_chain.can_be_extended_by(&auth.issued_by) {
.iter()
.any(|a| a.trust.issued_for == auth.issued_by)
{
let mut new_chain = cur_chain.clone(); let mut new_chain = cur_chain.clone();
new_chain.push(auth); new_chain.add_revocations(
self.storage
.get_revocations(&auth.issued_by.clone().into())?,
);
new_chain.auths.push(auth);
chains_queue.push_back(new_chain); chains_queue.push_back(new_chain);
} }
} }
@ -289,8 +292,8 @@ where
let issued_by: &PK = last.issued_by.as_ref(); let issued_by: &PK = last.issued_by.as_ref();
let converges_to_root = roots.contains(issued_by); let converges_to_root = roots.contains(issued_by);
if self_signed && converges_to_root && cur_chain.len() > 1 { if self_signed && converges_to_root && cur_chain.auths.len() > 1 {
terminated_chains.push(cur_chain); terminated_chains.push(cur_chain.auths.into());
} }
} }
@ -334,9 +337,11 @@ where
} }
/// Mark public key as revoked. /// Mark public key as revoked.
pub fn revoke(&mut self, revoke: Revoke) -> Result<(), TrustGraphError> { /// Every chain that contains path from `revoked_by` to revoked `pk`
Revoke::verify(&revoke)?; /// will be excluded from valid certificates until revocation canceled by giving trust
pub fn revoke(&mut self, revocation: Revocation) -> Result<(), TrustGraphError> {
Revocation::verify(&revocation)?;
Ok(self.storage.revoke(revoke)?) Ok(self.storage.revoke(revocation)?)
} }
} }

View File

@ -1,5 +1,5 @@
use crate::public_key_hashable::PublicKeyHashable as PK; use crate::public_key_hashable::PublicKeyHashable as PK;
use crate::revoke::Revoke; use crate::revoke::Revocation;
use crate::trust_graph::WeightFactor; use crate::trust_graph::WeightFactor;
use crate::trust_relation::{Auth, TrustRelation}; use crate::trust_relation::{Auth, TrustRelation};
use std::fmt::Display; use std::fmt::Display;
@ -16,13 +16,15 @@ pub trait Storage {
issued_by: &PK, issued_by: &PK,
) -> Result<Option<TrustRelation>, Self::Error>; ) -> Result<Option<TrustRelation>, Self::Error>;
fn get_authorizations(&self, pk: &PK) -> Result<Vec<Auth>, Self::Error>; fn get_authorizations(&self, issued_for: &PK) -> Result<Vec<Auth>, Self::Error>;
fn get_revocations(&self, issued_for: &PK) -> Result<Vec<Revocation>, Self::Error>;
fn insert(&mut self, node: TrustRelation) -> Result<(), Self::Error>; fn insert(&mut self, node: TrustRelation) -> Result<(), Self::Error>;
fn get_root_weight_factor(&self, pk: &PK) -> Result<Option<WeightFactor>, Self::Error>; fn get_root_weight_factor(&self, pk: &PK) -> Result<Option<WeightFactor>, Self::Error>;
fn add_root_weight_factor(&mut self, pk: PK, weight: WeightFactor) -> Result<(), Self::Error>; fn add_root_weight_factor(&mut self, pk: PK, weight: WeightFactor) -> Result<(), Self::Error>;
fn root_keys(&self) -> Result<Vec<PK>, Self::Error>; fn root_keys(&self) -> Result<Vec<PK>, Self::Error>;
fn revoke(&mut self, revoke: Revoke) -> Result<(), Self::Error>; fn revoke(&mut self, revocation: Revocation) -> Result<(), Self::Error>;
fn update_auth(&mut self, auth: Auth, cur_time: Duration) -> Result<(), Self::Error>; fn update_auth(&mut self, auth: Auth, cur_time: Duration) -> Result<(), Self::Error>;
fn remove_expired(&mut self, current_time: Duration) -> Result<(), Self::Error>; fn remove_expired(&mut self, current_time: Duration) -> Result<(), Self::Error>;
} }

View File

@ -1,206 +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 crate::public_key_hashable::PublicKeyHashable;
use crate::revoke::Revoke;
use crate::trust::Trust;
use failure::_core::time::Duration;
use fluence_keypair::public_key::PublicKey;
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
enum TrustRelation {
Auth(Auth),
Revoke(Revoke),
}
impl TrustRelation {
/// Returns timestamp of when this relation was created
pub fn issued_at(&self) -> Duration {
match self {
TrustRelation::Auth(auth) => auth.trust.issued_at,
TrustRelation::Revoke(revoke) => revoke.revoked_at,
}
}
/// Returns public key of the creator of this relation
pub fn issued_by(&self) -> &PublicKey {
match self {
TrustRelation::Auth(auth) => &auth.issued_by,
TrustRelation::Revoke(revoke) => &revoke.revoked_by,
}
}
}
/// Represents who give a certificate
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Auth {
/// proof of this authorization
pub trust: Trust,
/// the issuer of this authorization
pub issued_by: PublicKey,
}
/// An element of trust graph that store relations (trust or revoke)
/// that given by some owners of public keys.
#[serde_as]
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct TrustNode {
/// identity key of this element
pub pk: PublicKey,
/// one public key could be authorized or revoked by multiple certificates
#[serde_as(as = "Vec<(_, _)>")]
trust_relations: HashMap<PublicKeyHashable, TrustRelation>,
/// for maintain
pub verified_at: Duration,
}
#[allow(dead_code)]
impl TrustNode {
pub fn new(pk: PublicKey, verified_at: Duration) -> Self {
Self {
pk,
trust_relations: HashMap::new(),
verified_at,
}
}
pub fn get_auth(&self, pk: PublicKey) -> Option<Auth> {
match self.trust_relations.get(&pk.into()) {
Some(TrustRelation::Auth(auth)) => Some(auth.clone()),
_ => None,
}
}
pub fn get_revoke(&self, pk: PublicKey) -> Option<Revoke> {
match self.trust_relations.get(&pk.into()) {
Some(TrustRelation::Revoke(rev)) => Some(rev.clone()),
_ => None,
}
}
pub fn authorizations(&self) -> impl Iterator<Item = &Auth> + '_ {
self.trust_relations.values().filter_map(|tr| {
if let TrustRelation::Auth(auth) = tr {
Some(auth)
} else {
None
}
})
}
pub fn revocations(&self) -> impl Iterator<Item = &Revoke> + '_ {
self.trust_relations.values().filter_map(|tr| {
if let TrustRelation::Revoke(revoke) = tr {
Some(revoke)
} else {
None
}
})
}
/// Adds authorization. If the trust node already has this authorization,
/// add auth with later expiration date.
pub fn update_auth(&mut self, auth: Auth) {
self.update_relation(TrustRelation::Auth(auth));
}
// insert new trust relation, ignore if there is another one with same public key
fn insert(&mut self, pk: PublicKeyHashable, tr: TrustRelation) {
self.trust_relations.insert(pk, tr);
}
fn update_relation(&mut self, relation: TrustRelation) {
let issued_by = relation.issued_by().as_ref();
match self.trust_relations.get(issued_by) {
Some(TrustRelation::Auth(auth)) => {
if auth.trust.issued_at < relation.issued_at() {
self.insert(issued_by.clone(), relation)
}
}
Some(TrustRelation::Revoke(existed_revoke)) => {
if existed_revoke.revoked_at < relation.issued_at() {
self.insert(issued_by.clone(), relation)
}
}
None => self.insert(issued_by.clone(), relation),
};
}
pub fn update_revoke(&mut self, revoke: Revoke) {
self.update_relation(TrustRelation::Revoke(revoke));
}
}
#[cfg(test)]
mod tests {
use std::time::Duration;
use fluence_keypair::key_pair::KeyPair;
use super::*;
#[test]
fn test_auth_and_revoke_trust_node() {
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(),
trust_relations: HashMap::new(),
verified_at: now,
};
let truster = KeyPair::generate_ed25519();
let revoke = Revoke::create(&truster, kp.public(), now);
trust_node.update_revoke(revoke);
assert!(trust_node.get_revoke(truster.public()).is_some());
let old_trust = Trust::create(&truster, kp.public(), Duration::new(60, 0), past);
let old_auth = Auth {
trust: old_trust,
issued_by: truster.public(),
};
trust_node.update_auth(old_auth);
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(), Duration::new(60, 0), future);
let auth = Auth {
trust,
issued_by: truster.public(),
};
trust_node.update_auth(auth);
assert!(trust_node.get_auth(truster.public()).is_some());
assert!(trust_node.get_revoke(truster.public()).is_none());
}
}

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
use crate::revoke::Revoke; use crate::revoke::Revocation;
use crate::trust::Trust; use crate::trust::Trust;
use failure::_core::time::Duration; use failure::_core::time::Duration;
use fluence_keypair::public_key::PublicKey; use fluence_keypair::public_key::PublicKey;
@ -33,7 +33,7 @@ pub struct Auth {
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TrustRelation { pub enum TrustRelation {
Auth(Auth), Auth(Auth),
Revoke(Revoke), Revocation(Revocation),
} }
impl TrustRelation { impl TrustRelation {
@ -41,7 +41,7 @@ impl TrustRelation {
pub fn issued_at(&self) -> Duration { pub fn issued_at(&self) -> Duration {
match self { match self {
TrustRelation::Auth(auth) => auth.trust.issued_at, TrustRelation::Auth(auth) => auth.trust.issued_at,
TrustRelation::Revoke(revoke) => revoke.revoked_at, TrustRelation::Revocation(r) => r.revoked_at,
} }
} }
@ -49,28 +49,29 @@ impl TrustRelation {
pub fn issued_by(&self) -> &PublicKey { pub fn issued_by(&self) -> &PublicKey {
match self { match self {
TrustRelation::Auth(auth) => &auth.issued_by, TrustRelation::Auth(auth) => &auth.issued_by,
TrustRelation::Revoke(revoke) => &revoke.revoked_by, TrustRelation::Revocation(r) => &r.revoked_by,
} }
} }
pub fn issued_for(&self) -> &PublicKey { pub fn issued_for(&self) -> &PublicKey {
match self { match self {
TrustRelation::Auth(auth) => &auth.trust.issued_for, TrustRelation::Auth(auth) => &auth.trust.issued_for,
TrustRelation::Revoke(revoke) => &revoke.pk, TrustRelation::Revocation(r) => &r.pk,
} }
} }
pub fn expires_at(&self) -> Duration { pub fn expires_at(&self) -> Duration {
match self { match self {
TrustRelation::Auth(auth) => auth.trust.expires_at, TrustRelation::Auth(auth) => auth.trust.expires_at,
TrustRelation::Revoke(_) => Duration::from_secs(0), // revocations never expire
TrustRelation::Revocation(_) => Duration::from_secs(0),
} }
} }
pub fn signature(&self) -> &Signature { pub fn signature(&self) -> &Signature {
match self { match self {
TrustRelation::Auth(auth) => &auth.trust.signature, TrustRelation::Auth(auth) => &auth.trust.signature,
TrustRelation::Revoke(revoke) => &revoke.signature, TrustRelation::Revocation(r) => &r.signature,
} }
} }
} }