bridge_table.rs 9.7 KB

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