|
|
@@ -1,10 +1,11 @@
|
|
|
use crate::{
|
|
|
bridge_verification_info::BridgeVerificationInfo, get_date, BridgeDistributor, COUNTRY_CODES,
|
|
|
+ MAX_BACKDATE,
|
|
|
};
|
|
|
|
|
|
use curve25519_dalek::scalar::Scalar;
|
|
|
use lox_library::{bridge_table::BridgeLine, cred::Lox};
|
|
|
-
|
|
|
+use rand::RngCore;
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
use sha1::{Digest, Sha1};
|
|
|
use sha3::Sha3_256;
|
|
|
@@ -12,6 +13,7 @@ use sha3::Sha3_256;
|
|
|
#[derive(Debug, Serialize)]
|
|
|
pub enum NegativeReportError {
|
|
|
DateInFuture,
|
|
|
+ DateInPast, // report is more than MAX_BACKDATE days old
|
|
|
FailedToDeserialize, // couldn't deserialize to SerializableNegativeReport
|
|
|
InvalidCountryCode,
|
|
|
MissingCountryCode,
|
|
|
@@ -32,6 +34,9 @@ pub struct NegativeReport {
|
|
|
/// today's Julian date
|
|
|
pub date: u32,
|
|
|
|
|
|
+ /// a random nonce used in the bridge_pok
|
|
|
+ pub nonce: [u8; 32],
|
|
|
+
|
|
|
/// the bridge distributor, e.g., Lox, Https, or Moat
|
|
|
pub distributor: BridgeDistributor,
|
|
|
}
|
|
|
@@ -42,6 +47,7 @@ impl NegativeReport {
|
|
|
bridge_pok: ProofOfBridgeKnowledge,
|
|
|
country: String,
|
|
|
date: u32,
|
|
|
+ nonce: [u8; 32],
|
|
|
distributor: BridgeDistributor,
|
|
|
) -> Self {
|
|
|
let mut hasher = Sha1::new();
|
|
|
@@ -52,6 +58,7 @@ impl NegativeReport {
|
|
|
bridge_pok,
|
|
|
country,
|
|
|
date,
|
|
|
+ nonce,
|
|
|
distributor,
|
|
|
}
|
|
|
}
|
|
|
@@ -62,24 +69,42 @@ impl NegativeReport {
|
|
|
distributor: BridgeDistributor,
|
|
|
) -> Self {
|
|
|
let date = get_date();
|
|
|
- let bridge_pok =
|
|
|
- ProofOfBridgeKnowledge::HashOfBridgeLine(HashOfBridgeLine::new(&bridgeline, date));
|
|
|
- NegativeReport::new(
|
|
|
+ let mut rng = rand::thread_rng();
|
|
|
+ let mut nonce = [0; 32];
|
|
|
+ rng.fill_bytes(&mut nonce);
|
|
|
+ let bridge_pok = ProofOfBridgeKnowledge::HashOfBridgeLine(HashOfBridgeLine::new(
|
|
|
+ &bridgeline,
|
|
|
+ date,
|
|
|
+ nonce,
|
|
|
+ ));
|
|
|
+ Self::new(
|
|
|
bridgeline.fingerprint,
|
|
|
bridge_pok,
|
|
|
country,
|
|
|
date,
|
|
|
+ nonce,
|
|
|
distributor,
|
|
|
)
|
|
|
}
|
|
|
|
|
|
pub fn from_lox_bucket(bridge_id: [u8; 20], bucket: Scalar, country: String) -> Self {
|
|
|
let date = get_date();
|
|
|
- let bridge_pok = ProofOfBridgeKnowledge::HashOfBucket(HashOfBucket::new(&bucket, date));
|
|
|
- NegativeReport::new(bridge_id, bridge_pok, country, date, BridgeDistributor::Lox)
|
|
|
+ let mut rng = rand::thread_rng();
|
|
|
+ let mut nonce = [0; 32];
|
|
|
+ rng.fill_bytes(&mut nonce);
|
|
|
+ let bridge_pok =
|
|
|
+ ProofOfBridgeKnowledge::HashOfBucket(HashOfBucket::new(&bucket, date, nonce));
|
|
|
+ Self::new(
|
|
|
+ bridge_id,
|
|
|
+ bridge_pok,
|
|
|
+ country,
|
|
|
+ date,
|
|
|
+ nonce,
|
|
|
+ BridgeDistributor::Lox,
|
|
|
+ )
|
|
|
}
|
|
|
|
|
|
- pub fn from_lox_credential(bridge_id: [u8; 20], cred: Lox, country: String) -> Self {
|
|
|
+ pub fn from_lox_credential(bridge_id: [u8; 20], cred: &Lox, country: String) -> Self {
|
|
|
NegativeReport::from_lox_bucket(bridge_id, cred.bucket, country)
|
|
|
}
|
|
|
|
|
|
@@ -90,6 +115,7 @@ impl NegativeReport {
|
|
|
bridge_pok: self.bridge_pok,
|
|
|
country: self.country,
|
|
|
date: self.date,
|
|
|
+ nonce: self.nonce,
|
|
|
distributor: self.distributor,
|
|
|
}
|
|
|
}
|
|
|
@@ -119,12 +145,12 @@ impl NegativeReport {
|
|
|
pub fn verify(self, bridge_info: &BridgeVerificationInfo) -> bool {
|
|
|
match self.bridge_pok {
|
|
|
ProofOfBridgeKnowledge::HashOfBridgeLine(pok) => {
|
|
|
- let hash = HashOfBridgeLine::new(&bridge_info.bridge_line, self.date);
|
|
|
+ let hash = HashOfBridgeLine::new(&bridge_info.bridge_line, self.date, self.nonce);
|
|
|
hash == pok
|
|
|
}
|
|
|
ProofOfBridgeKnowledge::HashOfBucket(pok) => {
|
|
|
for b in &bridge_info.buckets {
|
|
|
- let hash = HashOfBucket::new(&b, self.date);
|
|
|
+ let hash = HashOfBucket::new(&b, self.date, self.nonce);
|
|
|
if hash == pok {
|
|
|
return true;
|
|
|
}
|
|
|
@@ -143,6 +169,7 @@ pub struct SerializableNegativeReport {
|
|
|
bridge_pok: ProofOfBridgeKnowledge,
|
|
|
pub country: String,
|
|
|
pub date: u32,
|
|
|
+ pub nonce: [u8; 32],
|
|
|
pub distributor: BridgeDistributor,
|
|
|
}
|
|
|
|
|
|
@@ -154,14 +181,19 @@ impl SerializableNegativeReport {
|
|
|
if !COUNTRY_CODES.contains(self.country.as_str()) {
|
|
|
return Err(NegativeReportError::InvalidCountryCode);
|
|
|
}
|
|
|
- if self.date > get_date().into() {
|
|
|
+ let date = get_date();
|
|
|
+ if self.date > date {
|
|
|
return Err(NegativeReportError::DateInFuture);
|
|
|
}
|
|
|
+ if self.date < date - MAX_BACKDATE {
|
|
|
+ return Err(NegativeReportError::DateInPast);
|
|
|
+ }
|
|
|
Ok(NegativeReport {
|
|
|
fingerprint: self.fingerprint,
|
|
|
bridge_pok: self.bridge_pok,
|
|
|
country: self.country.to_string(),
|
|
|
date: self.date.try_into().unwrap(),
|
|
|
+ nonce: self.nonce,
|
|
|
distributor: self.distributor,
|
|
|
})
|
|
|
}
|
|
|
@@ -184,9 +216,10 @@ pub struct HashOfBridgeLine {
|
|
|
}
|
|
|
|
|
|
impl HashOfBridgeLine {
|
|
|
- pub fn new(bl: &BridgeLine, date: u32) -> Self {
|
|
|
+ pub fn new(bl: &BridgeLine, date: u32, nonce: [u8; 32]) -> Self {
|
|
|
let mut hasher = Sha3_256::new();
|
|
|
hasher.update(date.to_le_bytes());
|
|
|
+ hasher.update(nonce);
|
|
|
hasher.update(bincode::serialize(&bl).unwrap());
|
|
|
let hash: [u8; 32] = hasher.finalize().into();
|
|
|
Self { hash }
|
|
|
@@ -200,9 +233,10 @@ pub struct HashOfBucket {
|
|
|
}
|
|
|
|
|
|
impl HashOfBucket {
|
|
|
- pub fn new(bucket: &Scalar, date: u32) -> Self {
|
|
|
+ pub fn new(bucket: &Scalar, date: u32, nonce: [u8; 32]) -> Self {
|
|
|
let mut hasher = Sha3_256::new();
|
|
|
hasher.update(date.to_le_bytes());
|
|
|
+ hasher.update(nonce);
|
|
|
hasher.update(bucket.to_bytes());
|
|
|
let hash: [u8; 32] = hasher.finalize().into();
|
|
|
Self { hash }
|