bridge_table.rs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*! The encrypted table of bridges. The table consists of a number of
  2. * buckets, each holding some number (currently up to 3) of bridges.
  3. * Each bucket is individually encrypted with a bucket key. Users will
  4. * have a credential containing a bucket (number, key) combination, and
  5. * so will be able to read one of the buckets. Users will either
  6. * download the whole encrypted bucket list or use PIR to download a
  7. * piece of it, so that the bridge authority does not learn which bucket
  8. * the user has access to. */
  9. use aes_gcm::aead;
  10. use aes_gcm::aead::{generic_array::GenericArray, Aead, NewAead};
  11. use aes_gcm::Aes128Gcm;
  12. use rand::RngCore;
  13. use std::convert::TryInto;
  14. /// Each bridge information line is serialized into this many bytes
  15. pub const BRIDGE_BYTES: usize = 220;
  16. /// The max number of bridges per bucket
  17. pub const MAX_BRIDGES_PER_BUCKET: usize = 3;
  18. /// The size of a plaintext bucket
  19. pub const BUCKET_BYTES: usize = BRIDGE_BYTES * MAX_BRIDGES_PER_BUCKET;
  20. /// The size of an encrypted bucket
  21. pub const ENC_BUCKET_BYTES: usize = BUCKET_BYTES + 12 + 16;
  22. /// A bridge information line
  23. #[derive(Debug)]
  24. pub struct BridgeLine {
  25. /// IPv4 or IPv6 address
  26. pub addr: [u8; 16],
  27. /// port
  28. pub port: u16,
  29. /// other protocol information, including pluggable transport,
  30. /// public key, etc.
  31. pub info: [u8; BRIDGE_BYTES - 18],
  32. }
  33. impl Default for BridgeLine {
  34. /// An "empty" BridgeLine is represented by all zeros
  35. fn default() -> Self {
  36. Self {
  37. addr: [0; 16],
  38. port: 0,
  39. info: [0; BRIDGE_BYTES - 18],
  40. }
  41. }
  42. }
  43. impl BridgeLine {
  44. /// Encode a BridgeLine to a byte array
  45. pub fn encode(&self) -> [u8; BRIDGE_BYTES] {
  46. let mut res: [u8; BRIDGE_BYTES] = [0; BRIDGE_BYTES];
  47. res[0..16].copy_from_slice(&self.addr);
  48. res[16..18].copy_from_slice(&self.port.to_be_bytes());
  49. res[18..].copy_from_slice(&self.info);
  50. res
  51. }
  52. /// Decode a BridgeLine from a byte array
  53. pub fn decode(data: &[u8; BRIDGE_BYTES]) -> Self {
  54. let mut res: Self = Default::default();
  55. res.addr.copy_from_slice(&data[0..16]);
  56. res.port = u16::from_be_bytes(data[16..18].try_into().unwrap());
  57. res.info.copy_from_slice(&data[18..]);
  58. res
  59. }
  60. /// Encode a bucket to a byte array
  61. pub fn bucket_encode(bucket: &[BridgeLine; MAX_BRIDGES_PER_BUCKET]) -> [u8; BUCKET_BYTES] {
  62. let mut res: [u8; BUCKET_BYTES] = [0; BUCKET_BYTES];
  63. let mut pos: usize = 0;
  64. for bridge in bucket {
  65. res[pos..pos + BRIDGE_BYTES].copy_from_slice(&bridge.encode());
  66. pos += BRIDGE_BYTES;
  67. }
  68. res
  69. }
  70. /// Decode a bucket from a byte array
  71. pub fn bucket_decode(data: &[u8; BUCKET_BYTES]) -> [BridgeLine; MAX_BRIDGES_PER_BUCKET] {
  72. let mut pos: usize = 0;
  73. let mut res: [BridgeLine; MAX_BRIDGES_PER_BUCKET] = Default::default();
  74. for bridge in res.iter_mut().take(MAX_BRIDGES_PER_BUCKET) {
  75. *bridge = BridgeLine::decode(data[pos..pos + BRIDGE_BYTES].try_into().unwrap());
  76. pos += BRIDGE_BYTES;
  77. }
  78. res
  79. }
  80. /// Create a random BridgeLine for testing
  81. #[cfg(test)]
  82. pub fn random() -> Self {
  83. let mut rng = rand::thread_rng();
  84. let mut res: Self = Default::default();
  85. // Pick a random 4-byte address
  86. let mut addr: [u8; 4] = [0; 4];
  87. rng.fill_bytes(&mut addr);
  88. // If the leading byte is 224 or more, that's not a valid IPv4
  89. // address. Choose an IPv6 address instead (but don't worry too
  90. // much about it being well formed).
  91. if addr[0] >= 224 {
  92. rng.fill_bytes(&mut res.addr);
  93. } else {
  94. // Store an IPv4 address as a v4-mapped IPv6 address
  95. res.addr[10] = 255;
  96. res.addr[11] = 255;
  97. res.addr[12..16].copy_from_slice(&addr);
  98. };
  99. let ports: [u16; 4] = [443, 4433, 8080, 43079];
  100. let portidx = (rng.next_u32() % 4) as usize;
  101. res.port = ports[portidx];
  102. let mut fingerprint: [u8; 20] = [0; 20];
  103. let mut cert: [u8; 52] = [0; 52];
  104. rng.fill_bytes(&mut fingerprint);
  105. rng.fill_bytes(&mut cert);
  106. let infostr: String = format!(
  107. "obfs4 {} cert={} iat-mode=0",
  108. hex_fmt::HexFmt(fingerprint),
  109. base64::encode_config(cert, base64::STANDARD_NO_PAD)
  110. );
  111. res.info[..infostr.len()].copy_from_slice(infostr.as_bytes());
  112. res
  113. }
  114. }
  115. /// A BridgeTable is the internal structure holding the buckets
  116. /// containing the bridges, the keys used to encrypt the buckets, and
  117. /// the encrypted buckets. The encrypted buckets will be exposed to the
  118. /// users of the system, and each user credential will contain the
  119. /// decryption key for one bucket.
  120. #[derive(Debug, Default)]
  121. pub struct BridgeTable {
  122. keys: Vec<[u8; 16]>,
  123. buckets: Vec<[BridgeLine; MAX_BRIDGES_PER_BUCKET]>,
  124. encbuckets: Vec<[u8; ENC_BUCKET_BYTES]>,
  125. }
  126. // Invariant: the lengths of the keys and buckets vectors are the same.
  127. // The encbuckets vector only gets updated when encrypt_table is called.
  128. impl BridgeTable {
  129. /// Append a new bucket to the bridge table
  130. pub fn new_bucket(&mut self, bucket: [BridgeLine; MAX_BRIDGES_PER_BUCKET]) {
  131. // Pick a random key to encrypt this bucket
  132. let mut rng = rand::thread_rng();
  133. let mut key: [u8; 16] = [0; 16];
  134. rng.fill_bytes(&mut key);
  135. self.keys.push(key);
  136. self.buckets.push(bucket);
  137. }
  138. /// Create the vector of encrypted buckets from the keys and buckets
  139. /// in the BridgeTable. All of the entries will be (randomly)
  140. /// re-encrypted, so it will be hidden whether any individual bucket
  141. /// has changed (except for entirely new buckets, of course).
  142. pub fn encrypt_table(&mut self) {
  143. let mut rng = rand::thread_rng();
  144. self.encbuckets.clear();
  145. for (key, bucket) in self.keys.iter().zip(self.buckets.iter()) {
  146. let mut encbucket: [u8; ENC_BUCKET_BYTES] = [0; ENC_BUCKET_BYTES];
  147. let plainbucket: [u8; BUCKET_BYTES] = BridgeLine::bucket_encode(bucket);
  148. // Set the AES key
  149. let aeskey = GenericArray::from_slice(key);
  150. // Pick a random nonce
  151. let mut noncebytes: [u8; 12] = [0; 12];
  152. rng.fill_bytes(&mut noncebytes);
  153. let nonce = GenericArray::from_slice(&noncebytes);
  154. // Encrypt
  155. let cipher = Aes128Gcm::new(aeskey);
  156. let ciphertext: Vec<u8> = cipher.encrypt(&nonce, plainbucket.as_ref()).unwrap();
  157. encbucket[0..12].copy_from_slice(&noncebytes);
  158. encbucket[12..].copy_from_slice(ciphertext.as_slice());
  159. self.encbuckets.push(encbucket);
  160. }
  161. }
  162. /// Decrypt an individual encrypted bucket, given its key
  163. pub fn decrypt_bucket(
  164. key: &[u8; 16],
  165. encbucket: &[u8; ENC_BUCKET_BYTES],
  166. ) -> Result<[BridgeLine; MAX_BRIDGES_PER_BUCKET], aead::Error> {
  167. // Set the nonce and the key
  168. let nonce = GenericArray::from_slice(&encbucket[0..12]);
  169. let aeskey = GenericArray::from_slice(key);
  170. // Decrypt
  171. let cipher = Aes128Gcm::new(aeskey);
  172. let plaintext: Vec<u8> = cipher.decrypt(&nonce, encbucket[12..].as_ref())?;
  173. // Convert the plaintext bytes to an array of BridgeLines
  174. Ok(BridgeLine::bucket_decode(
  175. plaintext.as_slice().try_into().unwrap(),
  176. ))
  177. }
  178. }
  179. // Unit tests that require access to private fields
  180. #[cfg(test)]
  181. mod tests {
  182. use super::*;
  183. #[test]
  184. fn test_bridge_table() -> Result<(), aead::Error> {
  185. // Create an empty bridge table
  186. let mut btable: BridgeTable = Default::default();
  187. // Make 20 buckets with one random bridge each
  188. for _ in 0..20 {
  189. let bucket: [BridgeLine; 3] =
  190. [BridgeLine::random(), Default::default(), Default::default()];
  191. btable.new_bucket(bucket);
  192. }
  193. // And 20 more with three random bridges each
  194. for _ in 0..20 {
  195. let bucket: [BridgeLine; 3] = [
  196. BridgeLine::random(),
  197. BridgeLine::random(),
  198. BridgeLine::random(),
  199. ];
  200. btable.new_bucket(bucket);
  201. }
  202. // Create the encrypted bridge table
  203. btable.encrypt_table();
  204. // Try to decrypt a 1-bridge bucket
  205. let key7 = btable.keys[7];
  206. let encbucket7 = btable.encbuckets[7];
  207. let bucket7 = BridgeTable::decrypt_bucket(&key7, &encbucket7)?;
  208. println!("bucket 7 = {:?}", bucket7);
  209. // Try to decrypt a 3-bridge bucket
  210. let key24 = btable.keys[24];
  211. let encbucket24 = btable.encbuckets[24];
  212. let bucket24 = BridgeTable::decrypt_bucket(&key24, &encbucket24)?;
  213. println!("bucket 24 = {:?}", bucket24);
  214. // Try to decrypt a bucket with the wrong key
  215. let key12 = btable.keys[12];
  216. let encbucket15 = btable.encbuckets[15];
  217. let res = BridgeTable::decrypt_bucket(&key12, &encbucket15).unwrap_err();
  218. println!("bucket key mismatch = {:?}", res);
  219. Ok(())
  220. }
  221. }