Browse Source

Proposed Extension layer for OpenInvite

onyinyang 10 months ago
commit
7f27b92812
6 changed files with 506 additions and 0 deletions
  1. 1 0
      .gitignore
  2. 296 0
      Cargo.lock
  3. 11 0
      Cargo.toml
  4. 48 0
      src/cmz.rs
  5. 2 0
      src/lib.rs
  6. 148 0
      src/proto/open_invite.md

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+/target

+ 296 - 0
Cargo.lock

@@ -0,0 +1,296 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "block-buffer"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "byteorder"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "cpufeatures"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "curve25519-dalek"
+version = "4.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "curve25519-dalek-derive",
+ "digest",
+ "fiat-crypto",
+ "rand_core",
+ "rustc_version",
+ "serde",
+ "subtle",
+]
+
+[[package]]
+name = "curve25519-dalek-derive"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "digest"
+version = "0.10.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
+dependencies = [
+ "block-buffer",
+ "crypto-common",
+]
+
+[[package]]
+name = "fiat-crypto"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
+
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+
+[[package]]
+name = "libc"
+version = "0.2.169"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
+
+[[package]]
+name = "lox-extensions"
+version = "0.1.0"
+dependencies = [
+ "curve25519-dalek",
+ "lazy_static",
+ "rand",
+ "serde",
+ "sha2",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.93"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rustc_version"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
+dependencies = [
+ "semver",
+]
+
+[[package]]
+name = "semver"
+version = "1.0.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03"
+
+[[package]]
+name = "serde"
+version = "1.0.217"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.217"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "sha2"
+version = "0.10.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
+name = "subtle"
+version = "2.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
+
+[[package]]
+name = "syn"
+version = "2.0.98"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "typenum"
+version = "1.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
+
+[[package]]
+name = "version_check"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "zerocopy"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
+dependencies = [
+ "byteorder",
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]

+ 11 - 0
Cargo.toml

@@ -0,0 +1,11 @@
+[package]
+name = "lox-extensions"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+curve25519-dalek = {version = "4.1.3", default-features = false, features = ["serde", "rand_core", "digest", "precomputed-tables"] }
+lazy_static = "1.5.0"
+rand = {version = "0.8.0", features = ["std_rng"] }
+serde = "1.0.217"
+sha2 = "0.10.8"

+ 48 - 0
src/cmz.rs

@@ -0,0 +1,48 @@
+use curve25519_dalek::ristretto::RistrettoPoint;
+use std::collections::HashMap;
+
+// The `CMZ` attribute will automatically add a `MAC: (Point,Point)` field
+// to the struct, create a `Privates` struct for the attributes, and a
+// `Publics` struct for the public keys for the credential.  It will also
+// add issuing and showing methods, which each consume an indication of
+// which attributes to hide, reveal, issue jointly, etc., and produce
+// a `Statement` that attests to the correctness of the issue or the show.
+// Then the Extension layer can use an `AndStatement` combinator to combine
+// that with whatever higher-layer logic is needed.
+
+pub enum IssueType {
+    Select,
+    Joint,
+    Reveal,
+    Hide,
+}
+
+pub enum ShowType {
+    Reveal,
+    Hide,
+}
+
+pub trait CMZ {
+
+    AnnotatedCredential;
+
+    // All fields will be cast as mapping from String -> Scalar
+    // The annotated credential is ouput
+    fn annotate(&self, HashMap<String, Scalar>, IssuerKeys) -> Self;
+    // All fields will be cast as mapping from String -> ShowType 
+    // Outputs AnnotatedShowCredential to be related to AnnotatedIssueCredential by Statement
+    fn show_annotation(&self, HashMap<String, ShowType>) -> AnnotatedShowCredential;
+
+    // All fields will be cast as mapping from String -> IssueType with an output statement
+    // Outputs AnnotatedIssueCredential to be related to AnnotatedShowCredential by Statement
+    fn issue_annotation(&self, HashMap<String, IssueType>) -> AnnotatedIssueCredential;
+   
+    // Takes the annotated show and issue type credentials as well as a statement that relates them 
+    // outputs the State, which contains the client generated attributes/scalars required to 
+    // build the new credential
+    fn issue_request(&self, Vec<AnnotatedShowCredential>, Vec<AnnotatedIssueCredential>, Statement) -> (State, StatementProof);
+    
+    //Takes the annotated credential and statement received from the issuer and builds the updated
+    //credential
+    fn handle_response(&self, AnnotatedIssueCredential, Statement) -> Credential;
+}

+ 2 - 0
src/lib.rs

@@ -0,0 +1,2 @@
+pub mod cmz;
+//pub mod open_invite;

+ 148 - 0
src/proto/open_invite.md

@@ -0,0 +1,148 @@
+Open Invitation Credential
+
+`use super::super::cred;`
+`use super::super::cmz::{IssueType, ShowType};`
+
+```
+#[serde_as]
+#[derive(Serialize, Deserialize)]
+pub struct Request {
+    #[serde_as(as = "[_; OPENINV_LENGTH]")]
+    invite: [u8; OPENINV_LENGTH],
+    // Lox credential with each attribute annotated with the IssueType
+    issue_cred: AnnotatedIssueCredential,
+    // Statement relating the annotated_credentials, in this case: the
+    // commitment to the Lox ID
+    open_issue_statement: Statement,
+}
+```
+
+The client state for this protocol
+```
+#[derive(Debug, Serialize, Deserialize)]
+pub struct State {
+    // Randomized attributes could be stored in annotated credential as
+    // part of the state, that can be used to process the Issued credential
+    // later
+    annotated_cred: AnnotatedIssueCredential,
+    s: Scalar,
+}
+```
+
+The response message for this protocol: (This was copied from the exisiting
+protocol and still needs to be updated)
+
+```
+#[derive(Serialize, Deserialize)]
+pub struct Response {
+    P: RistrettoPoint,
+    BlindLoxQ: RistrettoPoint,
+    server_id: Scalar,
+    bucket: Scalar,
+    level_since: Scalar,
+    piBlindIssue: CompactProof,
+    bridge_line: BridgeLine,
+}
+```
+
+Client Request:
+```
+pub fn request(invite: &[u8; OPENINV_LENGTH], lox_pub: &IssuerPubKey) -> (Request, State) {
+
+// There is no call to "show" for open invitation but the open invite must be verified  
+
+let open_invite_cred_directive = HashMap::from([
+       ("id", Scalar::random()),
+       ("bucket", Scalar::ZERO), // Placeholder value
+       ("trust_level", Scalar::ZERO), // Placeholder value 
+       ("level_since", Scalar::ZERO), // Placeholder value 
+       ("invites_remaining", Scalar::ZERO), // Placeholder value
+       ("blockages", Scalar::ZERO), // Placeholder value
+    ]);
+// Create new Lox credential with mapped fields(String) -> Scalar
+let open_invite_cred = cred.Lox.annotate(open_invite_cred_directive, lox_pub);
+
+// Create the open invitation issue directive
+let open_invite_issue_directive = HashMap::from([
+       ("id", IssueType::Joint),
+       ("bucket", IssueType::Select),
+       ("trust_level", IssueType::Select), // Constant: 0
+       ("level_since", IssueType::Select), // Constant: 0
+       ("invites_remaining", IssueType::Select), // Constant: 0
+       ("blockages", IssueType::Select), // Constant: 0
+    ]);
+
+// Annotate the credential with the IssueType for each attribute, returning the 
+// AnnotatedIssueCredential
+let issue_cred = open_invite_cred.issue_annotated_request(open_invite_issue_directive);
+
+// Open Invite doesn't have a statement comparing issue and show annotated
+// credentials, but needs to commit to the joint issue lox id
+let (state, open_invite_issue_statement) =
+open_invite_cred.issue_request(vec![issue_cred], Statement::Empty); 
+(
+        Request {
+            invite: *invite,
+            issue_cred: 
+            open_invite_issue_statement
+        },
+        state
+    )
+
+}
+```
+
+
+Server Response:
+Receive an open invitation issued by the BridgeDb and if it is
+valid and fresh, issue a Lox credential at trust level 0.
+
+
+
+```
+impl BridgeAuth {
+
+pub fn issue_response(&self, Option<Vec<AnnotatedShowCredential>>, Vec<AnnotatedIssueCredential>, Statement) -> Statement, Credential;
+
+pub fn handle_open_invite(&mut self, req: Request) -> Result<Response, ProofError> {
+
+    // verify Invite from request: check signature and age are correct
+
+    // Create new Lox credential with mapped fields(String) -> Scalar
+    // Including both the private and public keys
+    let issue_statement, open_invite_issuecred = self.issue_response(None, req.issue_cred,
+    req.open_invite_issue_statement);
+
+    Response {
+      // This still needs work
+      // Yet another annotated credential with all of the attributes
+      // from the server + P and blinded Q
+      // ZKProof
+      // BridgeLine
+      open_invite_issuecred,
+      issue_statement,
+      BridgeLine,
+    }
+
+
+}
+```
+
+
+Handle the response to the request, producing the desired Lox
+credential if successful.
+```
+pub fn handle_response(
+    state: State,
+    resp: Response,
+    lox_pub: &IssuerPubKey,
+) -> Result<(cred::Lox, BridgeLine), ProofError> {
+
+// Pass the credential from the response to the annotated credential from the
+// client's state and call handle_response to form the final credential
+let lox_cred = state.annotated_cred.handle_response(resp.BlindedCredential, resp.Statement)
+
+Ok( lox_cred, resp.BridgeLine)
+}
+
+```