Start on trust promotion
This is the protocol for the user to get promoted from untrusted (trust level 0) to trusted (trust level 1).
This commit is contained in:
parent
b86973174a
commit
e7bb50ab2b
|
@ -29,7 +29,7 @@ pub const BUCKET_BYTES: usize = BRIDGE_BYTES * MAX_BRIDGES_PER_BUCKET;
|
|||
pub const ENC_BUCKET_BYTES: usize = BUCKET_BYTES + 12 + 16;
|
||||
|
||||
/// A bridge information line
|
||||
#[derive(Debug)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct BridgeLine {
|
||||
/// IPv4 or IPv6 address
|
||||
pub addr: [u8; 16],
|
||||
|
|
|
@ -41,3 +41,19 @@ pub struct Lox {
|
|||
pub P_noopmigration: RistrettoPoint,
|
||||
pub Q_noopmigration: RistrettoPoint,
|
||||
}
|
||||
|
||||
// The migration key credential is never actually instantiated. It is
|
||||
// an implicit credential with the following attributes:
|
||||
// - lox_id: Scalar,
|
||||
// - from_bucket: Scalar
|
||||
// Plus the usual (P,Q) MAC. This credential type does have an
|
||||
// associated private and public key, however. The idea is that if a
|
||||
// user proves (in zero knowledge) that their Lox credential entitles
|
||||
// them to migrate from one bucket to another, the BA will issue a
|
||||
// (blinded, so the BA will not know the values of the attributes or of
|
||||
// Q) MAC on this implicit credential. The Q value will then be used
|
||||
// (actually, a hash of lox_id, from_bucket, and Q) to encrypt the
|
||||
// to_bucket, P, and Q fields of a Migration credential. That way,
|
||||
// people entitled to migrate buckets can receive a Migration credential
|
||||
// with their new bucket, without the BA learning either their old or
|
||||
// new buckets.
|
||||
|
|
|
@ -20,6 +20,8 @@ extern crate zkp;
|
|||
pub mod bridge_table;
|
||||
pub mod cred;
|
||||
pub mod dup_filter;
|
||||
pub mod migration_table;
|
||||
pub mod trust_promotion;
|
||||
|
||||
use sha2::Sha512;
|
||||
|
||||
|
@ -178,6 +180,10 @@ pub struct BridgeAuth {
|
|||
migration_priv: IssuerPrivKey,
|
||||
/// The public key for migration credentials
|
||||
pub migration_pub: IssuerPubKey,
|
||||
/// The private key for migration key credentials
|
||||
migrationkey_priv: IssuerPrivKey,
|
||||
/// The public key for migration key credentials
|
||||
pub migrationkey_pub: IssuerPubKey,
|
||||
|
||||
/// The public key of the BridgeDb issuing open invitations
|
||||
pub bridgedb_pub: PublicKey,
|
||||
|
@ -185,10 +191,16 @@ pub struct BridgeAuth {
|
|||
/// The bridge table
|
||||
bridge_table: bridge_table::BridgeTable,
|
||||
|
||||
/// The migration table
|
||||
migration_table: migration_table::MigrationTable,
|
||||
|
||||
/// Duplicate filter for open invitations
|
||||
openinv_filter: dup_filter::DupFilter<Scalar>,
|
||||
/// Duplicate filter for credential ids
|
||||
id_filter: dup_filter::DupFilter<Scalar>,
|
||||
/// Duplicate filter for trust promotions (from untrusted level 0 to
|
||||
/// trusted level 1)
|
||||
trust_promotion_filter: dup_filter::DupFilter<Scalar>,
|
||||
|
||||
/// For testing only: offset of the true time to the simulated time
|
||||
time_offset: time::Duration,
|
||||
|
@ -196,19 +208,27 @@ pub struct BridgeAuth {
|
|||
|
||||
impl BridgeAuth {
|
||||
pub fn new(bridgedb_pub: PublicKey) -> Self {
|
||||
// Create the private and public keys for each of the types of
|
||||
// credential, each with the appropriate number of attributes
|
||||
let lox_priv = IssuerPrivKey::new(6);
|
||||
let lox_pub = IssuerPubKey::new(&lox_priv);
|
||||
let migration_priv = IssuerPrivKey::new(3);
|
||||
let migration_pub = IssuerPubKey::new(&migration_priv);
|
||||
let migrationkey_priv = IssuerPrivKey::new(2);
|
||||
let migrationkey_pub = IssuerPubKey::new(&migrationkey_priv);
|
||||
Self {
|
||||
lox_priv,
|
||||
lox_pub,
|
||||
migration_priv,
|
||||
migration_pub,
|
||||
migrationkey_priv,
|
||||
migrationkey_pub,
|
||||
bridgedb_pub,
|
||||
bridge_table: Default::default(),
|
||||
migration_table: Default::default(),
|
||||
openinv_filter: Default::default(),
|
||||
id_filter: Default::default(),
|
||||
trust_promotion_filter: Default::default(),
|
||||
time_offset: time::Duration::zero(),
|
||||
}
|
||||
}
|
||||
|
@ -284,4 +304,48 @@ mod tests {
|
|||
println!("cred = {:?}", cred);
|
||||
println!("bucket = {:?}", bucket);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trust_promotion() {
|
||||
// Create a BridegDb
|
||||
let bdb = BridgeDb::new(15);
|
||||
// Create a BridgeAuth
|
||||
let mut ba = BridgeAuth::new(bdb.pubkey);
|
||||
|
||||
// Make 15 buckets with one random bridge each
|
||||
for _ in 0..15 {
|
||||
let bucket: [BridgeLine; 3] =
|
||||
[BridgeLine::random(), Default::default(), Default::default()];
|
||||
ba.bridge_table.new_bucket(bucket);
|
||||
}
|
||||
// Make 5 more buckets, each containing 3 of the previously
|
||||
// created bridges
|
||||
for i in 0u32..5 {
|
||||
let iusize = i as usize;
|
||||
let bucket: [BridgeLine; 3] = [
|
||||
ba.bridge_table.buckets[3 * iusize][0],
|
||||
ba.bridge_table.buckets[3 * iusize + 1][0],
|
||||
ba.bridge_table.buckets[3 * iusize + 2][0],
|
||||
];
|
||||
ba.bridge_table.new_bucket(bucket);
|
||||
// Add the allowed migrations to the migration table
|
||||
ba.migration_table.table.push((3 * i, 15 + i));
|
||||
ba.migration_table.table.push((3 * i + 1, 15 + i));
|
||||
ba.migration_table.table.push((3 * i + 2, 15 + i));
|
||||
}
|
||||
// Create the encrypted bridge table
|
||||
ba.bridge_table.encrypt_table();
|
||||
|
||||
// Issue an open invitation
|
||||
let inv = bdb.invite();
|
||||
|
||||
// Use it to get a Lox credential
|
||||
let (req, state) = open_invite::request(&inv);
|
||||
let resp = ba.handle_open_invite(req).unwrap();
|
||||
let cred =
|
||||
open_invite::handle_response(state, resp, &ba.lox_pub, &ba.migration_pub).unwrap();
|
||||
|
||||
// Time passes
|
||||
ba.advance_days(40);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
/*! The migration table.
|
||||
|
||||
This is a table listing pairs of (from_bucket_id, to_bucket_id). A pair
|
||||
in this table indicates that a user with a Lox credential containing
|
||||
from_bucket_id (and possibly meeting other conditions as well) is
|
||||
entitled to exchange their credential for one with to_bucket_id. (Note
|
||||
that the credentials contain the bucket attributes, which include both
|
||||
the id and the bucket decrytpion key, but the table just contains the
|
||||
bucket ids.) */
|
||||
|
||||
/// The migration table
|
||||
#[derive(Default, Debug)]
|
||||
pub struct MigrationTable {
|
||||
pub table: Vec<(u32, u32)>,
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*! A module for the protocol for the user to get promoted from
|
||||
untrusted (trust level 0) to trusted (trust level 1).
|
||||
|
||||
They are allowed to do this as long as UNTRUSTED_INTERVAL days have
|
||||
passed since they obtained their level 0 Lox credential, and their
|
||||
bridge (level 0 users get put in a one-bridge bucket) has not been
|
||||
blocked. (Blocked bridges in one-bridge buckets will have their entries
|
||||
removed from the bridge authority's migration table.)
|
||||
|
||||
The user presents their current Lox credential:
|
||||
- id: revealed
|
||||
- bucket: blinded
|
||||
- trust_level: revealed to be 0
|
||||
- level_since: blinded, but proved in ZK that it's at least
|
||||
UNTRUSTED_INTERVAL days ago
|
||||
- invites_remaining: revealed to be 0
|
||||
- invites_issued: revealed to be 0
|
||||
|
||||
They will receive in return the encrypted MAC (Pk, EncQk) for their
|
||||
implicit Migration Key credential with attributes id and bucket,
|
||||
along with a HashMap of encrypted Migration credentials. For each
|
||||
(from_i, to_i) in the BA's migration list, there will be an entry in
|
||||
the HashMap with key H1(id, from_attr_i, Qk_i) and value
|
||||
Enc_{H2(id, from_attr_i, Qk_i)}(to_attr_i, P_i, Q_i). Here H1 and H2
|
||||
are the first 16 bytes and the second 16 bytes respectively of the
|
||||
SHA256 hash of the input, P_i and Q_i are a MAC on the Migration
|
||||
credential with attributes id, from_attr_i, and to_attr_i. Qk_i is the
|
||||
value EncQk would decrypt to if bucket were equal to from_attr_i. */
|
||||
|
||||
use curve25519_dalek::ristretto::RistrettoBasepointTable;
|
||||
use curve25519_dalek::ristretto::RistrettoPoint;
|
||||
use curve25519_dalek::scalar::Scalar;
|
||||
use curve25519_dalek::traits::IsIdentity;
|
||||
|
||||
use zkp::CompactProof;
|
||||
use zkp::ProofError;
|
||||
use zkp::Transcript;
|
||||
|
||||
/// 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: u64 = 30;
|
||||
|
||||
pub struct Request {
|
||||
id: Scalar,
|
||||
}
|
Loading…
Reference in New Issue