|
@@ -0,0 +1,153 @@
|
|
|
|
|
+/*! A module for the protocol for the user to increase their trust level
|
|
|
|
|
+(from a level at least 1; use the trust promotion protocol to go from
|
|
|
|
|
+untrusted (level 0) to minimally trusted (level 1).
|
|
|
|
|
+
|
|
|
|
|
+They are allowed to do this as long as some amount of time (depending on
|
|
|
|
|
+their current level) has elapsed since their last level change, and they
|
|
|
|
|
+have a Bucket Reachability credential for their current bucket and
|
|
|
|
|
+today's date. (Such credentials are placed daily in the encrypted
|
|
|
|
|
+bridge table.)
|
|
|
|
|
+
|
|
|
|
|
+The user presents their current Lox credential:
|
|
|
|
|
+- id: revealed
|
|
|
|
|
+- bucket: blinded
|
|
|
|
|
+- trust_level: revealed, and must be at least 1
|
|
|
|
|
+- level_since: blinded, but proved in ZK that it's at least the
|
|
|
|
|
+ appropriate number of days ago
|
|
|
|
|
+- invites_remaining: blinded
|
|
|
|
|
+- blockages: blinded, but proved in ZK that it's at most the appropriate
|
|
|
|
|
+ blockage limit for the target trust level
|
|
|
|
|
+
|
|
|
|
|
+and a Bucket Reachability credential:
|
|
|
|
|
+- date: revealed to be today
|
|
|
|
|
+- bucket: blinded, but proved in ZK that it's the same as in the Lox
|
|
|
|
|
+ credential above
|
|
|
|
|
+
|
|
|
|
|
+and a new Lox credential to be issued:
|
|
|
|
|
+
|
|
|
|
|
+- id: jointly chosen by the user and BA
|
|
|
|
|
+- bucket: blinded, but proved in ZK that it's the same as in the Lox
|
|
|
|
|
+ credential above
|
|
|
|
|
+- trust_level: revealed to be one more than the trust level above
|
|
|
|
|
+- level_since: today
|
|
|
|
|
+- invites_remaining: revealed to be the number of invites for the new
|
|
|
|
|
+ level (note that the invites_remaining from the previous credential
|
|
|
|
|
+ are _not_ carried over)
|
|
|
|
|
+- blockages: blinded, but proved in ZK that it's the same as in the
|
|
|
|
|
+ Lox credential above
|
|
|
|
|
+
|
|
|
|
|
+*/
|
|
|
|
|
+
|
|
|
|
|
+use phf::{Map, phf_map};
|
|
|
|
|
+use super::super::cmz::{IssueType, ShowType};
|
|
|
|
|
+use super::super::lox_creds;
|
|
|
|
|
+use curve25519_dalek::ristretto::RistrettoPoint as G;
|
|
|
|
|
+
|
|
|
|
|
+/// The maximum trust level in the system. A user can run this level
|
|
|
|
|
+/// upgrade protocol when they're already at the max level; they will
|
|
|
|
|
+/// get a fresh invites_remaining batch, and reset their level_since
|
|
|
|
|
+/// field to today's date, but will remain in the max level.
|
|
|
|
|
+pub const MAX_LEVEL: usize = 4;
|
|
|
|
|
+
|
|
|
|
|
+/// DAYS_AGO\[i\] for i >= 1 is the minimum number of days a user
|
|
|
|
|
+/// must be at trust level i before advancing to level i+1 (or as above,
|
|
|
|
|
+/// remain at level i if i == MAX_LEVEL). Note that the
|
|
|
|
|
+/// DAYS_AGO\[0\] entry is a dummy; the trust_promotion protocol
|
|
|
|
|
+/// is used instead of this one to move from level 0 to level 1.
|
|
|
|
|
+pub const DAYS_AGO: [u32; MAX_LEVEL + 1] = [0, 14, 28, 56, 84];
|
|
|
|
|
+
|
|
|
|
|
+/// LEVEL_INVITATIONS\[i\] for i >= 1 is the number of invitations a
|
|
|
|
|
+/// user will be eligible to issue upon advancing from level i to level
|
|
|
|
|
+/// i+1. Again the LEVEL_INVITATIONS\[0\] entry is a dummy, as for
|
|
|
|
|
+/// DAYS_AGO.
|
|
|
|
|
+pub const LEVEL_INVITATIONS: [u32; MAX_LEVEL + 1] = [0, 2, 4, 6, 8];
|
|
|
|
|
+
|
|
|
|
|
+/// MAX_BLOCKAGES\[i\] for i >= 1 is the maximum number of bucket
|
|
|
|
|
+/// blockages this credential is allowed to have recorded in order to
|
|
|
|
|
+/// advance from level i to level i+1. Again the LEVEL_INVITATIONS\[0\]
|
|
|
|
|
+/// entry is a dummy, as for DAYS_AGO.
|
|
|
|
|
+// If you change this to have a number greater than 7, you need to add
|
|
|
|
|
+// one or more bits to the ZKP.
|
|
|
|
|
+pub const MAX_BLOCKAGES: [u32; MAX_LEVEL + 1] = [0, 4, 3, 2, 2];
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+static LOX_LEVEL_UP_SHOW: Map<&str, ShowType> = phf_map! {
|
|
|
|
|
+ "id" => ShowType::Reveal,
|
|
|
|
|
+ "bucket" => ShowType::Hide,
|
|
|
|
|
+ "trust_level" => ShowType::Reveal,
|
|
|
|
|
+ "level_since" => ShowType::Hide,
|
|
|
|
|
+ "invites_remaining" => ShowType::Hide,
|
|
|
|
|
+ "blockages" => ShowType::Hide,
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+static REACHABILITY_SHOW: Map<&str, ShowType> = phf_map! {
|
|
|
|
|
+ "date" => ShowType::Reveal,
|
|
|
|
|
+ "bucket" => ShowType::Hide,
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+static LOX_LEVEL_UP_ISSUE: Map<&str, IssueType> = phf_map! {
|
|
|
|
|
+ "id" => IssueType::Joint,
|
|
|
|
|
+ "bucket" => IssueType::Hide,
|
|
|
|
|
+ "trust_level" => IssueType::Reveal,
|
|
|
|
|
+ "level_since" => IssueType::Server,
|
|
|
|
|
+ "invites_remaining" => IssueType::Implicit, // determined by trust_level
|
|
|
|
|
+ "blockages" => IssueType::Hide,
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+let level_up = CMZ.Protocol(
|
|
|
|
|
+ vec![("L", lox_creds::Lox::attrs(), LOX_LEVEL_UP_SHOW),
|
|
|
|
|
+ ("BR", Reachability::attrs(), REACHABILITY_SHOW)],
|
|
|
|
|
+ vec![("NEW", Lox::attrs(), LOX_LEVEL_UP_ISSUE)],
|
|
|
|
|
+ statement,
|
|
|
|
|
+ request_message
|
|
|
|
|
+);
|
|
|
|
|
+
|
|
|
|
|
+let statement = Statement! {
|
|
|
|
|
+ today-(DAYS_AGO[level]+511) <= L.level_since <= today-DAYS_AGO[level],
|
|
|
|
|
+ 0 <= L.blockages <= MAX_BLOCKAGES[level+1],
|
|
|
|
|
+ BR.bucket = L.bucket,
|
|
|
|
|
+ NEW.bucket = L.bucket,
|
|
|
|
|
+ NEW.blockages = L.blockages,
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+pub fn request(lox_credential: lox_creds::Lox, reachability_credential: lox_cred::Bucket,
|
|
|
|
|
+pubkeys: IssuerPubKeys) -> Result<(Vec<u8>, State), Error> {
|
|
|
|
|
+
|
|
|
|
|
+ // TODO: Check everything required for the lox_credential to run
|
|
|
|
|
+ // this protocol
|
|
|
|
|
+ let new_lox_credential = lox_creds::Lox::default();
|
|
|
|
|
+ let mut rng = rand::thread_rng();
|
|
|
|
|
+ new_lox_credential.id = Some(<G as Group>::Scalar::random(&mut rng));
|
|
|
|
|
+ new_lox_credential.bucket = Some(lox_credential.bucket);
|
|
|
|
|
+ new_lox_credential.trust_level = Some((lox_credential.trust_level as usize + 1).into());
|
|
|
|
|
+ new_lox_credential.invites_remaining = Some(LEVEL_INVITATIONS[trust_level as usize].into())
|
|
|
|
|
+ new_lox_credential.blockages = Some(lox_credential.blockages);
|
|
|
|
|
+
|
|
|
|
|
+ // TODO: Allocate pubkeys somehow
|
|
|
|
|
+ match level_up.show_issue(
|
|
|
|
|
+ vec![&lox_credential, &reachability_credential],
|
|
|
|
|
+ vec![&mut new_lox_credential]) {
|
|
|
|
|
+ Ok(request_message, state) => Ok(request_message, state),
|
|
|
|
|
+ Err(e) => Error(e),
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+impl BridgeAuth {
|
|
|
|
|
+
|
|
|
|
|
+ pub fn handle_level_up(&mut self, req: Request) -> Result<Response,
|
|
|
|
|
+ProofError> {
|
|
|
|
|
+
|
|
|
|
|
+ let public_verify = TODO;
|
|
|
|
|
+ level_up.handle(
|
|
|
|
|
+ vec![&mut req.lox_credential, &mut req.reachability_credential],
|
|
|
|
|
+ vec![&mut req.new_lox_credential],
|
|
|
|
|
+ public_verify)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+pub fn handle_response(state: State, resp: Response) -> Result<Vec<Credential>, ProofError> {
|
|
|
|
|
+ match cmz_finalize(client_state, response_message) {
|
|
|
|
|
+ Ok(Vec<Credential>) => Ok(Vec<Credential>),
|
|
|
|
|
+ Err(e) => ProofError(e),
|
|
|
|
|
+ }
|
|
|
|
|
+}
|