rdpf.hpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #ifndef __RDPF_HPP__
  2. #define __RDPF_HPP__
  3. #include <vector>
  4. #include <iostream>
  5. #include "mpcio.hpp"
  6. #include "coroutine.hpp"
  7. #include "types.hpp"
  8. struct RDPF {
  9. // The 128-bit seed
  10. DPFnode seed;
  11. // correction words; the depth of the DPF is the length of this
  12. // vector
  13. std::vector<DPFnode> cw;
  14. // correction flag bits: the one for level i is bit i of this word
  15. value_t cfbits;
  16. // The amount we have to scale the low words of the leaf values by
  17. // to get additive shares of a unit vector
  18. value_t unit_sum_inverse;
  19. // Additive share of the scaling value M_as such that the high words
  20. // of the leaf values for P0 and P1 add to M_as * e_{target}
  21. RegAS scaled_sum;
  22. // XOR share of the scaling value M_xs such that the high words
  23. // of the leaf values for P0 and P1 XOR to M_xs * e_{target}
  24. RegXS scaled_xor;
  25. RDPF() {}
  26. // Construct a DPF with the given (XOR-shared) target location, and
  27. // of the given depth, to be used for random-access memory reads and
  28. // writes. The DPF is constructed collaboratively by P0 and P1,
  29. // with the server P2 helping by providing correlated randomness,
  30. // such as SelectTriples.
  31. //
  32. // Cost:
  33. // (2 DPFnode + 2 bytes)*depth + 1 word communication in
  34. // 2*depth + 1 messages
  35. // (2 DPFnode + 1 byte)*depth communication from P2 to each party
  36. // 2^{depth+1}-2 local AES operations for P0,P1
  37. // 0 local AES operations for P2
  38. RDPF(MPCTIO &tio, yield_t &yield,
  39. RegXS target, nbits_t depth);
  40. // The number of bytes it will take to store this RDPF
  41. size_t size() const;
  42. // The number of bytes it will take to store a RDPF of the given
  43. // depth
  44. static size_t size(nbits_t depth);
  45. // The depth
  46. inline nbits_t depth() const { return cw.size(); }
  47. };
  48. // I/O for RDPFs
  49. template <typename T>
  50. T& operator>>(T &is, RDPF &rdpf)
  51. {
  52. is.read((char *)&rdpf.seed, sizeof(rdpf.seed));
  53. uint8_t depth;
  54. is.read((char *)&depth, sizeof(depth));
  55. assert(depth <= VALUE_BITS);
  56. rdpf.cw.clear();
  57. for (uint8_t i=0; i<depth; ++i) {
  58. DPFnode cw;
  59. is.read((char *)&cw, sizeof(cw));
  60. rdpf.cw.push_back(cw);
  61. }
  62. value_t cfbits = 0;
  63. is.read((char *)&cfbits, BITBYTES(depth));
  64. rdpf.cfbits = cfbits;
  65. is.read((char *)&rdpf.unit_sum_inverse, sizeof(rdpf.unit_sum_inverse));
  66. is.read((char *)&rdpf.scaled_sum, sizeof(rdpf.scaled_sum));
  67. is.read((char *)&rdpf.scaled_xor, sizeof(rdpf.scaled_xor));
  68. return is;
  69. }
  70. template <typename T>
  71. T& operator<<(T &os, const RDPF &rdpf)
  72. {
  73. os.write((const char *)&rdpf.seed, sizeof(rdpf.seed));
  74. uint8_t depth = rdpf.cw.size();
  75. assert(depth <= VALUE_BITS);
  76. os.write((const char *)&depth, sizeof(depth));
  77. for (uint8_t i=0; i<depth; ++i) {
  78. os.write((const char *)&rdpf.cw[i], sizeof(rdpf.cw[i]));
  79. }
  80. os.write((const char *)&rdpf.cfbits, BITBYTES(depth));
  81. os.write((const char *)&rdpf.unit_sum_inverse, sizeof(rdpf.unit_sum_inverse));
  82. os.write((const char *)&rdpf.scaled_sum, sizeof(rdpf.scaled_sum));
  83. os.write((const char *)&rdpf.scaled_xor, sizeof(rdpf.scaled_xor));
  84. return os;
  85. }
  86. // Computational peers will generate triples of RDPFs with the _same_
  87. // random target for use in Duoram. They will each hold a share of the
  88. // target (neither knowing the complete target index). They will each
  89. // give one of the DPFs (not a matching pair) to the server, but not the
  90. // shares of the target index. So computational peers will hold a
  91. // RDPFTriple (which includes both an additive and an XOR share of the
  92. // target index), while the server will hold a RDPFPair (which does
  93. // not).
  94. struct RDPFTriple {
  95. RegAS as_target;
  96. RegXS xs_target;
  97. RDPF dpf[3];
  98. RDPFTriple() {}
  99. // Construct three RDPFs of the given depth all with the same
  100. // randomly generated target index.
  101. RDPFTriple(MPCTIO &tio, yield_t &yield,
  102. nbits_t depth);
  103. };
  104. // I/O for RDPF Triples
  105. template <typename T>
  106. T& operator<<(T &os, const RDPFTriple &rdpftrip)
  107. {
  108. os << rdpftrip.dpf[0] << rdpftrip.dpf[1] << rdpftrip.dpf[2];
  109. nbits_t depth = rdpftrip.dpf[0].depth();
  110. os.write(&rdpftrip.as_target.ashare, BITBYTES(depth));
  111. os.write(&rdpftrip.xs_target.xshare, BITBYTES(depth));
  112. }
  113. template <typename T>
  114. T& operator>>(T &is, RDPFTriple &rdpftrip)
  115. {
  116. is >> rdpftrip.dpf[0] >> rdpftrip.dpf[1] >> rdpftrip.dpf[2];
  117. nbits_t depth = rdpftrip.dpf[0].depth();
  118. rdpftrip.as_target.ashare = 0;
  119. is.read(&rdpftrip.as_target.ashare, BITBYTES(depth));
  120. rdpftrip.xs_target.xshare = 0;
  121. is.read(&rdpftrip.xs_target.xshare, BITBYTES(depth));
  122. }
  123. struct RDPFPair {
  124. RDPF dpf[2];
  125. };
  126. // I/O for RDPF Pairs
  127. template <typename T>
  128. T& operator<<(T &os, const RDPFPair &rdpfpair)
  129. {
  130. os << rdpfpair.dpf[0] << rdpfpair.dpf[1];
  131. }
  132. template <typename T>
  133. T& operator>>(T &is, RDPFPair &rdpfpair)
  134. {
  135. is >> rdpfpair.dpf[0] >> rdpfpair.dpf[1];
  136. }
  137. #endif