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;
|
pub const ENC_BUCKET_BYTES: usize = BUCKET_BYTES + 12 + 16;
|
||||||
|
|
||||||
/// A bridge information line
|
/// A bridge information line
|
||||||
#[derive(Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct BridgeLine {
|
pub struct BridgeLine {
|
||||||
/// IPv4 or IPv6 address
|
/// IPv4 or IPv6 address
|
||||||
pub addr: [u8; 16],
|
pub addr: [u8; 16],
|
||||||
|
|
|
@ -41,3 +41,19 @@ pub struct Lox {
|
||||||
pub P_noopmigration: RistrettoPoint,
|
pub P_noopmigration: RistrettoPoint,
|
||||||
pub Q_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 bridge_table;
|
||||||
pub mod cred;
|
pub mod cred;
|
||||||
pub mod dup_filter;
|
pub mod dup_filter;
|
||||||
|
pub mod migration_table;
|
||||||
|
pub mod trust_promotion;
|
||||||
|
|
||||||
use sha2::Sha512;
|
use sha2::Sha512;
|
||||||
|
|
||||||
|
@ -178,6 +180,10 @@ pub struct BridgeAuth {
|
||||||
migration_priv: IssuerPrivKey,
|
migration_priv: IssuerPrivKey,
|
||||||
/// The public key for migration credentials
|
/// The public key for migration credentials
|
||||||
pub migration_pub: IssuerPubKey,
|
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
|
/// The public key of the BridgeDb issuing open invitations
|
||||||
pub bridgedb_pub: PublicKey,
|
pub bridgedb_pub: PublicKey,
|
||||||
|
@ -185,10 +191,16 @@ pub struct BridgeAuth {
|
||||||
/// The bridge table
|
/// The bridge table
|
||||||
bridge_table: bridge_table::BridgeTable,
|
bridge_table: bridge_table::BridgeTable,
|
||||||
|
|
||||||
|
/// The migration table
|
||||||
|
migration_table: migration_table::MigrationTable,
|
||||||
|
|
||||||
/// Duplicate filter for open invitations
|
/// Duplicate filter for open invitations
|
||||||
openinv_filter: dup_filter::DupFilter<Scalar>,
|
openinv_filter: dup_filter::DupFilter<Scalar>,
|
||||||
/// Duplicate filter for credential ids
|
/// Duplicate filter for credential ids
|
||||||
id_filter: dup_filter::DupFilter<Scalar>,
|
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
|
/// For testing only: offset of the true time to the simulated time
|
||||||
time_offset: time::Duration,
|
time_offset: time::Duration,
|
||||||
|
@ -196,19 +208,27 @@ pub struct BridgeAuth {
|
||||||
|
|
||||||
impl BridgeAuth {
|
impl BridgeAuth {
|
||||||
pub fn new(bridgedb_pub: PublicKey) -> Self {
|
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_priv = IssuerPrivKey::new(6);
|
||||||
let lox_pub = IssuerPubKey::new(&lox_priv);
|
let lox_pub = IssuerPubKey::new(&lox_priv);
|
||||||
let migration_priv = IssuerPrivKey::new(3);
|
let migration_priv = IssuerPrivKey::new(3);
|
||||||
let migration_pub = IssuerPubKey::new(&migration_priv);
|
let migration_pub = IssuerPubKey::new(&migration_priv);
|
||||||
|
let migrationkey_priv = IssuerPrivKey::new(2);
|
||||||
|
let migrationkey_pub = IssuerPubKey::new(&migrationkey_priv);
|
||||||
Self {
|
Self {
|
||||||
lox_priv,
|
lox_priv,
|
||||||
lox_pub,
|
lox_pub,
|
||||||
migration_priv,
|
migration_priv,
|
||||||
migration_pub,
|
migration_pub,
|
||||||
|
migrationkey_priv,
|
||||||
|
migrationkey_pub,
|
||||||
bridgedb_pub,
|
bridgedb_pub,
|
||||||
bridge_table: Default::default(),
|
bridge_table: Default::default(),
|
||||||
|
migration_table: Default::default(),
|
||||||
openinv_filter: Default::default(),
|
openinv_filter: Default::default(),
|
||||||
id_filter: Default::default(),
|
id_filter: Default::default(),
|
||||||
|
trust_promotion_filter: Default::default(),
|
||||||
time_offset: time::Duration::zero(),
|
time_offset: time::Duration::zero(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -284,4 +304,48 @@ mod tests {
|
||||||
println!("cred = {:?}", cred);
|
println!("cred = {:?}", cred);
|
||||||
println!("bucket = {:?}", bucket);
|
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