@@ -10,6 +10,7 @@ use sha2::{Digest, Sha256, Sha512};
1010use tracing:: { debug, instrument, trace} ;
1111
1212const SESSION_ID : & [ u8 ] = b"submit" ;
13+ const PROBE_ID_SALT : & [ u8 ] = b"ooni.org/userauth/v1" ;
1314
1415muCMZProtocol ! ( submit<min_age_today, max_age, min_measurement_count,
1516 max_measurement_count, @DOMAIN , @NYM >,
@@ -46,21 +47,21 @@ impl SubmitRequest {
4647}
4748
4849fn digest_point ( point : RistrettoPoint ) -> [ u8 ; 32 ] {
49- let digest = Sha256 :: digest ( point. compress ( ) . as_bytes ( ) ) ;
50+ let mut hasher = Sha256 :: new ( ) ;
51+ hasher. update ( PROBE_ID_SALT ) ;
52+ hasher. update ( point. compress ( ) . as_bytes ( ) ) ;
53+ let digest = hasher. finalize ( ) ;
5054 let mut out = [ 0u8 ; 32 ] ;
5155 out. copy_from_slice ( & digest) ;
5256 out
5357}
5458
59+ fn inclusive_upper_bound ( range : & std:: ops:: Range < u32 > ) -> u32 {
60+ range. end . saturating_sub ( 1 )
61+ }
62+
5563impl UserState {
56- #[ instrument( skip(
57- self ,
58- rng,
59- probe_cc,
60- probe_asn,
61- age_range,
62- measurement_count_range
63- ) ) ]
64+ #[ instrument( skip( self , rng, probe_cc, probe_asn, age_range, measurement_count_range) ) ]
6465 pub fn submit_request (
6566 & self ,
6667 rng : & mut ( impl RngCore + CryptoRng ) ,
@@ -148,9 +149,9 @@ impl UserState {
148149 New . measurement_count = Some ( ( measurement_count + 1 ) . into ( ) ) ;
149150 let params = submit:: Params {
150151 min_age_today : age_range. start . into ( ) ,
151- max_age : age_range. end . into ( ) ,
152+ max_age : inclusive_upper_bound ( & age_range) . into ( ) ,
152153 min_measurement_count : measurement_count_range. start . into ( ) ,
153- max_measurement_count : measurement_count_range. end . into ( ) ,
154+ max_measurement_count : inclusive_upper_bound ( & measurement_count_range) . into ( ) ,
154155 DOMAIN ,
155156 NYM ,
156157 } ;
@@ -221,7 +222,7 @@ impl ServerState {
221222 let domain_str = format ! ( "ooni.org/{}/{}" , probe_cc, probe_asn) ;
222223 let DOMAIN = G :: hash_from_bytes :: < Sha512 > ( domain_str. as_bytes ( ) ) ;
223224
224- // The probe id is the same as the nym point.
225+ // The probe id must be the salted hash of the nym point.
225226 // Otherwise, return an error.
226227 // We do not really care about the server returning early here,
227228 // a malicious probe should already have computed the probe ID from the
@@ -232,9 +233,9 @@ impl ServerState {
232233
233234 let params = submit:: Params {
234235 min_age_today : age_range. start . into ( ) ,
235- max_age : age_range. end . into ( ) ,
236+ max_age : inclusive_upper_bound ( & age_range) . into ( ) ,
236237 min_measurement_count : measurement_count_range. start . into ( ) ,
237- max_measurement_count : measurement_count_range. end . into ( ) ,
238+ max_measurement_count : inclusive_upper_bound ( & measurement_count_range) . into ( ) ,
238239 DOMAIN ,
239240 NYM : nym_point,
240241 } ;
@@ -303,6 +304,12 @@ mod tests {
303304 ) ;
304305 }
305306
307+ #[ test]
308+ fn test_inclusive_upper_bound ( ) {
309+ assert_eq ! ( inclusive_upper_bound( & ( 10 ..11 ) ) , 10 ) ;
310+ assert_eq ! ( inclusive_upper_bound( & ( 0 ..1 ) ) , 0 ) ;
311+ }
312+
306313 #[ test]
307314 fn test_submit_request ( ) {
308315 let rng = & mut rand:: thread_rng ( ) ;
0 commit comments