The request message of the issue invitation protocol
This commit is contained in:
parent
654208769f
commit
d924b98060
|
@ -75,3 +75,21 @@ pub struct BucketReachability {
|
||||||
pub date: Scalar,
|
pub date: Scalar,
|
||||||
pub bucket: Scalar,
|
pub bucket: Scalar,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The Invitation credential.
|
||||||
|
///
|
||||||
|
/// These credentials allow a Lox user (the inviter) of sufficient trust
|
||||||
|
/// (level 2 or higher) to invite someone else (the invitee) to join the
|
||||||
|
/// system. The invitee ends up at trust level 1, in the _same bucket_
|
||||||
|
/// as the inviter, and inherits the inviter's blockages count (so that
|
||||||
|
/// you can't clear your blockages count simply by inviting yourself).
|
||||||
|
/// Invitations expire after some amount of time.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Invitation {
|
||||||
|
pub P: RistrettoPoint,
|
||||||
|
pub Q: RistrettoPoint,
|
||||||
|
pub inv_id: Scalar,
|
||||||
|
pub date: Scalar,
|
||||||
|
pub bucket: Scalar,
|
||||||
|
pub blockages: Scalar,
|
||||||
|
}
|
||||||
|
|
|
@ -190,6 +190,10 @@ pub struct BridgeAuth {
|
||||||
reachability_priv: IssuerPrivKey,
|
reachability_priv: IssuerPrivKey,
|
||||||
/// The public key for bucket reachability credentials
|
/// The public key for bucket reachability credentials
|
||||||
pub reachability_pub: IssuerPubKey,
|
pub reachability_pub: IssuerPubKey,
|
||||||
|
/// The private key for invitation credentials
|
||||||
|
invitation_priv: IssuerPrivKey,
|
||||||
|
/// The public key for invitation credentials
|
||||||
|
pub invitation_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,
|
||||||
|
@ -224,6 +228,8 @@ impl BridgeAuth {
|
||||||
let migrationkey_pub = IssuerPubKey::new(&migrationkey_priv);
|
let migrationkey_pub = IssuerPubKey::new(&migrationkey_priv);
|
||||||
let reachability_priv = IssuerPrivKey::new(2);
|
let reachability_priv = IssuerPrivKey::new(2);
|
||||||
let reachability_pub = IssuerPubKey::new(&reachability_priv);
|
let reachability_pub = IssuerPubKey::new(&reachability_priv);
|
||||||
|
let invitation_priv = IssuerPrivKey::new(4);
|
||||||
|
let invitation_pub = IssuerPubKey::new(&invitation_priv);
|
||||||
Self {
|
Self {
|
||||||
lox_priv,
|
lox_priv,
|
||||||
lox_pub,
|
lox_pub,
|
||||||
|
@ -233,6 +239,8 @@ impl BridgeAuth {
|
||||||
migrationkey_pub,
|
migrationkey_pub,
|
||||||
reachability_priv,
|
reachability_priv,
|
||||||
reachability_pub,
|
reachability_pub,
|
||||||
|
invitation_priv,
|
||||||
|
invitation_pub,
|
||||||
bridgedb_pub,
|
bridgedb_pub,
|
||||||
bridge_table: Default::default(),
|
bridge_table: Default::default(),
|
||||||
migration_table: Default::default(),
|
migration_table: Default::default(),
|
||||||
|
@ -329,6 +337,23 @@ impl BridgeAuth {
|
||||||
|
|
||||||
Q == cred.Q
|
Q == cred.Q
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
/// Verify the MAC on a Invitation credential
|
||||||
|
pub fn verify_invitation(&self, cred: &cred::Invitation) -> bool {
|
||||||
|
if cred.P.is_identity() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let Q = (self.invitation_priv.x[0]
|
||||||
|
+ cred.inv_id * self.invitation_priv.x[1]
|
||||||
|
+ cred.date * self.invitation_priv.x[2]
|
||||||
|
+ cred.bucket * self.invitation_priv.x[3]
|
||||||
|
+ cred.blockages * self.invitation_priv.x[4])
|
||||||
|
* cred.P;
|
||||||
|
|
||||||
|
Q == cred.Q
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try to extract a u64 from a Scalar
|
/// Try to extract a u64 from a Scalar
|
||||||
|
@ -372,6 +397,7 @@ pub fn pt_dbl(P: &RistrettoPoint) -> RistrettoPoint {
|
||||||
/// Response. It also adds a handle_* function to the BridgeAuth struct
|
/// Response. It also adds a handle_* function to the BridgeAuth struct
|
||||||
/// that consumes a Request and produces a Result<Response, ProofError>.
|
/// that consumes a Request and produces a Result<Response, ProofError>.
|
||||||
pub mod proto {
|
pub mod proto {
|
||||||
|
pub mod issue_invite;
|
||||||
pub mod level_up;
|
pub mod level_up;
|
||||||
pub mod migration;
|
pub mod migration;
|
||||||
pub mod open_invite;
|
pub mod open_invite;
|
||||||
|
|
|
@ -0,0 +1,443 @@
|
||||||
|
/*! A module for the protocol for a user to request the issuing of an
|
||||||
|
Invitation credential they can pass to someone they know.
|
||||||
|
|
||||||
|
They are allowed to do this as long as their current Lox credentials has
|
||||||
|
a non-zero "invites_remaining" attribute (which will be decreased by
|
||||||
|
one), 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: blinded
|
||||||
|
- level_since: blinded
|
||||||
|
- invites_remaining: blinded, but proved in ZK that it's not zero
|
||||||
|
- blockages: blinded
|
||||||
|
|
||||||
|
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: blinded, but proved in ZK that it's the same as in the
|
||||||
|
Lox credential above
|
||||||
|
- level_since: blinded, but proved in ZK that it's the same as in the
|
||||||
|
Lox credential above
|
||||||
|
- invites_remaining: blinded, but proved in ZK that it's one less than
|
||||||
|
the number in the Lox credential above
|
||||||
|
- blockages: blinded, but proved in ZK that it's the same as in the
|
||||||
|
Lox credential above
|
||||||
|
|
||||||
|
and a new Invitation credential to be issued:
|
||||||
|
|
||||||
|
- inv_id: jointly chosen by the user and BA
|
||||||
|
- date: revealed to be today
|
||||||
|
- bucket: blinded, but proved in ZK that it's the same as in the Lox
|
||||||
|
credential above
|
||||||
|
- blockages: blinded, but proved in ZK that it's the same as in the Lox
|
||||||
|
credential above
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
use super::super::cred;
|
||||||
|
use super::super::dup_filter::SeenType;
|
||||||
|
use super::super::{pt_dbl, scalar_dbl, scalar_u32};
|
||||||
|
use super::super::{BridgeAuth, IssuerPubKey};
|
||||||
|
use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE};
|
||||||
|
|
||||||
|
pub struct Request {
|
||||||
|
// Fields for blind showing the Lox credential
|
||||||
|
P: RistrettoPoint,
|
||||||
|
id: Scalar,
|
||||||
|
CBucket: RistrettoPoint,
|
||||||
|
CLevel: RistrettoPoint,
|
||||||
|
CSince: RistrettoPoint,
|
||||||
|
CInvRemain: RistrettoPoint,
|
||||||
|
CBlockages: RistrettoPoint,
|
||||||
|
CQ: RistrettoPoint,
|
||||||
|
|
||||||
|
// Fields for blind showing the Bucket Reachability credential
|
||||||
|
P_reach: RistrettoPoint,
|
||||||
|
CBucket_reach: RistrettoPoint,
|
||||||
|
CQ_reach: RistrettoPoint,
|
||||||
|
|
||||||
|
// Fields for user blinding of the Lox credential to be issued
|
||||||
|
D: RistrettoPoint,
|
||||||
|
EncIdClient: (RistrettoPoint, RistrettoPoint),
|
||||||
|
EncBucket: (RistrettoPoint, RistrettoPoint),
|
||||||
|
EncLevel: (RistrettoPoint, RistrettoPoint),
|
||||||
|
EncSince: (RistrettoPoint, RistrettoPoint),
|
||||||
|
EncInvRemain: (RistrettoPoint, RistrettoPoint),
|
||||||
|
EncBlockages: (RistrettoPoint, RistrettoPoint),
|
||||||
|
|
||||||
|
// Fields for user blinding of the Inivtation credential to be
|
||||||
|
// issued
|
||||||
|
EncInvIdClient: (RistrettoPoint, RistrettoPoint),
|
||||||
|
// The bucket and blockages attributes in the Invitation credential
|
||||||
|
// issuing protocol can just reuse the exact encryptions as for the
|
||||||
|
// Lox credential issuing protocol above.
|
||||||
|
|
||||||
|
// The combined ZKP
|
||||||
|
piUser: CompactProof,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct State {
|
||||||
|
d: Scalar,
|
||||||
|
D: RistrettoPoint,
|
||||||
|
EncIdClient: (RistrettoPoint, RistrettoPoint),
|
||||||
|
EncBucket: (RistrettoPoint, RistrettoPoint),
|
||||||
|
EncLevel: (RistrettoPoint, RistrettoPoint),
|
||||||
|
EncSince: (RistrettoPoint, RistrettoPoint),
|
||||||
|
EncInvRemain: (RistrettoPoint, RistrettoPoint),
|
||||||
|
EncBlockages: (RistrettoPoint, RistrettoPoint),
|
||||||
|
EncInvIdClient: (RistrettoPoint, RistrettoPoint),
|
||||||
|
id_client: Scalar,
|
||||||
|
bucket: Scalar,
|
||||||
|
level: Scalar,
|
||||||
|
since: Scalar,
|
||||||
|
invremain: Scalar,
|
||||||
|
blockages: Scalar,
|
||||||
|
inv_id_client: Scalar,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Response {
|
||||||
|
// The fields for the new Lox credential; the new invites_remaining
|
||||||
|
// is one less than the old value, so we don't have to include it
|
||||||
|
// here explicitly
|
||||||
|
P: RistrettoPoint,
|
||||||
|
EncQ: (RistrettoPoint, RistrettoPoint),
|
||||||
|
id_server: Scalar,
|
||||||
|
TId: RistrettoPoint,
|
||||||
|
TBucket: RistrettoPoint,
|
||||||
|
TLevel: RistrettoPoint,
|
||||||
|
TSince: RistrettoPoint,
|
||||||
|
TInvRemain: RistrettoPoint,
|
||||||
|
TBlockages: RistrettoPoint,
|
||||||
|
inv_id_server: Scalar,
|
||||||
|
TInvId: RistrettoPoint,
|
||||||
|
|
||||||
|
// The ZKP
|
||||||
|
piBlindIssue: CompactProof,
|
||||||
|
}
|
||||||
|
|
||||||
|
define_proof! {
|
||||||
|
requestproof,
|
||||||
|
"Issue Invite Request",
|
||||||
|
(bucket, level, since, invremain, blockages, zbucket, zlevel,
|
||||||
|
zsince, zinvremain, zblockages, negzQ,
|
||||||
|
zbucket_reach, negzQ_reach,
|
||||||
|
d, eid_client, ebucket, elevel, esince, einvremain, eblockages, id_client,
|
||||||
|
inv_id_client, einv_id_client,
|
||||||
|
invremain_inverse, zinvremain_inverse),
|
||||||
|
(P, CBucket, CLevel, CSince, CInvRemain, CBlockages, V, Xbucket,
|
||||||
|
Xlevel, Xsince, Xinvremain, Xblockages,
|
||||||
|
P_reach, CBucket_reach, V_reach, Xbucket_reach,
|
||||||
|
D, EncIdClient0, EncIdClient1, EncBucket0, EncBucket1,
|
||||||
|
EncLevel0, EncLevel1, EncSince0, EncSince1,
|
||||||
|
EncInvRemain0, EncInvRemain1_plus_B, EncBlockages0, EncBlockages1,
|
||||||
|
EncInvIdClient0, EncInvIdClient1),
|
||||||
|
(A, B):
|
||||||
|
// Blind showing of the Lox credential
|
||||||
|
CBucket = (bucket*P + zbucket*A),
|
||||||
|
CLevel = (level*P + zlevel*A),
|
||||||
|
CSince = (since*P + zsince*A),
|
||||||
|
CInvRemain = (invremain*P + zinvremain*A),
|
||||||
|
CBlockages = (blockages*P + zblockages*A),
|
||||||
|
// Proof that invremain is not 0
|
||||||
|
P = (invremain_inverse*CInvRemain + zinvremain_inverse*A),
|
||||||
|
// Blind showing of the Bucket Reachability credential; note the
|
||||||
|
// same bucket is used in the proof
|
||||||
|
CBucket_reach = (bucket*P_reach + zbucket_reach*A),
|
||||||
|
// User blinding of the Lox credential to be issued
|
||||||
|
D = (d*B),
|
||||||
|
EncIdClient0 = (eid_client*B),
|
||||||
|
EncIdClient1 = (id_client*B + eid_client*D),
|
||||||
|
EncBucket0 = (ebucket*B),
|
||||||
|
EncBucket1 = (bucket*B + ebucket*D),
|
||||||
|
EncLevel0 = (elevel*B),
|
||||||
|
EncLevel1 = (level*B + elevel*D),
|
||||||
|
EncSince0 = (esince*B),
|
||||||
|
EncSince1 = (since*B + esince*D),
|
||||||
|
EncInvRemain0 = (einvremain*B),
|
||||||
|
EncInvRemain1_plus_B = (invremain*B + einvremain*D),
|
||||||
|
EncBlockages0 = (eblockages*B),
|
||||||
|
EncBlockages1 = (blockages*B + eblockages*D),
|
||||||
|
// User blinding of the Invitation to be issued
|
||||||
|
EncInvIdClient0 = (einv_id_client*B),
|
||||||
|
EncInvIdClient1 = (inv_id_client*B + einv_id_client*D)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn request(
|
||||||
|
lox_cred: &cred::Lox,
|
||||||
|
reach_cred: &cred::BucketReachability,
|
||||||
|
lox_pub: &IssuerPubKey,
|
||||||
|
reach_pub: &IssuerPubKey,
|
||||||
|
today: u32,
|
||||||
|
) -> Result<(Request, State), ProofError> {
|
||||||
|
let A: &RistrettoPoint = &CMZ_A;
|
||||||
|
let B: &RistrettoPoint = &CMZ_B;
|
||||||
|
let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE;
|
||||||
|
let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE;
|
||||||
|
|
||||||
|
// Ensure the credential can be correctly shown: it must be the case
|
||||||
|
// that invites_remaining not be 0
|
||||||
|
if lox_cred.invites_remaining == Scalar::zero() {
|
||||||
|
return Err(ProofError::VerificationFailure);
|
||||||
|
}
|
||||||
|
// The buckets in the Lox and Bucket Reachability credentials have
|
||||||
|
// to match
|
||||||
|
if lox_cred.bucket != reach_cred.bucket {
|
||||||
|
return Err(ProofError::VerificationFailure);
|
||||||
|
}
|
||||||
|
// The Bucket Reachability credential has to be dated today
|
||||||
|
let reach_date: u32 = match scalar_u32(&reach_cred.date) {
|
||||||
|
Some(v) => v,
|
||||||
|
None => return Err(ProofError::VerificationFailure),
|
||||||
|
};
|
||||||
|
if reach_date != today {
|
||||||
|
return Err(ProofError::VerificationFailure);
|
||||||
|
}
|
||||||
|
// The new invites_remaining
|
||||||
|
let new_invites_remaining = &lox_cred.invites_remaining - Scalar::one();
|
||||||
|
|
||||||
|
// Blind showing the Lox credential
|
||||||
|
|
||||||
|
// Reblind P and Q
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
let t = Scalar::random(&mut rng);
|
||||||
|
let P = t * lox_cred.P;
|
||||||
|
let Q = t * lox_cred.Q;
|
||||||
|
|
||||||
|
// Form Pedersen commitments to the blinded attributes
|
||||||
|
let zbucket = Scalar::random(&mut rng);
|
||||||
|
let zlevel = Scalar::random(&mut rng);
|
||||||
|
let zsince = Scalar::random(&mut rng);
|
||||||
|
let zinvremain = Scalar::random(&mut rng);
|
||||||
|
let zblockages = Scalar::random(&mut rng);
|
||||||
|
let CBucket = lox_cred.bucket * P + &zbucket * Atable;
|
||||||
|
let CLevel = lox_cred.bucket * P + &zlevel * Atable;
|
||||||
|
let CSince = lox_cred.level_since * P + &zsince * Atable;
|
||||||
|
let CInvRemain = lox_cred.invites_remaining * P + &zinvremain * Atable;
|
||||||
|
let CBlockages = lox_cred.blockages * P + &zblockages * Atable;
|
||||||
|
|
||||||
|
// Form a Pedersen commitment to the MAC Q
|
||||||
|
// We flip the sign of zQ from that of the Hyphae paper so that
|
||||||
|
// the ZKP has a "+" instead of a "-", as that's what the zkp
|
||||||
|
// macro supports.
|
||||||
|
let negzQ = Scalar::random(&mut rng);
|
||||||
|
let CQ = Q - &negzQ * Atable;
|
||||||
|
|
||||||
|
// Compute the "error factor"
|
||||||
|
let V = zbucket * lox_pub.X[2]
|
||||||
|
+ zlevel * lox_pub.X[3]
|
||||||
|
+ zsince * lox_pub.X[4]
|
||||||
|
+ zinvremain * lox_pub.X[5]
|
||||||
|
+ zblockages * lox_pub.X[6]
|
||||||
|
+ &negzQ * Atable;
|
||||||
|
|
||||||
|
// Blind showing the Bucket Reachability credential
|
||||||
|
|
||||||
|
// Reblind P and Q
|
||||||
|
let t_reach = Scalar::random(&mut rng);
|
||||||
|
let P_reach = t_reach * reach_cred.P;
|
||||||
|
let Q_reach = t_reach * reach_cred.Q;
|
||||||
|
|
||||||
|
// Form Pedersen commitments to the blinded attributes
|
||||||
|
let zbucket_reach = Scalar::random(&mut rng);
|
||||||
|
let CBucket_reach = reach_cred.bucket * P_reach + &zbucket_reach * Atable;
|
||||||
|
|
||||||
|
// Form a Pedersen commitment to the MAC Q
|
||||||
|
// We flip the sign of zQ from that of the Hyphae paper so that
|
||||||
|
// the ZKP has a "+" instead of a "-", as that's what the zkp
|
||||||
|
// macro supports.
|
||||||
|
let negzQ_reach = Scalar::random(&mut rng);
|
||||||
|
let CQ_reach = Q_reach - &negzQ_reach * Atable;
|
||||||
|
|
||||||
|
// Compute the "error factor"
|
||||||
|
let V_reach = zbucket_reach * reach_pub.X[2] + &negzQ_reach * Atable;
|
||||||
|
|
||||||
|
// User blinding for the Lox certificate to be issued
|
||||||
|
|
||||||
|
// Pick an ElGamal keypair
|
||||||
|
let d = Scalar::random(&mut rng);
|
||||||
|
let D = &d * Btable;
|
||||||
|
|
||||||
|
// Pick a random client component of the id
|
||||||
|
let id_client = Scalar::random(&mut rng);
|
||||||
|
|
||||||
|
// Encrypt it (times the basepoint B) to the ElGamal public key D we
|
||||||
|
// just created
|
||||||
|
let eid_client = Scalar::random(&mut rng);
|
||||||
|
let EncIdClient = (&eid_client * Btable, &id_client * Btable + eid_client * D);
|
||||||
|
|
||||||
|
// Encrypt the other blinded fields (times B) to D as well
|
||||||
|
let ebucket = Scalar::random(&mut rng);
|
||||||
|
let EncBucket = (&ebucket * Btable, &lox_cred.bucket * Btable + ebucket * D);
|
||||||
|
let elevel = Scalar::random(&mut rng);
|
||||||
|
let EncLevel = (
|
||||||
|
&elevel * Btable,
|
||||||
|
&lox_cred.trust_level * Btable + elevel * D,
|
||||||
|
);
|
||||||
|
let esince = Scalar::random(&mut rng);
|
||||||
|
let EncSince = (
|
||||||
|
&esince * Btable,
|
||||||
|
&lox_cred.level_since * Btable + esince * D,
|
||||||
|
);
|
||||||
|
let einvremain = Scalar::random(&mut rng);
|
||||||
|
let EncInvRemain = (
|
||||||
|
&einvremain * Btable,
|
||||||
|
&new_invites_remaining * Btable + einvremain * D,
|
||||||
|
);
|
||||||
|
let eblockages = Scalar::random(&mut rng);
|
||||||
|
let EncBlockages = (
|
||||||
|
&eblockages * Btable,
|
||||||
|
&lox_cred.blockages * Btable + eblockages * D,
|
||||||
|
);
|
||||||
|
|
||||||
|
// User blinding for the Invitation certificate to be issued
|
||||||
|
|
||||||
|
// Pick a random client component of the id
|
||||||
|
let inv_id_client = Scalar::random(&mut rng);
|
||||||
|
|
||||||
|
// Encrypt it (times the basepoint B) to the ElGamal public key D we
|
||||||
|
// just created
|
||||||
|
let einv_id_client = Scalar::random(&mut rng);
|
||||||
|
let EncInvIdClient = (
|
||||||
|
&einv_id_client * Btable,
|
||||||
|
&id_client * Btable + einv_id_client * D,
|
||||||
|
);
|
||||||
|
|
||||||
|
// The proof that invites_remaining is not zero. We prove this by
|
||||||
|
// demonstrating that we know its inverse.
|
||||||
|
let invremain_inverse = &lox_cred.invites_remaining.invert();
|
||||||
|
|
||||||
|
let zinvremain_inverse = -zinvremain * invremain_inverse;
|
||||||
|
|
||||||
|
// So now invremain_inverse * CInvRemain + zinvremain_inverse * A = P
|
||||||
|
|
||||||
|
// Construct the proof
|
||||||
|
let mut transcript = Transcript::new(b"issue invite request");
|
||||||
|
let piUser = requestproof::prove_compact(
|
||||||
|
&mut transcript,
|
||||||
|
requestproof::ProveAssignments {
|
||||||
|
A: &A,
|
||||||
|
B: &B,
|
||||||
|
P: &P,
|
||||||
|
CBucket: &CBucket,
|
||||||
|
CLevel: &CLevel,
|
||||||
|
CSince: &CSince,
|
||||||
|
CInvRemain: &CInvRemain,
|
||||||
|
CBlockages: &CBlockages,
|
||||||
|
V: &V,
|
||||||
|
Xbucket: &lox_pub.X[2],
|
||||||
|
Xlevel: &lox_pub.X[3],
|
||||||
|
Xsince: &lox_pub.X[4],
|
||||||
|
Xinvremain: &lox_pub.X[5],
|
||||||
|
Xblockages: &lox_pub.X[6],
|
||||||
|
P_reach: &P_reach,
|
||||||
|
CBucket_reach: &CBucket_reach,
|
||||||
|
V_reach: &V_reach,
|
||||||
|
Xbucket_reach: &reach_pub.X[2],
|
||||||
|
D: &D,
|
||||||
|
EncIdClient0: &EncIdClient.0,
|
||||||
|
EncIdClient1: &EncIdClient.1,
|
||||||
|
EncBucket0: &EncBucket.0,
|
||||||
|
EncBucket1: &EncBucket.1,
|
||||||
|
EncLevel0: &EncLevel.0,
|
||||||
|
EncLevel1: &EncLevel.1,
|
||||||
|
EncSince0: &EncSince.0,
|
||||||
|
EncSince1: &EncSince.1,
|
||||||
|
EncInvRemain0: &EncInvRemain.0,
|
||||||
|
EncInvRemain1_plus_B: &(EncInvRemain.1 + B),
|
||||||
|
EncBlockages0: &EncBlockages.0,
|
||||||
|
EncBlockages1: &EncBlockages.1,
|
||||||
|
EncInvIdClient0: &EncInvIdClient.0,
|
||||||
|
EncInvIdClient1: &EncInvIdClient.1,
|
||||||
|
bucket: &lox_cred.bucket,
|
||||||
|
level: &lox_cred.trust_level,
|
||||||
|
since: &lox_cred.level_since,
|
||||||
|
invremain: &lox_cred.invites_remaining,
|
||||||
|
blockages: &lox_cred.blockages,
|
||||||
|
zbucket: &zbucket,
|
||||||
|
zlevel: &zlevel,
|
||||||
|
zsince: &zsince,
|
||||||
|
zinvremain: &zinvremain,
|
||||||
|
zblockages: &zblockages,
|
||||||
|
negzQ: &negzQ,
|
||||||
|
zbucket_reach: &zbucket_reach,
|
||||||
|
negzQ_reach: &negzQ_reach,
|
||||||
|
d: &d,
|
||||||
|
eid_client: &eid_client,
|
||||||
|
ebucket: &ebucket,
|
||||||
|
elevel: &elevel,
|
||||||
|
esince: &esince,
|
||||||
|
einvremain: &einvremain,
|
||||||
|
eblockages: &eblockages,
|
||||||
|
id_client: &id_client,
|
||||||
|
inv_id_client: &inv_id_client,
|
||||||
|
einv_id_client: &einv_id_client,
|
||||||
|
invremain_inverse: &invremain_inverse,
|
||||||
|
zinvremain_inverse: &zinvremain_inverse,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.0;
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
Request {
|
||||||
|
P,
|
||||||
|
id: lox_cred.id,
|
||||||
|
CBucket,
|
||||||
|
CLevel,
|
||||||
|
CSince,
|
||||||
|
CInvRemain,
|
||||||
|
CBlockages,
|
||||||
|
CQ,
|
||||||
|
P_reach,
|
||||||
|
CBucket_reach,
|
||||||
|
CQ_reach,
|
||||||
|
D,
|
||||||
|
EncIdClient,
|
||||||
|
EncBucket,
|
||||||
|
EncLevel,
|
||||||
|
EncSince,
|
||||||
|
EncInvRemain,
|
||||||
|
EncBlockages,
|
||||||
|
EncInvIdClient,
|
||||||
|
piUser,
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
d,
|
||||||
|
D,
|
||||||
|
EncIdClient,
|
||||||
|
EncBucket,
|
||||||
|
EncLevel,
|
||||||
|
EncSince,
|
||||||
|
EncInvRemain,
|
||||||
|
EncBlockages,
|
||||||
|
EncInvIdClient,
|
||||||
|
id_client,
|
||||||
|
bucket: lox_cred.bucket,
|
||||||
|
level: lox_cred.trust_level,
|
||||||
|
since: lox_cred.level_since,
|
||||||
|
invremain: new_invites_remaining,
|
||||||
|
blockages: lox_cred.blockages,
|
||||||
|
inv_id_client,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
|
@ -76,6 +76,8 @@ pub const LEVEL_INVITATIONS: [u32; MAX_LEVEL + 1] = [0, 2, 4, 6, 8];
|
||||||
/// blockages this credential is allowed to have recorded in order to
|
/// blockages this credential is allowed to have recorded in order to
|
||||||
/// advance from level i to level i+1. Again the LEVEL_INVITATIONS\[0\]
|
/// advance from level i to level i+1. Again the LEVEL_INVITATIONS\[0\]
|
||||||
/// entry is a dummy, as for LEVEL_INTERVAL.
|
/// entry is a dummy, as for LEVEL_INTERVAL.
|
||||||
|
// 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];
|
pub const MAX_BLOCKAGES: [u32; MAX_LEVEL + 1] = [0, 4, 3, 2, 2];
|
||||||
|
|
||||||
pub struct Request {
|
pub struct Request {
|
||||||
|
@ -399,7 +401,7 @@ pub fn request(
|
||||||
// Encrypt the other blinded fields (times B) to D as well
|
// Encrypt the other blinded fields (times B) to D as well
|
||||||
let ebucket = Scalar::random(&mut rng);
|
let ebucket = Scalar::random(&mut rng);
|
||||||
let EncBucket = (&ebucket * Btable, &lox_cred.bucket * Btable + ebucket * D);
|
let EncBucket = (&ebucket * Btable, &lox_cred.bucket * Btable + ebucket * D);
|
||||||
let newinvites: Scalar = LEVEL_INVITATIONS[new_level as usize].into();
|
let newinvites: Scalar = LEVEL_INVITATIONS[trust_level as usize].into();
|
||||||
let eblockages = Scalar::random(&mut rng);
|
let eblockages = Scalar::random(&mut rng);
|
||||||
let EncBlockages = (
|
let EncBlockages = (
|
||||||
&eblockages * Btable,
|
&eblockages * Btable,
|
||||||
|
@ -830,7 +832,7 @@ impl BridgeAuth {
|
||||||
|
|
||||||
// Create the invitations_remaining attribute (Scalar), which is
|
// Create the invitations_remaining attribute (Scalar), which is
|
||||||
// the number of invitations at the new level
|
// the number of invitations at the new level
|
||||||
let invitations_remaining: Scalar = LEVEL_INVITATIONS[new_level].into();
|
let invitations_remaining: Scalar = LEVEL_INVITATIONS[level].into();
|
||||||
|
|
||||||
// Compute the MAC on the visible attributes
|
// Compute the MAC on the visible attributes
|
||||||
let b = Scalar::random(&mut rng);
|
let b = Scalar::random(&mut rng);
|
||||||
|
|
|
@ -200,3 +200,35 @@ fn test_level_up() {
|
||||||
println!("cred4 = {:?}", cred4);
|
println!("cred4 = {:?}", cred4);
|
||||||
assert!(ba.verify_lox(&cred4));
|
assert!(ba.verify_lox(&cred4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_issue_inv() {
|
||||||
|
let (bdb, mut ba) = setup();
|
||||||
|
let cred1 = level0_migration(&bdb, &mut ba);
|
||||||
|
assert!(scalar_u32(&cred1.trust_level).unwrap() == 1);
|
||||||
|
|
||||||
|
// Time passes
|
||||||
|
ba.advance_days(20);
|
||||||
|
|
||||||
|
let cred2 = level_up(&mut ba, &cred1);
|
||||||
|
assert!(scalar_u32(&cred2.trust_level).unwrap() == 2);
|
||||||
|
println!("cred2 = {:?}", cred2);
|
||||||
|
assert!(ba.verify_lox(&cred2));
|
||||||
|
|
||||||
|
// Read the bucket in the credential to get today's Bucket
|
||||||
|
// Reachability credential
|
||||||
|
let (id, key) = bridge_table::from_scalar(cred2.bucket).unwrap();
|
||||||
|
let encbuckets = ba.enc_bridge_table();
|
||||||
|
let bucket =
|
||||||
|
bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap();
|
||||||
|
let reachcred = bucket.1.unwrap();
|
||||||
|
|
||||||
|
let (req, state) = issue_invite::request(
|
||||||
|
&cred2,
|
||||||
|
&reachcred,
|
||||||
|
&ba.lox_pub,
|
||||||
|
&ba.reachability_pub,
|
||||||
|
ba.today(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue