|
|
@@ -0,0 +1,182 @@
|
|
|
+Trust Promotion Credential
|
|
|
+
|
|
|
+`use super::super::cred;`
|
|
|
+`use super::super::cmz::{IssueType, ShowType};`
|
|
|
+
|
|
|
+```
|
|
|
+/// The minimum number of days a user has to be at trust level 0
|
|
|
+/// (untrusted) with their (single) bridge unblocked before they can
|
|
|
+/// move to level 1.
|
|
|
+///
|
|
|
+/// The implementation also puts an upper bound of UNTRUSTED_INTERVAL +
|
|
|
+/// 511 days, which is not unreasonable; we want users to be engaging
|
|
|
+/// with the system in order to move up trust levels.
|
|
|
+pub const UNTRUSTED_INTERVAL: u32 = 30;
|
|
|
+
|
|
|
+#[serde_as]
|
|
|
+#[derive(Serialize, Deserialize)]
|
|
|
+pub struct Request {
|
|
|
+ // 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 {
|
|
|
+ // The encrypted MAC for the Migration Key credential
|
|
|
+ Pk: RistrettoPoint,
|
|
|
+ BlindMigKeyQk: RistrettoPoint,
|
|
|
+
|
|
|
+ // A table of encrypted Migration credentials; the encryption keys
|
|
|
+ // are formed from the possible values of Qk (the decrypted form of
|
|
|
+ // EncQk)
|
|
|
+ #[serde_as(as = "Vec<(_,[_; migration_table::ENC_MIGRATION_BYTES])>")]
|
|
|
+ enc_migration_table: HashMap<[u8; 16], [u8; migration_table::ENC_MIGRATION_BYTES]>,
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+Generate statement takes two annotated credentials and proves each of the statements
|
|
|
+listed
|
|
|
+```
|
|
|
+generate_statement! {
|
|
|
+statement,
|
|
|
+"Trust Promotion Statement",
|
|
|
+(L, K, today, UNTRUSTED_INTERVAL):
|
|
|
+L.bucket = K.bucket,
|
|
|
+today+UNTRUSTED_INTERVAL >= L.level_since >= 511+UNTRUSTED_INTERVAL,
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+Client Request:
|
|
|
+```
|
|
|
+pub fn request(lox_cred: &cred::Lox, lox_pub: &IssuerPubKey, migkey_pub: &IssuerPubKey, today: u32) -> (Request, State) {
|
|
|
+
|
|
|
+// Create new Lox credential with mapped fields(String) -> Scalar
|
|
|
+let trust_promotion_cred = cred.Lox.annotate_cred(lox_cred, lox_pub);
|
|
|
+
|
|
|
+// The call to "show" for trust promotion has the following show types
|
|
|
+let trust_promotion_show_directive = HashMap::from([
|
|
|
+ ("id", ShowType::Reveal),
|
|
|
+ ("bucket", ShowType::Hide),
|
|
|
+ // Set to 0, no need to compute
|
|
|
+ ("trust_level", ShowType::Reveal),
|
|
|
+ // Prove that level since + UNTRUSTED_INTERVAL <= today
|
|
|
+ ("level_since", ShowType::Hide),
|
|
|
+ // Set to 0, no need to compute
|
|
|
+ ("invites_remaining", Scalar::Reveal),
|
|
|
+ // Set to 0, no need to compute
|
|
|
+ ("blockages", Scalar::Reveal),
|
|
|
+]);
|
|
|
+
|
|
|
+// Annotate the credential with the ShowType for each attribute, returning the
|
|
|
+// AnnotatedShowCredential
|
|
|
+let show_cred: AnnotatedShowCredential = trust_promo_cred.show_annotation(trust_promotion_show_directive);
|
|
|
+
|
|
|
+
|
|
|
+// Create annotated migration key credential directive
|
|
|
+let migration_key_cred_directive = MigrationKey {
|
|
|
+ id: lox_cred.id,
|
|
|
+ bucket: lox_cred.bucket,
|
|
|
+ };
|
|
|
+
|
|
|
+// Create new Migration Key credential with mapped fields(String) -> Scalar
|
|
|
+let migkey_cred = cred.MigrationKey.annotate(migration_key_cred_directive, migkey_pub);
|
|
|
+
|
|
|
+
|
|
|
+let trust_promo_mig_cred_issue_directive = HashMap::from([
|
|
|
+ ("id", IssueType::Reveal),
|
|
|
+ ("bucket", IssueType::Hide),
|
|
|
+ ]);
|
|
|
+
|
|
|
+// Annotate the credential with the IssueType for each attribute, returning the
|
|
|
+// AnnotatedIssueCredential
|
|
|
+let issue_cred = migkey_cred.issue_annotation(trust_promo_cred_issue_directive);
|
|
|
+
|
|
|
+// Trust promo statement
|
|
|
+let statement = statement::prove_statements {
|
|
|
+ L: trust_promo_cred,
|
|
|
+ K: migkey_cred,
|
|
|
+ UNTRUSTED_INTERVAL,
|
|
|
+ today,
|
|
|
+ },
|
|
|
+
|
|
|
+(
|
|
|
+
|
|
|
+trust_promo_cred.issue_request(vec![show_cred], vec![issue_cred], statement)
|
|
|
+
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+
|
|
|
+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_trust_promotion(&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.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)
|
|
|
+}
|
|
|
+
|
|
|
+```
|