diff --git a/cryptoTools b/cryptoTools index 0fe0528..1ffddc5 160000 --- a/cryptoTools +++ b/cryptoTools @@ -1 +1 @@ -Subproject commit 0fe05285f4f22d520a31ed226ea757d7c3dac49c +Subproject commit 1ffddc5215231d6ebda47b84c4b42782a7f4e790 diff --git a/frontend/benchmark.h b/frontend/benchmark.h index 111a45c..c5b51e9 100644 --- a/frontend/benchmark.h +++ b/frontend/benchmark.h @@ -40,8 +40,7 @@ namespace osuCrypto oc::Timer timer; QuasiCyclicCode code; - auto p = nextPrime(n); - code.init(p); + code.init2(k, n); std::vector c0(code.size(), ZeroBlock); for (auto t = 0ull; t < trials; ++t) { diff --git a/frontend/main.cpp b/frontend/main.cpp index af204dd..339b0ad 100644 --- a/frontend/main.cpp +++ b/frontend/main.cpp @@ -25,6 +25,7 @@ #include "libOTe/Tools/LDPC/Util.h" #include "cryptoTools/Crypto/RandomOracle.h" #include "libOTe/Tools/EACode/EAChecker.h" +#include "libOTe/Tools/ExConvCode/ExConvChecker.h" #include "libOTe/TwoChooseOne/Iknp/IknpOtExtSender.h" #include "libOTe/TwoChooseOne/Iknp/IknpOtExtReceiver.h" @@ -84,7 +85,19 @@ int main(int argc, char** argv) cmd.parse(argc, argv); bool flagSet = false; + + if (cmd.isSet("EAChecker")) + { + EAChecker(cmd); + return 0; + } + if (cmd.isSet("ExConvChecker")) + { + ExConvChecker(cmd); + return 0; + } + // various benchmarks if (cmd.isSet("bench")) { diff --git a/libOTe/Tools/EACode/EAChecker.cpp b/libOTe/Tools/EACode/EAChecker.cpp new file mode 100644 index 0000000..2950f8f --- /dev/null +++ b/libOTe/Tools/EACode/EAChecker.cpp @@ -0,0 +1,307 @@ +#include "EAChecker.h" +#include + +//#define USE_ANKERL_HASH +#ifdef USE_ANKERL_HASH +#include "out/unordered_dense/include/ankerl/unordered_dense.h" +#endif +namespace osuCrypto +{ + + u64 hash(span mIdx, u64 b, u64 N) + { + block hh = ZeroBlock; + for (u64 j = 0; j < mIdx.size(); ++j) + hh = hh ^ mAesFixedKey.ecbEncBlock(block(mIdx[j], j)); + return hh.get(0); + } + + // approx hash + std::vector ahash(span mIdx, u64 numBins, u64 N, double d, bool verbose) + { + std::vector H, B; + H.push_back(hash(mIdx, numBins, N)); + + auto binSize = N / numBins; + auto threshold = N * d / numBins; + + u64 lastBin = numBins - 1; + std::vector tweaks, tweakIdx; + for (u64 j = 0; j < mIdx.size(); ++j) + { + auto bIdx = mIdx[j] * numBins / N; + auto bRem = mIdx[j] - bIdx * N / numBins; + + //if (verbose) + // std::cout << bIdx << ", r " << bRem << " vs " << threshold << std::endl; + if (bRem < threshold && bRem != 0) + { + //if (verbose) + // std::cout << "v- " << bRem << " < " << threshold << std::endl; + tweakIdx.push_back(j); + tweaks.push_back(-1); + } + if (bRem > binSize - threshold && bRem != lastBin) + { + //if (verbose) + // std::cout << "v+ " << bRem << " < " << threshold << std::endl; + tweakIdx.push_back(j); + tweaks.push_back(1); + } + + B.push_back(bIdx); + } + + for (u64 i = 1; i < (1ull << tweakIdx.size()); ++i) + { + RandomOracle ro(sizeof(u64)); + BitIterator iIter((u8*)&i); + auto bb = B; + for (u64 j = 0; j < tweakIdx.size(); ++j) + { + if (*iIter++) + { + bb[tweakIdx[j]] += tweaks[j]; + } + } + + block hh = ZeroBlock; + for (u64 j = 0; j < bb.size(); ++j) + hh = hh ^ mAesFixedKey.ecbEncBlock(block(bb[j], j)); + H.push_back(hh.get(0)); + } + return H; + } + + + // the (psuedo) minimum distance finder for EA codes. + // section 4.2 https://eprint.iacr.org/2023/882 + void EAChecker(CLP& cmd) + { + u64 seed = cmd.getOr("s", 0); + + // trials + u64 tt = cmd.getOr("t", 1); + + // threads + u64 nt = cmd.getOr("nt", 1); + + // message size + u64 n = cmd.getOr("n", 1ull<< cmd.getOr("nn", 10)); + + // expansion factor + u64 e = cmd.getOr("e", 5); + + // code size + u64 N = n * e; + + // expander weight + u64 bw = cmd.getOr("bw", 7); + + // number of bins + u64 b = cmd.getOr("b", 50); + + // verbose + bool v = cmd.isSet("v"); + + // if an element is d close to a bin boundary, it is considered to be in both bins. + double d = cmd.getOr("d", 0.25); + + // if true, consider all combinations of rows that hash to the same bin. + bool highWeight = cmd.isSet("hw"); + + // allow collisisons in the expander + bool allowCollisions = cmd.isSet("ac"); + + // regular expander + bool regular = cmd.getOr("reg", 0); + + std::vector thrds(nt); + std::mutex mutex; + u64 gMinDist = -1, gMinDistSingle = -1; + auto runOne = [&](u64 t, Matrix& sig) { + + std::vector xx(2 * bw), ii;; + + // the set of hashes that represent almost collissions +#ifdef USE_ANKERL_HASH + ankerl::unordered_dense::map> sets; +#else + std::unordered_map> sets; +#endif + + // current best min dist. + u64 minDis = N; + + u64 minDistSingle = N; + // maxBinSize bin size + u64 maxBinSize = 0; + //u64 maxBinSize = 0, minDis = N, min0 = -1; + PRNG prng(block(seed, t)); + + u64 step = n / bw; + + for (u64 i = 0; i < n; ++i) + { + // sample the row + span x = sig[i]; + + if (regular) + { + for (u64 j = 0; j < bw; ++j) + { + x[j] = prng.get() % step + j * step; + } + } + else if (allowCollisions) + { + for (u64 j = 0; j < bw; ++j) + { + x[j] = prng.get() % N; + } + } + else + { + for (u64 j = 0; j < bw; ++j) + { + x[j] = prng.get() % N; + auto end = x.begin() + j; + while(std::find(x.begin(), end, x[j]) != end) + x[j] = prng.get() % N; + } + } + std::sort(x.begin(), x.end()); + + // minimum distance of this item alone + u64 mm0 = 0; + for (u64 j = 0; j < bw - 1; j += 2) + { + mm0 += x[j + 1] - x[j]; + } + if (bw & 1) + mm0 += N - x.back(); + minDistSingle = std::min(minDistSingle, mm0); + + // hash the row and see if there are any similar rows. + auto H = ahash(sig[i], b, N, d, false); + + for (auto h : H) + { + auto& ss = sets[h]; + ss.push_back(i); + if (ss.size() > maxBinSize) + { + maxBinSize = ss.size(); + + if (v) + std::cout << "maxBinSize " << maxBinSize << " " << i << std::endl; + } + + // consider all combinations of rows that hash to the same bin. + if (highWeight) + { + u64 pow = 1ull << (ss.size() - 1); + for (u64 jj = 1; jj < pow; ++jj) + { + xx.clear(); + xx.insert(xx.end(), x.begin(), x.end()); + for (u64 j = 0; j < ss.size() - 1; ++j) + { + if (jj & (1ull << j)) + { + auto s2 = sig[ss[j]]; + xx.insert(xx.end(), s2.begin(), s2.end()); + } + } + + std::sort(xx.begin(), xx.end()); + u64 d = 0; + for (u64 t = 0; t < xx.size() - 1; t += 2) + { + d += (xx[t + 1] - xx[t]); + } + if (xx.size() & 1) + { + d += (N - 1) - xx.back(); + } + + if (d < minDis) + { + ii = { { i } }; + for (u64 j = 0; j < ss.size() - 1; ++j) + { + if (jj & (1ull << j)) + ii.push_back(ss[j]); + } + minDis = d; + if (v) + std::cout << "minDis " << minDis << std::endl; + } + } + } + else + { + + // compare this row to all other rows that hash to the same bin. + for (u64 j = 0; j < ss.size() - 1; ++j) + { + xx.clear(); + auto& x2 = sig[ss[j]]; + std::merge(x.begin(), x.end(), x2.begin(), x2.end(), std::back_inserter(xx)); + //xx.insert(xx.end(), x.begin(), x.end()); + //auto s2 = sig[ss[j]]; + //xx.insert(xx.end(), s2.begin(), s2.end()); + //std::sort(xx.begin(), xx.end()); + + u64 d = 0; + for (u64 t = 0; t < bw; ++t) + { + if (xx[2 * t + 1] < xx[2 * t]) + throw RTE_LOC; + d += (xx[2 * t + 1] - xx[2 * t]); + } + if (d < minDis) + { + ii = { { i, ss[j] } }; + minDis = d; + if (v) + std::cout << "minDis " << minDis << std::endl; + } + } + } + + } + } + + std::lock_guard lock(mutex); + std::cout <<"maxBinSize: " << maxBinSize << ", minDis: " << minDis * 1.0 / N << ", minDistSingle: " << minDistSingle * 1.0 / N << " ( "; + + for (auto i : ii) + std::cout << i << ", "; + std::cout << " )" << std::endl; + + gMinDist = std::min(gMinDist, minDis); + gMinDistSingle = std::min(gMinDistSingle, minDistSingle); + + std::cout << "size " << double(sets.size())/n << std::endl; + }; + + for (u64 tIdx = 0; tIdx < nt; ++tIdx) + { + thrds[tIdx] = std::thread( + [&, tIdx] { + Matrix sig(n, bw); + + for (u64 t = tIdx; t < tt; t += nt) + { + runOne(t, sig); + } + }); + } + + for (u64 tIdx = 0; tIdx < nt; ++tIdx) + thrds[tIdx].join(); + + std::cout << "\n\ngMinDist:" << gMinDist * 1.0 / N << " gMinDistSingle: " << gMinDistSingle * 1.0 / N << std::endl; + } +} \ No newline at end of file diff --git a/libOTe/Tools/EACode/EAChecker.h b/libOTe/Tools/EACode/EAChecker.h index 89a750e..44866f9 100644 --- a/libOTe/Tools/EACode/EAChecker.h +++ b/libOTe/Tools/EACode/EAChecker.h @@ -13,288 +13,8 @@ namespace osuCrypto { - //struct Signature - //{ - // u64 mI; - // std::vector mIdx; - // Signature(std::vector idx, u64 i) - // : mI(i) - // , mIdx(std::move(idx)) - // { - // } - u64 hash(span mIdx, u64 b, u64 N) - { - //RandomOracle ro(sizeof(u64)); - - //for (u64 j = 0; j < mIdx.size(); ++j) - // ro.Update(mIdx[j] * b / N); - //u64 h; - //ro.Final(h); - //return h; - - block hh = ZeroBlock; - for (u64 j = 0; j < mIdx.size(); ++j) - hh = hh ^ mAesFixedKey.ecbEncBlock(block(mIdx[j], j)); - return hh.get(0); - } - - std::vector ahash(span mIdx, u64 numBins, u64 N, double d, bool verbose) - { - std::vector H, B; - H.push_back(hash(mIdx, numBins, N)); - - auto binSize = N / numBins; - auto threshold = N * d / numBins; - - u64 lastBin = numBins - 1; - std::vector tweaks, tweakIdx; - for (u64 j = 0; j < mIdx.size(); ++j) - { - auto bIdx = mIdx[j] * numBins / N; - auto bRem = mIdx[j] - bIdx * N / numBins; - - - //if (verbose) - // std::cout << bIdx << ", r " << bRem << " vs " << threshold << std::endl; - if (bRem < threshold && bRem != 0) - { - //if (verbose) - // std::cout << "v- " << bRem << " < " << threshold << std::endl; - tweakIdx.push_back(j); - tweaks.push_back(-1); - } - if (bRem > binSize - threshold && bRem != lastBin) - { - //if (verbose) - // std::cout << "v+ " << bRem << " < " << threshold << std::endl; - tweakIdx.push_back(j); - tweaks.push_back(1); - } - - B.push_back(bIdx); - } - - for (u64 i = 1; i < (1ull << tweakIdx.size()); ++i) - { - RandomOracle ro(sizeof(u64)); - BitIterator iIter((u8*)&i); - auto bb = B; - for (u64 j = 0; j < tweakIdx.size(); ++j) - { - if (*iIter++) - { - bb[tweakIdx[j]] += tweaks[j]; - } - } - - //ro.Update(bb.data(), bb.size()); - //u64 h; - //ro.Final(h); - //H.push_back(h); - - block hh = ZeroBlock; - for (u64 j = 0; j < bb.size(); ++j) - hh = hh ^ mAesFixedKey.ecbEncBlock(block(bb[j], j)); - H.push_back(hh.get(0)); - } - return H; - } - //}; - - - void EAChecker(CLP& cmd) - { - u64 seed = cmd.getOr("s", 0); - u64 tt = cmd.getOr("t", 1); - u64 nt = cmd.getOr("nt", 1); - u64 n = cmd.getOr("n", 10000); - u64 e = cmd.getOr("e", 5); - - u64 N = n * e; - u64 k = cmd.getOr("k", 7); - - u64 b = cmd.getOr("b", 50); - - bool v = cmd.isSet("v"); - - double d = cmd.getOr("d", 0.25); - - bool highWeight = cmd.isSet("hw"); - std::vector thrds(nt); - std::mutex mutex; - u64 mm = -1, m0 = -1; - auto runOne = [&](u64 t, Matrix& sig) - { - - std::vector xx(2 * k), ii;; - - std::unordered_map> sets; - //sig.reserve(n); - - u64 max = 0, minDis = N, min0 = -1; - PRNG prng(block(seed, t)); - for (u64 i = 0; i < n; ++i) - { - auto x = sig[i]; - //if (v) - // std::cout << i << ": "; - for (u64 j = 0; j < k; ++j) - { - x[j] = prng.get() % N; - - //if (v) - // std::cout << x[j] << " "; - } - //if (v) - // std::cout << std::endl; - std::sort(x.begin(), x.end()); - u64 mm0 =0; - for (u64 j = 0; j < k-1; j += 2) - { - mm0 += x[j + 1] - x[j]; - } - if (k & 1) - mm += N-x.back(); - - - min0 = std::min(min0, mm); - //sig.emplace_back(x, i); - - auto H = ahash(sig[i], b, N, d, i == 709209); - - //if (i == 709209 || i == 483878) - //{ - // std::cout << "----------------------- " << i << std::endl; - // for (u64 j = 0; j < x.size(); ++j) - // std::cout << x[j] << " "; - // std::cout << std::endl; - // for (u64 j = 0; j < x.size(); ++j) - // std::cout << x[j] * b / N << " "; - // std::cout << std::endl; - // for (u64 j = 0; j < x.size(); ++j) - // { - // auto bIdx = (x[j] * b / N); - // auto bStart = bIdx * N / b; - // auto f = (x[j] - bStart ) / double(N / b); - // std::cout << f << " "; - // } - // std::cout << std::endl; - // for (u64 j = 0; j < H.size(); ++j) - // std::cout << j << " " << H[j] << std::endl; - //} - - for (auto h : H) - { - auto& ss = sets[h]; - ss.push_back(i); - if (ss.size() > max) - { - max = ss.size(); - - if (v) - std::cout << "m" << max << " " << i << std::endl; - } - - if (highWeight) - { - u64 pow = 1ull << (ss.size() - 1); - for (u64 jj = 1; jj < pow; ++jj) - { - xx.clear(); - xx.insert(xx.end(), x.begin(), x.end()); - for (u64 j = 0; j < ss.size() - 1; ++j) - { - if (jj & (1ull << j)) - { - auto s2 = sig[ss[j]]; - xx.insert(xx.end(), s2.begin(), s2.end()); - } - } - - std::sort(xx.begin(), xx.end()); - u64 d = 0; - for (u64 t = 0; t < xx.size() - 1; t += 2) - { - d += (xx[t + 1] - xx[t]); - } - if (xx.size() & 1) - { - d += (N - 1) - xx.back(); - } - - if (d < minDis) - { - ii = { { i } }; - for (u64 j = 0; j < ss.size() - 1; ++j) - { - if (jj & (1ull << j)) - ii.push_back(ss[j]); - } - minDis = d; - if (v) - std::cout << minDis << std::endl; - } - } - } - else - { - for (u64 j = 0; j < ss.size() - 1; ++j) - { - //std::cout << ss[j] << " vs " << i << std::endl; - - xx.clear(); - xx.insert(xx.end(), x.begin(), x.end()); - auto s2 = sig[ss[j]]; - xx.insert(xx.end(), s2.begin(), s2.end()); - std::sort(xx.begin(), xx.end()); - - u64 d = 0; - for (u64 t = 0; t < k; ++t) - { - if (xx[2 * t + 1] < xx[2 * t]) - throw RTE_LOC; - d += (xx[2 * t + 1] - xx[2 * t]); - } - if (d < minDis) - { - ii = { { i, ss[j] } }; - minDis = d; - if (v) - std::cout << minDis << std::endl; - } - } - } - - } - } - - std::lock_guard lock(mutex); - std::cout << max << " " << minDis * 1.0 / N << " " << min0 *1.0 / N<<" ( "; - - for (auto i : ii) - std::cout << i << ", "; - std::cout << " )" << std::endl; - - mm = std::min(mm, minDis); - m0 = std::min(m0, min0); - }; - for (u64 tIdx = 0; tIdx < nt; ++tIdx) - { - thrds[tIdx] = std::thread( - [&,tIdx]{ - Matrix sig(n, k); - - for (u64 t = tIdx; t < tt; t += nt) - { - runOne(t, sig); - } - }); - } - - for (u64 tIdx = 0; tIdx < nt; ++tIdx) - thrds[tIdx].join(); - - std::cout << "\n\n" << mm * 1.0 / N << " " << m0 * 1.0 / N << std::endl; - } + // the (psuedo) minimum distance finder for EA codes. + // section 4.2 https://eprint.iacr.org/2023/882 + void EAChecker(CLP& cmd); } \ No newline at end of file diff --git a/libOTe/Tools/EACode/EACode.h b/libOTe/Tools/EACode/EACode.h index e99ddf6..0e00fc9 100644 --- a/libOTe/Tools/EACode/EACode.h +++ b/libOTe/Tools/EACode/EACode.h @@ -24,13 +24,30 @@ namespace osuCrypto class EACode : public ExpanderCode, public TimerAdapter { public: - using ExpanderCode::config; + + void config( + u64 messageSize, + u64 codeSize, + u64 expanderWeight, + block seed = block(33333, 33333)) + { + ExpanderCode::config(messageSize, codeSize, expanderWeight, false, seed); + } // Compute w = G * e. template void dualEncode(span e, span w, Ctx ctx); + template + void dualEncode(Iter iter, Ctx ctx) + { + span e(iter, iter + mCodeSize); + AlignedUnVector w(mMessageSize); + dualEncode(e, w, ctx); + std::copy(w.begin(), w.end(), iter); + } + template void dualEncode2( span e0, diff --git a/libOTe/Tools/EACode/Util.h b/libOTe/Tools/EACode/Util.h index 8d08fe0..189f9e1 100644 --- a/libOTe/Tools/EACode/Util.h +++ b/libOTe/Tools/EACode/Util.h @@ -33,31 +33,27 @@ namespace osuCrypto value_type mPow2Mask; block mPow2MaskBlk; - //static const auto numIdx = + ExpanderModd() = default; ExpanderModd(block seed, u64 m) - : prng(seed, 256) - , modVal(m) - , mod(libdivide::libdivide_u64_gen(m)) { + init(seed, m); + } + + void init(block seed, u64 m) + { + prng = PRNG(seed, 256); + modVal = (m); + mod = (libdivide::libdivide_u64_gen(m)); mPow2 = log2ceil(modVal); mIsPow2 = mPow2 == log2floor(modVal); - //mIsPow2 = false; if (mIsPow2) { mPow2Mask = modVal - 1; - //mPow2MaskBlk = std::array{ mPow2Mask, mPow2Mask, mPow2Mask, mPow2Mask }; mPow2MaskBlk = std::array{ mPow2Mask, mPow2Mask}; - //mPow2Step = divCeil(mPow2, 8); - //mPow2Vals.resize(prng.mBufferByteCapacity / mPow2Step); - //vals = mPow2Vals; - } - else - { - //throw RTE_LOC; } - //vals = span((u64*)prng.mBuffer.data(), prng.mBuffer.size() * 2); - //std::cout << "mIsPow2 " << mIsPow2 << std::endl; + + vals.resize(prng.mBuffer.size() * sizeof(block) / sizeof(vals[0])); refill(); } @@ -67,16 +63,11 @@ namespace osuCrypto idx = 0; assert(prng.mBuffer.size() == 256); - //block b[8]; for (u64 i = 0; i < 256; i += 8) { - //auto idx = mPrng.mBuffer[i].get(); block* __restrict b = prng.mBuffer.data() + i; block* __restrict k = prng.mBuffer.data() + (u8)(i - 8); - //for (u64 j = 0; j < 8; ++j) - //{ - // b = b ^ mPrng.mBuffer.data()[idx[j]]; - //} + b[0] = AES::roundEnc(b[0], k[0]); b[1] = AES::roundEnc(b[1], k[1]); b[2] = AES::roundEnc(b[2], k[2]); @@ -104,16 +95,11 @@ namespace osuCrypto dst[i + 5] = src[i + 5] & mPow2MaskBlk; dst[i + 6] = src[i + 6] & mPow2MaskBlk; dst[i + 7] = src[i + 7] & mPow2MaskBlk; - //vals[i] - //vals.data()[i] = *(u64*)ptr & mPow2Mask; - //ptr += mPow2Step; - //++ptr; } } else { memcpy(dst, src, vals.size() * sizeof(value_type)); - //assert(vals.size() % 32 == 0); for (u64 i = 0; i < vals.size(); i += 32) doMod32(vals.data() + i, &mod, modVal); } diff --git a/libOTe/Tools/ExConvCode/ExConvChecker.cpp b/libOTe/Tools/ExConvCode/ExConvChecker.cpp new file mode 100644 index 0000000..532d7c3 --- /dev/null +++ b/libOTe/Tools/ExConvCode/ExConvChecker.cpp @@ -0,0 +1,192 @@ +#include "ExConvChecker.h" +#include "libOTe/Tools/ExConvCode/ExConvCode.h" +#include +#include "libOTe/Tools/CoeffCtx.h" + +namespace osuCrypto +{ + + + Matrix getAccumulator_(ExConvCode& encoder) + { + auto k = encoder.mMessageSize;; + auto n = encoder.mCodeSize;; + if (encoder.mSystematic == false) + throw RTE_LOC;//not impl + + auto d = n - k; + Matrix g(d, d); + for (u64 i = 0; i < d; ++i) + { + std::vector x(d); + x[i] = 1; + CoeffCtxGF2 ctx; + encoder.accumulate(x.data(), ctx); + + for (u64 j = 0; j < d; ++j) + { + g(j, i) = x[j]; + } + } + return g; + } + + + u64 getAccWeight(ExConvCode& encoder, u64 trials) + { + auto n = encoder.mCodeSize; + //auto g = getGenerator(encoder); + auto g = getAccumulator_(encoder); + auto G = compress(g); + + auto N = G.cols(); + + u64 min = n; + + + u64 step, exSize; + if (encoder.mExpander.mRegular) + exSize = step = encoder.mExpander.mCodeSize / encoder.mExpander.mExpanderWeight; + else + { + step = 0; + exSize = n; + } + detail::ExpanderModd prng(encoder.mExpander.mSeed, exSize); + + + for (u64 i = 0; i < trials; ++i) + { + u64 weight = 0; + for (u64 j = 0; j < N; ++j) + { + block sum = ZeroBlock; + for (u64 k = 0; k < encoder.mExpander.mExpanderWeight; ++k) + { + auto idx = prng.get() + step * k; + sum = sum ^ G(j, idx); + } + + weight += + popcount(sum.get(0)) + + popcount(sum.get(1)); + //weight += g(i, j); + } + + min = std::min(min, weight); + } + + return min; + } + + + //u64 getGeneratorWeight(ExConvCode& encoder) + //{ + // auto k = encoder.mMessageSize; + // auto n = encoder.mCodeSize; + // auto g = getGenerator(encoder); + // bool failed = false; + // u64 min = n; + // u64 iMin = 0;; + // for (u64 i = 0; i < k; ++i) + // { + // u64 weight = 0; + // for (u64 j = 0; j < n; ++j) + // { + // //if (verbose) + // //{ + // // if (g(i, j)) + // // std::cout << Color::Green << "1" << Color::Default; + // // else + // // std::cout << "0"; + // //} + // assert(g(i, j) < 2); + // weight += g(i, j); + // } + // //if (verbose) + // // std::cout << std::endl; + + // if (weight < min) + // iMin = i; + // min = std::min(min, weight); + // } + //} + + void ExConvChecker(const oc::CLP& cmd) + { + u64 k = cmd.getOr("k", 1ull << cmd.getOr("kk", 6)); + u64 n = k * 2; + bool verbose = cmd.isSet("v"); + bool accTwice = cmd.getOr("accTwice", 1); + bool sys = cmd.getOr("sys", 1); + bool reg = cmd.getOr("reg", 1); + u64 nt = cmd.getOr("nt", 1); + + u64 trials = cmd.getOr("trials", 1); + u64 awBeing = cmd.getOr("aw", 0); + u64 awEnd = cmd.getOr("awEnd", 20); + u64 bwBeing = cmd.getOr("bw", 3); + u64 bwEnd = cmd.getOr("bwEnd", 11); + + for (u64 aw = awBeing; aw < awEnd; aw += 2) + { + for (u64 bw = bwBeing; bw < bwEnd; bw += 2) + { + + + u64 avg = 0; + u64 gMin = n; + std::mutex mtx; + u64 ticks = n * trials; + std::atomic done = 0; + auto routine = [&](u64 i) { + for (u64 j = i; j < trials; j += nt) + { + + ExConvCode encoder; + encoder.config(k, n, bw, aw, sys, reg, block(21341234, j)); + encoder.mAccTwice = accTwice; + + u64 min = 0; + if (cmd.isSet("x2")) + min = getGeneratorWeightx2(encoder, verbose); + else + min = getGeneratorWeight&>(encoder, verbose, done); + + std::lock_guard lock(mtx); + gMin = std::min(gMin, min); + avg += min; + } + }; + + std::vector thrds(nt); + for (u64 i = 0; i < thrds.size(); ++i) + { + thrds[i] = std::thread(routine, i); + } + //routine(nt - 1); + u64 sleep = 1; + while (done != ticks) + { + std::this_thread::sleep_for(std::chrono::milliseconds(sleep)); + sleep = std::min(1000, sleep * 2); + + u64 d = double(done) * 40 / ticks; + + std::cout << "[" << std::string(d, '|') << std::string(40 - d, ' ') << "] " << double(done) * 100 / ticks << "%\r" << std::flush; + } + std::cout < + Matrix getGenerator(Code& encoder) + { + auto k = encoder.mMessageSize; + auto n = encoder.mCodeSize;; + Matrix g(k, n); + for (u64 i = 0; i < n; ++i) + { + std::vector x(n); + x[i] = 1; + encoder.template dualEncode(x.data(), {}); + + + for (u64 j = 0; j < k; ++j) + { + g.data(j)[i] = x[j]; + } + } + return g; + } + + inline Matrix compress(Matrix g) + { + Matrix G(g.rows(), divCeil(g.cols(), 128)); + for (u64 i = 0; i < g.rows(); ++i) + { + for (u64 j = 0; j < g.cols(); ) + { + if (j + 8 < g.cols()) + { + auto gij = &g(i, j); + u8 b = gij[0] << 0 + | gij[1] << 1 + | gij[2] << 2 + | gij[3] << 3 + | gij[4] << 4 + | gij[5] << 5 + | gij[6] << 6 + | gij[7] << 7; + + ((u8*)G.data(i))[j / 8] = b; + + j += 8; + } + else + { + *BitIterator((u8*)G.data(i), j) = g(i, j); + ++j; + } + } + } + return G; + } + + template + u64 getGeneratorWeightx2(Code& encoder, bool verbose) + { + auto k = encoder.mMessageSize; + auto n = encoder.mCodeSize; + auto g = getGenerator(encoder); + auto G = compress(g); + + u64 min = n; + auto N = G.cols(); + for (u64 i = 0; i < k; ++i) + { + for (u64 i2 = 0; i2 < k; ++i2) + { + auto gg = G.data(i); + u64 weight = 0; + if (i == i2) + { + for (u64 j = 0; j < N; ++j) + { + weight += + popcount(gg[j].template get(0)) + + popcount(gg[j].template get(1)); + } + + } + else + { + auto gg2 = G.data(i2); + for (u64 j = 0; j < N; ++j) + { + auto gj = gg[j] ^ gg2[j]; + weight += + popcount(gj.template get(0)) + + popcount(gj.template get(1)); + } + } + + if (verbose) + { + std::cout << i << " \n"; + for (u64 j = 0; j < n; ++j) + { + if (g(i, j)) + std::cout << Color::Green << "1" << Color::Default; + else + std::cout << "0"; + } + std::cout << "\n"; + + if (i != i2) + { + + std::cout << i2 << " \n"; + for (u64 j = 0; j < n; ++j) + { + if (g(i2, j)) + std::cout << Color::Green << "1" << Color::Default; + else + std::cout << "0"; + } + std::cout << "\n"; + } + + } + min = std::min(min, weight); + } + } + return min; + } + + template + u64 getGeneratorWeight(Code& encoder, bool verbose, Count c = {}) + { + auto k = encoder.mMessageSize; + auto n = encoder.mCodeSize; + //auto g = getGenerator(encoder); + + std::vector weights(k); + for (u64 i = 0; i < n; ++i) + { + std::vector x(n); + x[i] = 1; + encoder.template dualEncode(x.data(), {}); + + for (u64 j = 0; j < k; ++j) + { + weights[j] += x[j]; + } + ++c; + } + return *std::min_element(weights.begin(), weights.end()); + } + +} \ No newline at end of file diff --git a/libOTe/Tools/ExConvCode/ExConvCode.h b/libOTe/Tools/ExConvCode/ExConvCode.h index 0a574fc..5223c8b 100644 --- a/libOTe/Tools/ExConvCode/ExConvCode.h +++ b/libOTe/Tools/ExConvCode/ExConvCode.h @@ -70,6 +70,7 @@ namespace osuCrypto u64 expanderWeight = 7, u64 accumulatorWeight = 16, bool systematic = true, + bool regularExpander = true, block seed = block(9996754675674599, 56756745976768754)); // the seed that generates the code. @@ -87,6 +88,10 @@ namespace osuCrypto // is the code systematic (true=faster) bool mSystematic = true; + // accumulate twice, this guards against an weakness when the expander expands + // into a small region. This region could be at the end and therefore small weight. + bool mAccTwice = true; + // return n-k. code size n, message size k. u64 parityRows() const { return mCodeSize - mMessageSize; } @@ -155,9 +160,10 @@ namespace osuCrypto typename Iter > OC_FORCEINLINE void accOne8( - Iter&& xi, - Iter&& xj, - Iter&& end, + Iter X, + u64 i, + u64 j, + u64 size, u8 b, CoeffCtx& ctx); @@ -170,8 +176,9 @@ namespace osuCrypto typename Iter > OC_FORCEINLINE void accOne( - Iter&& xi, - Iter&& end, + Iter x, + u64 i, + u64 size, u8* matrixCoeff, CoeffCtx& ctx); @@ -183,8 +190,9 @@ namespace osuCrypto typename Iter > OC_FORCEINLINE void accOneGen( - Iter&& xi, - Iter&& end, + Iter x, + u64 i, + u64 size, u8* matrixCoeff, CoeffCtx& ctx); @@ -199,17 +207,24 @@ namespace osuCrypto Iter x, CoeffCtx& ctx) { + auto size = mCodeSize - mSystematic * mMessageSize; switch (mAccumulatorSize) { - case 16: - accumulateFixed(std::forward(x), ctx); - break; + //case 16: + // accumulateFixed(std::forward(x), ctx); + // accumulateFixed(std::forward(x), ctx); + // break; case 24: - accumulateFixed(std::forward(x), ctx); + accumulateFixed(std::forward(x), size, ctx, mSeed); + + if (mAccTwice) + accumulateFixed(std::forward(x), size, ctx, ~mSeed); break; default: // generic case - accumulateFixed(std::forward(x), ctx); + accumulateFixed(std::forward(x), size, ctx, mSeed); + if (mAccTwice) + accumulateFixed(std::forward(x), size, ctx, ~mSeed); } } @@ -220,8 +235,11 @@ namespace osuCrypto u64 AccumulatorSize, typename Iter > - void accumulateFixed(Iter x, - CoeffCtx& ctx); + void accumulateFixed( + Iter x, + u64 size, + CoeffCtx& ctx, + block seed); }; @@ -232,6 +250,7 @@ namespace osuCrypto u64 expanderWeight, u64 accumulatorSize, bool systematic, + bool regularExpander, block seed) { if (codeSize == 0) @@ -242,7 +261,7 @@ namespace osuCrypto mCodeSize = codeSize; mAccumulatorSize = accumulatorSize; mSystematic = systematic; - mExpander.config(messageSize, codeSize - messageSize * systematic, expanderWeight, seed ^ CCBlock); + mExpander.config(messageSize, codeSize - messageSize * systematic, expanderWeight, regularExpander, seed ^ CCBlock); } // Compute e[0,...,k-1] = G * e. @@ -253,6 +272,9 @@ namespace osuCrypto { static_assert(is_iterator::value, "must pass in an iterator to the data"); + if(mCodeSize == 0) + throw RTE_LOC; + (void)*(e_ + mCodeSize - 1); auto e = ctx.template restrictPtr(e_); @@ -263,7 +285,9 @@ namespace osuCrypto setTimePoint("ExConv.encode.begin"); accumulate(d, ctx); setTimePoint("ExConv.encode.accumulate"); + mExpander.expand(d, e, ctx); + setTimePoint("ExConv.encode.expand"); } else @@ -278,6 +302,7 @@ namespace osuCrypto auto wIter = ctx.template restrictPtr(w.begin()); mExpander.expand(e, wIter, ctx); + setTimePoint("ExConv.encode.expand"); ctx.copy(w.begin(), w.end(), e); @@ -297,12 +322,38 @@ namespace osuCrypto typename Iter > OC_FORCEINLINE void ExConvCode::accOne8( - Iter&& xi, - Iter&& xj, - Iter&& end, + Iter X, + u64 i, + u64 j, + u64 size, u8 b, CoeffCtx& ctx) { + auto xi = X + i; + + u64 js[8]; + js[0] = j + 0; + js[1] = j + 1; + js[2] = j + 2; + js[3] = j + 3; + js[4] = j + 4; + js[5] = j + 5; + js[6] = j + 6; + js[7] = j + 7; + + // xj += bj * xi + if constexpr (rangeCheck) + { + // j mod size + js[0] = js[0] >= size ? js[0] - size : js[0]; + js[1] = js[1] >= size ? js[1] - size : js[1]; + js[2] = js[2] >= size ? js[2] - size : js[2]; + js[3] = js[3] >= size ? js[3] - size : js[3]; + js[4] = js[4] >= size ? js[4] - size : js[4]; + js[5] = js[5] >= size ? js[5] - size : js[5]; + js[6] = js[6] >= size ? js[6] - size : js[6]; + js[7] = js[7] >= size ? js[7] - size : js[7]; + } #ifdef ENABLE_SSE if constexpr (std::is_same::value) @@ -355,23 +406,14 @@ namespace osuCrypto assert((((b >> 6) & 1) ? *xi : ZeroBlock) == tt[6]); assert((((b >> 7) & 1) ? *xi : ZeroBlock) == tt[7]); - // xj += bj * xi - if (rangeCheck && xj + 0 == end) return; - ctx.plus(*(xj + 0), *(xj + 0), tt[0]); - if (rangeCheck && xj + 1 == end) return; - ctx.plus(*(xj + 1), *(xj + 1), tt[1]); - if (rangeCheck && xj + 2 == end) return; - ctx.plus(*(xj + 2), *(xj + 2), tt[2]); - if (rangeCheck && xj + 3 == end) return; - ctx.plus(*(xj + 3), *(xj + 3), tt[3]); - if (rangeCheck && xj + 4 == end) return; - ctx.plus(*(xj + 4), *(xj + 4), tt[4]); - if (rangeCheck && xj + 5 == end) return; - ctx.plus(*(xj + 5), *(xj + 5), tt[5]); - if (rangeCheck && xj + 6 == end) return; - ctx.plus(*(xj + 6), *(xj + 6), tt[6]); - if (rangeCheck && xj + 7 == end) return; - ctx.plus(*(xj + 7), *(xj + 7), tt[7]); + ctx.plus(*(X + js[0]), *(X + js[0]), tt[0]); + ctx.plus(*(X + js[1]), *(X + js[1]), tt[1]); + ctx.plus(*(X + js[2]), *(X + js[2]), tt[2]); + ctx.plus(*(X + js[3]), *(X + js[3]), tt[3]); + ctx.plus(*(X + js[4]), *(X + js[4]), tt[4]); + ctx.plus(*(X + js[5]), *(X + js[5]), tt[5]); + ctx.plus(*(X + js[6]), *(X + js[6]), tt[6]); + ctx.plus(*(X + js[7]), *(X + js[7]), tt[7]); } else #endif @@ -385,22 +427,14 @@ namespace osuCrypto auto b6 = b & 64; auto b7 = b & 128; - if (rangeCheck && xj + 0 == end) return; - if (b0) ctx.plus(*(xj + 0), *(xj + 0), *xi); - if (rangeCheck && xj + 1 == end) return; - if (b1) ctx.plus(*(xj + 1), *(xj + 1), *xi); - if (rangeCheck && xj + 2 == end) return; - if (b2) ctx.plus(*(xj + 2), *(xj + 2), *xi); - if (rangeCheck && xj + 3 == end) return; - if (b3) ctx.plus(*(xj + 3), *(xj + 3), *xi); - if (rangeCheck && xj + 4 == end) return; - if (b4) ctx.plus(*(xj + 4), *(xj + 4), *xi); - if (rangeCheck && xj + 5 == end) return; - if (b5) ctx.plus(*(xj + 5), *(xj + 5), *xi); - if (rangeCheck && xj + 6 == end) return; - if (b6) ctx.plus(*(xj + 6), *(xj + 6), *xi); - if (rangeCheck && xj + 7 == end) return; - if (b7) ctx.plus(*(xj + 7), *(xj + 7), *xi); + if (b0) ctx.plus(*(X + js[0]), *(X + js[0]), *xi); + if (b1) ctx.plus(*(X + js[1]), *(X + js[1]), *xi); + if (b2) ctx.plus(*(X + js[2]), *(X + js[2]), *xi); + if (b3) ctx.plus(*(X + js[3]), *(X + js[3]), *xi); + if (b4) ctx.plus(*(X + js[4]), *(X + js[4]), *xi); + if (b5) ctx.plus(*(X + js[5]), *(X + js[5]), *xi); + if (b6) ctx.plus(*(X + js[6]), *(X + js[6]), *xi); + if (b7) ctx.plus(*(X + js[7]), *(X + js[7]), *xi); } } @@ -413,55 +447,53 @@ namespace osuCrypto typename Iter > OC_FORCEINLINE void ExConvCode::accOneGen( - Iter&& xi, - Iter&& end, + Iter X, + u64 i, + u64 size, u8* matrixCoeff, CoeffCtx& ctx) { - // xj += xi - std::remove_reference_t xj = xi + 1; - if (!rangeCheck || xj < end) - { - ctx.plus(*xj, *xj, *xi); - ctx.mulConst(*xj, *xj); - ++xj; - } + auto xi = X + i; + + u64 j = i + 1; + if (rangeCheck && j >= size) + j -= size; // xj += bj * xi u64 k = 0; - for (; k < mAccumulatorSize - 7; k += 8) + for (; k + 7 < mAccumulatorSize; k += 8) { - accOne8(xi, xj, end, *matrixCoeff++, ctx); + accOne8(X, i, j, size, *matrixCoeff++, ctx); - if constexpr (rangeCheck) - { - auto r = end - xj; - xj += std::min(r, 8); - } - else - { - xj += 8; - } + j += 8; + if (rangeCheck && j >= size) + j -= size; } + + // xj += bj * xi for (; k < mAccumulatorSize; ) { auto b = *matrixCoeff++; - for (u64 j = 0; j < 8 && k < mAccumulatorSize; ++j, ++k) + for (u64 p = 0; p < 8 && k < mAccumulatorSize; ++p, ++k) { - - if (rangeCheck == false || (xj != end)) + if (b & 1) { - if (b & 1) - ctx.plus(*xj, *xj, *xi); - - ++xj; - b >>= 1; + auto xj = X + j; + ctx.plus(*xj, *xj, *xi); } + b >>= 1; + ++j; + if (rangeCheck && j >= size) + j -= size; } } + + auto xj = X + j; + ctx.plus(*xj, *xj, *xi); + ctx.mulConst(*xj, *xj); } @@ -474,38 +506,37 @@ namespace osuCrypto typename Iter > OC_FORCEINLINE void ExConvCode::accOne( - Iter&& xi, - Iter&& end, + Iter X, + u64 i, + u64 size, u8* matrixCoeff, CoeffCtx& ctx) { static_assert(AccumulatorSize, "should have called the other overload"); static_assert(AccumulatorSize % 8 == 0, "must be a multiple of 8"); - // xj += xi - std::remove_reference_t xj = xi + 1; - if (!rangeCheck || xj < end) - { - ctx.plus(*xj, *xj, *xi); - ctx.mulConst(*xj, *xj); - ++xj; - } + + auto xi = X + i; + + u64 j = i + 1; + if (rangeCheck && j >= size) + j -= size; + // xj += bj * xi for (u64 k = 0; k < AccumulatorSize; k += 8) { - accOne8(xi, xj, end, *matrixCoeff++, ctx); + accOne8(X, i, j, size, *matrixCoeff++, ctx); - if constexpr (rangeCheck) - { - auto r = end - xj; - xj += std::min(r, 8); - } - else - { - xj += 8; - } + j += 8; + if (rangeCheck && j >= size) + j -= size; } + + auto xj = X + j; + ctx.plus(*xj, *xj, *xi); + ctx.mulConst(*xj, *xj); + } // accumulate x onto itself. @@ -516,13 +547,15 @@ namespace osuCrypto typename Iter > void ExConvCode::accumulateFixed( - Iter xi, - CoeffCtx& ctx) + Iter X, + u64 size, + CoeffCtx& ctx, + block seed) { - auto end = xi + (mCodeSize - mSystematic * mMessageSize); - auto main = end - 1 - mAccumulatorSize; + u64 i = 0; + auto main = size - 1 - mAccumulatorSize; - PRNG prng(mSeed ^ OneBlock); + PRNG prng(seed); u8* mtxCoeffIter = (u8*)prng.mBuffer.data(); auto mtxCoeffEnd = mtxCoeffIter + prng.mBuffer.size() * sizeof(block) - divCeil(mAccumulatorSize, 8); @@ -532,7 +565,7 @@ namespace osuCrypto if (AccumulatorSize && mAccumulatorSize != AccumulatorSize) throw RTE_LOC; - while (xi < main) + while (i < main) { if (mtxCoeffIter > mtxCoeffEnd) { @@ -542,14 +575,14 @@ namespace osuCrypto } // add xi to the next positions - if constexpr(AccumulatorSize == 0) - accOneGen(xi, end, mtxCoeffIter++, ctx); + if constexpr (AccumulatorSize == 0) + accOneGen(X, i, size, mtxCoeffIter++, ctx); else - accOne(xi, end, mtxCoeffIter++, ctx); - ++xi; + accOne(X, i, size, mtxCoeffIter++, ctx); + ++i; } - while (xi < end) + while (i < size) { if (mtxCoeffIter > mtxCoeffEnd) { @@ -560,10 +593,10 @@ namespace osuCrypto // add xi to the next positions if constexpr (AccumulatorSize == 0) - accOneGen(xi, end, mtxCoeffIter++, ctx); + accOneGen(X, i, size, mtxCoeffIter++, ctx); else - accOne(xi, end, mtxCoeffIter++, ctx); - ++xi; + accOne(X, i, size, mtxCoeffIter++, ctx); + ++i; } } diff --git a/libOTe/Tools/ExConvCode/Expander.h b/libOTe/Tools/ExConvCode/Expander.h index 1bd9803..1ecc654 100644 --- a/libOTe/Tools/ExConvCode/Expander.h +++ b/libOTe/Tools/ExConvCode/Expander.h @@ -25,11 +25,13 @@ namespace osuCrypto u64 messageSize, u64 codeSize, u64 expanderWeight, + bool regularExpander = true, block seed = block(33333, 33333)) { mMessageSize = messageSize; mCodeSize = codeSize; mExpanderWeight = expanderWeight; + mRegular = regularExpander; mSeed = seed; } @@ -45,13 +47,15 @@ namespace osuCrypto // The row weight of the B matrix. u64 mExpanderWeight = 0; + bool mRegular = true; + u64 parityRows() const { return mCodeSize - mMessageSize; } u64 parityCols() const { return mCodeSize; } u64 generatorRows() const { return mMessageSize; } u64 generatorCols() const { return mCodeSize; } - + // expand uniformly with the desired weight template< typename F, typename CoeffCtx, @@ -66,6 +70,21 @@ namespace osuCrypto ) const; + //// expand so that each region has weight 1. + //template< + // typename F, + // typename CoeffCtx, + // bool add, + // typename SrcIter, + // typename DstIter + //> + //void expandRegular( + // SrcIter&& input, + // DstIter&& output, + // CoeffCtx ctx = {} + //) const; + + //template< // bool Add, // typename CoeffCtx, @@ -76,6 +95,7 @@ namespace osuCrypto // std::tuple out, // CoeffCtx ctx = {})const; + Matrix getMatrix(); }; @@ -95,7 +115,6 @@ namespace osuCrypto (void)*(input + (mCodeSize - 1)); (void)*(output + (mMessageSize - 1)); - detail::ExpanderModd prng(mSeed, mCodeSize); auto rInput = ctx.template restrictPtr(input); auto rOutput = ctx.template restrictPtr(output); @@ -103,24 +122,59 @@ namespace osuCrypto auto main = mMessageSize / 8 * 8; u64 i = 0; - for (; i < main; i += 8, rOutput+= 8) + u64 reg = 0, uni = mExpanderWeight, step = 0; + detail::ExpanderModd uniGen(mSeed, mCodeSize), regGen; + if (mRegular) + { + uni = mExpanderWeight / 2; + reg = mExpanderWeight - uni; + step = mCodeSize / reg; + regGen.init(mSeed ^ block(342342134, 23421341), step); + } + + + for (; i < main; i += 8, rOutput += 8) { if constexpr (Add == false) { ctx.zero(rOutput, rOutput + 8); } + + // regular expanders + for (auto j = 0ull; j < reg; ++j) + { + u64 rr[8]; + rr[0] = regGen.get() + j * step; + rr[1] = regGen.get() + j * step; + rr[2] = regGen.get() + j * step; + rr[3] = regGen.get() + j * step; + rr[4] = regGen.get() + j * step; + rr[5] = regGen.get() + j * step; + rr[6] = regGen.get() + j * step; + rr[7] = regGen.get() + j * step; + + ctx.plus(*(rOutput + 0), *(rOutput + 0), *(rInput + rr[0])); + ctx.plus(*(rOutput + 1), *(rOutput + 1), *(rInput + rr[1])); + ctx.plus(*(rOutput + 2), *(rOutput + 2), *(rInput + rr[2])); + ctx.plus(*(rOutput + 3), *(rOutput + 3), *(rInput + rr[3])); + ctx.plus(*(rOutput + 4), *(rOutput + 4), *(rInput + rr[4])); + ctx.plus(*(rOutput + 5), *(rOutput + 5), *(rInput + rr[5])); + ctx.plus(*(rOutput + 6), *(rOutput + 6), *(rInput + rr[6])); + ctx.plus(*(rOutput + 7), *(rOutput + 7), *(rInput + rr[7])); + } - for (auto j = 0ull; j < mExpanderWeight; ++j) + // uniform expanders + for (auto j = 0ull; j < uni; ++j) { u64 rr[8]; - rr[0] = prng.get(); - rr[1] = prng.get(); - rr[2] = prng.get(); - rr[3] = prng.get(); - rr[4] = prng.get(); - rr[5] = prng.get(); - rr[6] = prng.get(); - rr[7] = prng.get(); + rr[0] = uniGen.get(); + rr[1] = uniGen.get(); + rr[2] = uniGen.get(); + rr[3] = uniGen.get(); + rr[4] = uniGen.get(); + rr[5] = uniGen.get(); + rr[6] = uniGen.get(); + rr[7] = uniGen.get(); ctx.plus(*(rOutput + 0), *(rOutput + 0), *(rInput + rr[0])); ctx.plus(*(rOutput + 1), *(rOutput + 1), *(rInput + rr[1])); @@ -139,14 +193,57 @@ namespace osuCrypto } for (; i < mMessageSize; ++i, ++rOutput) + { + for (auto j = 0ull; j < reg; ++j) + { + ctx.plus(*rOutput, *rOutput, *(input + regGen.get() + j * step)); + } + + for (auto j = 0ull; j < uni; ++j) + { + ctx.plus(*rOutput, *rOutput, *(input + uniGen.get())); + } + } + } + + inline Matrix ExpanderCode::getMatrix() + { + Matrix ret(mMessageSize, mExpanderWeight); + + auto main = mMessageSize / 8 * 8; + u64 i = 0; + + u64 step = mRegular ? mCodeSize / mExpanderWeight : 0; + detail::ExpanderModd prng(mSeed, mRegular ? mCodeSize / mExpanderWeight : mCodeSize); + + for (; i < main; i += 8) + { + for (auto j = 0ull; j < mExpanderWeight; ++j) + { + ret(i + 0, j) = prng.get() + step * j; + ret(i + 1, j) = prng.get() + step * j; + ret(i + 2, j) = prng.get() + step * j; + ret(i + 3, j) = prng.get() + step * j; + ret(i + 4, j) = prng.get() + step * j; + ret(i + 5, j) = prng.get() + step * j; + ret(i + 6, j) = prng.get() + step * j; + ret(i + 7, j) = prng.get() + step * j; + + } + } + + for (; i < mMessageSize; ++i) { for (auto j = 0ull; j < mExpanderWeight; ++j) { - ctx.plus(*rOutput, *rOutput, *(input + prng.get())); + ret(i, j) = prng.get() + step * j; } } + + return ret; } + //template< // bool Add, // typename CoeffCtx, diff --git a/libOTe/Tools/QuasiCyclicCode.h b/libOTe/Tools/QuasiCyclicCode.h index bcf9518..2bb9765 100644 --- a/libOTe/Tools/QuasiCyclicCode.h +++ b/libOTe/Tools/QuasiCyclicCode.h @@ -45,17 +45,6 @@ namespace osuCrypto //size of the input u64 size() { return mCodeSize; } - // initialize the compressing matrix that maps a - // vector of size n * scaler to a vector of size n. - void init(u64 n, u64 scaler = 2) - { - if (scaler <= 1) - throw RTE_LOC; - - mMessageSize = n; - mPrimeModulus = nextPrime(n); - mCodeSize = mMessageSize * scaler; - } void init2(u64 messageSize, u64 codeSize) { auto scaler = divCeil(codeSize, messageSize); diff --git a/libOTe/Tools/TungstenCode/TungstenCode.h b/libOTe/Tools/TungstenCode/TungstenCode.h index 76d174d..b66089d 100644 --- a/libOTe/Tools/TungstenCode/TungstenCode.h +++ b/libOTe/Tools/TungstenCode/TungstenCode.h @@ -148,6 +148,9 @@ namespace osuCrypto { > void dualEncode(Iter&& e, CoeffCtx ctx) { + if (mCodeSize == 0) + throw RTE_LOC; + using VecF = typename CoeffCtx::template Vec; VecF temp(mCodeSize - mMessageSize); diff --git a/libOTe/TwoChooseOne/ConfigureCode.cpp b/libOTe/TwoChooseOne/ConfigureCode.cpp index c206bb7..ca7ef15 100644 --- a/libOTe/TwoChooseOne/ConfigureCode.cpp +++ b/libOTe/TwoChooseOne/ConfigureCode.cpp @@ -12,217 +12,89 @@ namespace osuCrypto { - // We get e^{-2td} security against linear attacks, - // with noise weigh t and minDist d. + // We get e^{-2t d/N} security against linear attacks, + // with noise weight t and minDist d and code size N. // For regular we can be slightly more accurate with - // (1 − 2d)^t + // (1 − 2d/N)^t // which implies a bit security level of - // k = -t * log2(1 - 2d) - // t = -k / log2(1 - 2d) - u64 getRegNoiseWeight(double minDistRatio, u64 secParam) + // k = -t * log2(1 - 2d/N) + // t = -k / log2(1 - 2d/N) + // + // minDistRatio = d / N + // where d is the min dist and N is the code size. + u64 getRegNoiseWeight(double minDistRatio, u64 N, u64 secParam) { if (minDistRatio > 0.5 || minDistRatio <= 0) throw RTE_LOC; auto d = std::log2(1 - 2 * minDistRatio); - auto t = std::max(128, -double(secParam) / d); + auto t = std::max(40, -double(secParam) / d); + + if(N < 512) + t = std::max(t, 64); return roundUpTo(t, 8); } void EAConfigure( - u64 numOTs, u64 secParam, MultType mMultType, - u64& mRequestedNumOTs, - u64& mNumPartitions, - u64& mSizePer, - u64& mNoiseVecSize, - u64& mN, - EACode& mEncoder + u64& expanderWeight, + u64& scaler, + double& minDist ) { - auto mScaler = 2; - u64 w; - double minDist; + scaler = 5; switch (mMultType) { case osuCrypto::MultType::ExAcc7: - w = 7; + expanderWeight = 7; // this is known to be high but likely overall accurate minDist = 0.05; break; case osuCrypto::MultType::ExAcc11: - w = 11; + expanderWeight = 11; minDist = 0.1; break; case osuCrypto::MultType::ExAcc21: - w = 21; - minDist = 0.1; + expanderWeight = 21; + minDist = 0.15; break; case osuCrypto::MultType::ExAcc40: - w = 40; + expanderWeight = 41; minDist = 0.2; break; default: throw RTE_LOC; break; } - - mRequestedNumOTs = numOTs; - mNumPartitions = getRegNoiseWeight(minDist, secParam); - mSizePer = roundUpTo((numOTs * mScaler + mNumPartitions - 1) / mNumPartitions, 8); - mNoiseVecSize = mSizePer * mNumPartitions; - mN = mNoiseVecSize / mScaler; - - mEncoder.config(numOTs, numOTs * mScaler, w); } void ExConvConfigure( - u64 numOTs, u64 secParam, - MultType mMultType, - u64& mRequestedNumOTs, - u64& mNumPartitions, - u64& mSizePer, - u64& mNoiseVecSize, - u64& mN, - ExConvCode& mEncoder - ) - { - u64 a = 24; - auto mScaler = 2; - u64 w; - double minDist; - switch (mMultType) - { - case osuCrypto::MultType::ExConv7x24: - w = 7; - minDist = 0.1; - break; - case osuCrypto::MultType::ExConv21x24: - w = 21; - minDist = 0.15; - break; - default: - throw RTE_LOC; - break; - } - - mRequestedNumOTs = numOTs; - mNumPartitions = getRegNoiseWeight(minDist, secParam); - mSizePer = roundUpTo((numOTs * mScaler + mNumPartitions - 1) / mNumPartitions, 8); - mNoiseVecSize = mSizePer * mNumPartitions; - mN = mNoiseVecSize / mScaler; - - mEncoder.config(numOTs, numOTs * mScaler, w, a, true); - } - - - void ExConvConfigure( - double scaler, MultType mMultType, u64& expanderWeight, u64& accumulatorWeight, + u64& scaler, double& minDist) { - if (scaler != 2) - throw RTE_LOC; + scaler = 2; + switch (mMultType) { case osuCrypto::MultType::ExConv7x24: accumulatorWeight = 24; expanderWeight = 7; - minDist = 0.2; // psuedo min dist estimate + minDist = 0.15; // psuedo min dist estimate break; case osuCrypto::MultType::ExConv21x24: accumulatorWeight = 24; expanderWeight = 21; - minDist = 0.25; // psuedo min dist estimate + minDist = 0.2; // psuedo min dist estimate break; default: throw RTE_LOC; break; } - } - - -#ifdef ENABLE_INSECURE_SILVER - - void SilverConfigure( - u64 numOTs, u64 secParam, - MultType mMultType, - u64& mRequestedNumOTs, - u64& mNumPartitions, - u64& mSizePer, - u64& mN2, - u64& mN, - u64& gap, - SilverEncoder& mEncoder) - { - // warn the user on program exit. - struct Warned - { - ~Warned() - { - { - std::cout << oc::Color::Red << "WARNING: This program made use of the LPN silver encoder. " - << "This encoder is insecure and should not be used in production." - << " It remains here for performance comparison reasons only. \n\nDo not use this encode.\n\n" - << LOCATION << oc::Color::Default << std::endl; - } - } - }; - static Warned wardned; - - mRequestedNumOTs = numOTs; - auto mScaler = 2; - - auto code = mMultType == MultType::slv11 ? - SilverCode::Weight11 : - SilverCode::Weight5; - - gap = SilverCode::gap(code); - - mNumPartitions = getRegNoiseWeight(0.2, secParam); - mSizePer = roundUpTo((numOTs * mScaler + mNumPartitions - 1) / mNumPartitions, 8); - mN2 = mSizePer * mNumPartitions + gap; - mN = mN2 / mScaler; - - if (mN2 % mScaler) - throw RTE_LOC; - - mEncoder.mL.init(mN, code); - mEncoder.mR.init(mN, code, true); - } -#endif - - void QuasiCyclicConfigure( - u64 numOTs, u64 secParam, - u64 scaler, - MultType mMultType, - u64& mRequestedNumOTs, - u64& mNumPartitions, - u64& mSizePer, - u64& mNoiseVecSize, - u64& mN, - u64& mP, - u64& mScaler) - - { -#ifndef ENABLE_BITPOLYMUL - throw std::runtime_error("ENABLE_BITPOLYMUL not defined, rebuild the library with `-DENABLE_BITPOLYMUL=TRUE`. " LOCATION); -#endif - - mRequestedNumOTs = numOTs; - mP = nextPrime(std::max(numOTs, 128 * 128)); - mNumPartitions = getRegNoiseWeight(0.2, secParam); - auto ss = (mP * scaler + mNumPartitions - 1) / mNumPartitions; - mSizePer = roundUpTo(ss, 8); - mNoiseVecSize = mSizePer * mNumPartitions; - mN = mNoiseVecSize / scaler; - mScaler = scaler; - } - } diff --git a/libOTe/TwoChooseOne/ConfigureCode.h b/libOTe/TwoChooseOne/ConfigureCode.h index e838375..e3f0624 100644 --- a/libOTe/TwoChooseOne/ConfigureCode.h +++ b/libOTe/TwoChooseOne/ConfigureCode.h @@ -6,140 +6,155 @@ namespace osuCrypto { - enum class MultType - { - // https://eprint.iacr.org/2019/1159.pdf - QuasiCyclic = 1, - - // https://eprint.iacr.org/2022/1014 - ExAcc7 = 4, // fast - ExAcc11 = 5,// fast but more conservative - ExAcc21 = 6, - ExAcc40 = 7, // conservative - - // https://eprint.iacr.org/2023/882 - ExConv7x24 = 8, //fast - ExConv21x24 = 9, // conservative. - - // experimental - Tungsten // very fast, based on turbo codes. Unknown min distance. - }; - - inline std::ostream& operator<<(std::ostream& o, MultType m) - { - switch (m) - { - case osuCrypto::MultType::QuasiCyclic: - o << "QuasiCyclic"; - break; - - case osuCrypto::MultType::ExAcc7: - o << "ExAcc7"; - break; - case osuCrypto::MultType::ExAcc11: - o << "ExAcc11"; - break; - case osuCrypto::MultType::ExAcc21: - o << "ExAcc21"; - break; - case osuCrypto::MultType::ExAcc40: - o << "ExAcc40"; - break; - case osuCrypto::MultType::ExConv21x24: - o << "ExConv21x24"; - break; - case osuCrypto::MultType::ExConv7x24: - o << "ExConv7x24"; - break; - case osuCrypto::MultType::Tungsten: - o << "Tungsten"; - break; - default: - throw RTE_LOC; - break; - } - - return o; - } - - constexpr MultType DefaultMultType = MultType::ExConv7x24; - - // We get e^{-2td} security against linear attacks, - // with noise weigh t and minDist d. + enum class MultType + { + // https://eprint.iacr.org/2019/1159.pdf + QuasiCyclic = 1, + + // https://eprint.iacr.org/2022/1014 + ExAcc7 = 4, // fast + ExAcc11 = 5,// fast but more conservative + ExAcc21 = 6, + ExAcc40 = 7, // conservative + + // https://eprint.iacr.org/2023/882 + ExConv7x24 = 8, //fast + ExConv21x24 = 9, // conservative. + + // experimental + Tungsten // very fast, based on turbo codes. Unknown min distance. + }; + + inline std::ostream& operator<<(std::ostream& o, MultType m) + { + switch (m) + { + case osuCrypto::MultType::QuasiCyclic: + o << "QuasiCyclic"; + break; + + case osuCrypto::MultType::ExAcc7: + o << "ExAcc7"; + break; + case osuCrypto::MultType::ExAcc11: + o << "ExAcc11"; + break; + case osuCrypto::MultType::ExAcc21: + o << "ExAcc21"; + break; + case osuCrypto::MultType::ExAcc40: + o << "ExAcc40"; + break; + case osuCrypto::MultType::ExConv21x24: + o << "ExConv21x24"; + break; + case osuCrypto::MultType::ExConv7x24: + o << "ExConv7x24"; + break; + case osuCrypto::MultType::Tungsten: + o << "Tungsten"; + break; + default: + throw RTE_LOC; + break; + } + + return o; + } + + constexpr MultType DefaultMultType = MultType::ExConv7x24; + + + // We get e^{-2t d/N} security against linear attacks, + // with noise weight t and minDist d and code size N. // For regular we can be slightly more accurate with - // (1 − 2d)^t + // (1 − 2d/N)^t // which implies a bit security level of - // k = -t * log2(1 - 2d) - // t = -k / log2(1 - 2d) - u64 getRegNoiseWeight(double minDistRatio, u64 secParam); + // k = -t * log2(1 - 2d/N) + // t = -k / log2(1 - 2d/N) + // + // minDistRatio = d / N + // where d is the min dist and N is the code size. + u64 getRegNoiseWeight(double minDistRatio, u64 N, u64 secParam); class EACode; - - void EAConfigure( - u64 numOTs, u64 secParam, - MultType mMultType, - u64& mRequestedNumOTs, - u64& mNumPartitions, - u64& mSizePer, - u64& mNoiseVecSize, - u64& mN, - EACode& mEncoder - ); - - - class ExConvCode; - void ExConvConfigure( - u64 numOTs, u64 secParam, - MultType mMultType, - u64& mRequestedNumOTs, - u64& mNumPartitions, - u64& mSizePer, - u64& mNoiseVecSize, - u64& mN, - ExConvCode& mEncoder - ); - - - void ExConvConfigure( - double scaler, - MultType mMultType, - u64& expanderWeight, - u64& accumulatorWeight, - double& minDist - ); - - void QuasiCyclicConfigure( - u64 numOTs, u64 secParam, - u64 scaler, - MultType mMultType, - u64& mRequestedNumOTs, - u64& mNumPartitions, - u64& mSizePer, - u64& mNoiseVecSize, - u64& mN, - u64& mP, - u64& mScaler); - - - inline void QuasiCyclicConfigure( - double mScaler, - double& minDist) - { - if (mScaler == 2) - minDist = 0.2; // estimated psuedo min dist - else - throw RTE_LOC; // not impl - } - - - inline void TungstenConfigure( - double mScaler, - double& minDist) - { - if (mScaler == 2) - minDist = 0.2; // estimated psuedo min dist - else - throw RTE_LOC; // not impl - } + void EAConfigure( + MultType mMultType, + u64& scaler, + u64& expanderWeight, + double& minDist + ); + + void ExConvConfigure( + MultType mMultType, + u64& scaler, + u64& expanderWeight, + u64& accumulatorWeight, + double& minDist + ); + + inline void QuasiCyclicConfigure( + u64& scaler, + double& minDist + ) + { + scaler = 2; + minDist = 0.2; // estimated psuedo min dist + } + + + inline void TungstenConfigure( + u64& mScaler, + double& minDist) + { + mScaler = 2; + minDist = 0.2; // estimated psuedo min dist + + } + + inline void syndromeDecodingConfigure( + u64& mNumPartitions, u64& mSizePer, u64& mNoiseVecSize, + u64 secParam, + u64 mRequestSize, + MultType mMultType) + { + + double minDist = 0; + u64 scaler = 0; + switch (mMultType) + { + case osuCrypto::MultType::ExAcc7: + case osuCrypto::MultType::ExAcc11: + case osuCrypto::MultType::ExAcc21: + case osuCrypto::MultType::ExAcc40: + { + u64 _1; + EAConfigure(mMultType, scaler, _1, minDist); + } + case osuCrypto::MultType::ExConv7x24: + case osuCrypto::MultType::ExConv21x24: + { + u64 _1, _2; + ExConvConfigure(mMultType, scaler, _1, _2, minDist); + break; + } + case MultType::QuasiCyclic: + QuasiCyclicConfigure(scaler, minDist); + break; + case osuCrypto::MultType::Tungsten: + { + mRequestSize = roundUpTo(mRequestSize, 8); + TungstenConfigure(scaler, minDist); + break; + } + default: + throw RTE_LOC; + break; + } + + mNumPartitions = getRegNoiseWeight(minDist, mRequestSize * scaler, secParam); + mSizePer = std::max(4, roundUpTo(divCeil(mRequestSize * scaler, mNumPartitions), 2)); + mNoiseVecSize = mSizePer * mNumPartitions; + } } \ No newline at end of file diff --git a/libOTe/TwoChooseOne/Silent/SilentOtExtReceiver.cpp b/libOTe/TwoChooseOne/Silent/SilentOtExtReceiver.cpp index 9fa451c..a6fbbf7 100644 --- a/libOTe/TwoChooseOne/Silent/SilentOtExtReceiver.cpp +++ b/libOTe/TwoChooseOne/Silent/SilentOtExtReceiver.cpp @@ -215,52 +215,9 @@ namespace osuCrypto mMalType = malType; mNumThreads = numThreads; u64 secParam = 128; + mRequestNumOts = numOTs; - switch (mMultType) - { - case osuCrypto::MultType::QuasiCyclic: - - QuasiCyclicConfigure(numOTs, secParam, scaler, - mMultType, - mRequestNumOts, - mNumPartitions, - mSizePer, - mNoiseVecSize, - mN, - mP, - mScaler); - - break; - case osuCrypto::MultType::ExAcc7: - case osuCrypto::MultType::ExAcc11: - case osuCrypto::MultType::ExAcc21: - case osuCrypto::MultType::ExAcc40: - - EAConfigure(numOTs, secParam, mMultType, mRequestNumOts, mNumPartitions, mSizePer, mNoiseVecSize, mN, mEAEncoder); - break; - case osuCrypto::MultType::ExConv7x24: - case osuCrypto::MultType::ExConv21x24: - - ExConvConfigure(numOTs, secParam, mMultType, mRequestNumOts, mNumPartitions, mSizePer, mNoiseVecSize, mN, mExConvEncoder); - break; - case osuCrypto::MultType::Tungsten: - { - double minDist; - mRequestNumOts = numOTs; - mN = roundUpTo(numOTs, 8); - TungstenConfigure(mScaler, minDist); - - mNumPartitions = getRegNoiseWeight(minDist, secParam); - mSizePer = std::max(4, roundUpTo(divCeil(mRequestNumOts * mScaler, mNumPartitions), 2)); - mNoiseVecSize = mSizePer * mNumPartitions; - - break; - } - default: - throw RTE_LOC; - break; - } - + syndromeDecodingConfigure(mNumPartitions, mSizePer, mNoiseVecSize, secParam, mRequestNumOts, mMultType); mS.resize(mNumPartitions); mGen.configure(mSizePer, mS.size()); @@ -433,7 +390,7 @@ namespace osuCrypto if (isConfigured() == false) { // first generate 128 normal base OTs - configure(n, mScaler, mNumThreads, mMalType); + configure(n, 2, mNumThreads, mMalType); } if (n != mRequestNumOts) @@ -651,41 +608,49 @@ namespace osuCrypto { #ifdef ENABLE_BITPOLYMUL QuasiCyclicCode code; - code.init(mP, mScaler); - code.dualEncode(mA.subspan(0, code.size())); + u64 scaler; + double _; + QuasiCyclicConfigure(scaler, _); + code.init2(mRequestNumOts, mNoiseVecSize); + code.dualEncode(mA); #else throw std::runtime_error("ENABLE_BITPOLYMUL not defined."); #endif } break; -#ifdef ENABLE_INSECURE_SILVER - case osuCrypto::MultType::slv5: - case osuCrypto::MultType::slv11: - - if (mTimer) - mEncoder.setTimer(getTimer()); - mEncoder.dualEncode(mA); - break; -#endif case osuCrypto::MultType::ExAcc7: case osuCrypto::MultType::ExAcc11: case osuCrypto::MultType::ExAcc21: case osuCrypto::MultType::ExAcc40: { + EACode mEAEncoder; + u64 expanderWeight = 0, _1; + double _2; + EAConfigure(mMultType, _1, expanderWeight, _2); + mEAEncoder.config(mRequestNumOts, mNoiseVecSize, expanderWeight); AlignedUnVector A2(mEAEncoder.mMessageSize); - mEAEncoder.dualEncode(mA.subspan(0, mEAEncoder.mCodeSize), A2, {}); + mEAEncoder.dualEncode(mA, A2, {}); std::swap(mA, A2); break; } case osuCrypto::MultType::ExConv7x24: case osuCrypto::MultType::ExConv21x24: - if (mTimer) - mExConvEncoder.setTimer(getTimer()); - mExConvEncoder.dualEncode(mA.begin(), {}); + { + + u64 expanderWeight = 0, accWeight = 0, _1; + double _2; + ExConvConfigure(mMultType, _1, expanderWeight, accWeight, _2); + + ExConvCode exConvEncoder; + exConvEncoder.config(mRequestNumOts, mNoiseVecSize, expanderWeight, accWeight); + exConvEncoder.dualEncode(mA.begin(), {}); break; + } case osuCrypto::MultType::Tungsten: { + experimental::TungstenCode encoder; + encoder.config(oc::roundUpTo(mRequestNumOts, 8), mNoiseVecSize); encoder.dualEncode(mA.begin(), {}); break; } @@ -712,49 +677,62 @@ namespace osuCrypto { #ifdef ENABLE_BITPOLYMUL QuasiCyclicCode code; - code.init(mP, mScaler); - code.dualEncode(mA.subspan(0, code.size())); - code.dualEncode(mC.subspan(0, code.size())); + u64 scaler; + double _; + QuasiCyclicConfigure(scaler, _); + code.init2(mRequestNumOts, mNoiseVecSize); + + code.dualEncode(mA); + code.dualEncode(mC); #else throw std::runtime_error("ENABLE_BITPOLYMUL not defined."); #endif } break; -#ifdef ENABLE_INSECURE_SILVER - case osuCrypto::MultType::slv5: - case osuCrypto::MultType::slv11: - mEncoder.dualEncode2(mA, mC); - break; -#endif case osuCrypto::MultType::ExAcc7: case osuCrypto::MultType::ExAcc11: case osuCrypto::MultType::ExAcc21: case osuCrypto::MultType::ExAcc40: { + EACode mEAEncoder; + u64 expanderWeight = 0, _1; + double _2; + EAConfigure(mMultType, _1, expanderWeight, _2); + mEAEncoder.config(mRequestNumOts, mNoiseVecSize, expanderWeight); + AlignedUnVector A2(mEAEncoder.mMessageSize); AlignedUnVector C2(mEAEncoder.mMessageSize); mEAEncoder.dualEncode2( - mA.subspan(0, mEAEncoder.mCodeSize), A2, - mC.subspan(0, mEAEncoder.mCodeSize), C2, + mA, A2, + mC, C2, {}); std::swap(mA, A2); std::swap(mC, C2); + break; } - case osuCrypto::MultType::ExConv7x24: case osuCrypto::MultType::ExConv21x24: - if (mTimer) - mExConvEncoder.setTimer(getTimer()); - mExConvEncoder.dualEncode2( + { + u64 expanderWeight = 0, accWeight = 0, _1; + double _2; + ExConvConfigure(mMultType, _1, expanderWeight, accWeight, _2); + + ExConvCode exConvEncoder; + exConvEncoder.config(mRequestNumOts, mNoiseVecSize, expanderWeight, accWeight); + + exConvEncoder.dualEncode2( mA.begin(), - mC.begin(), + mC.begin(), {}); + break; + } case osuCrypto::MultType::Tungsten: { experimental::TungstenCode encoder; + encoder.config(roundUpTo(mRequestNumOts, 8), mNoiseVecSize); encoder.dualEncode(mA.begin(), {}); encoder.dualEncode(mC.begin(), {}); break; @@ -763,14 +741,13 @@ namespace osuCrypto throw RTE_LOC; break; } - + setTimePoint("recver.expand.ldpc.dualEncode"); } } void SilentOtExtReceiver::clear() { - mN = 0; mNoiseVecSize = 0; mRequestNumOts = 0; mSizePer = 0; diff --git a/libOTe/TwoChooseOne/Silent/SilentOtExtReceiver.h b/libOTe/TwoChooseOne/Silent/SilentOtExtReceiver.h index 12ed591..a4c50a4 100644 --- a/libOTe/TwoChooseOne/Silent/SilentOtExtReceiver.h +++ b/libOTe/TwoChooseOne/Silent/SilentOtExtReceiver.h @@ -33,21 +33,12 @@ namespace osuCrypto class SilentOtExtReceiver : public OtExtReceiver, public TimerAdapter { public: - // The prime for QuasiCycic encoding - u64 mP = 0; - // the number of OTs being requested. u64 mRequestNumOts = 0; - // The dense vector size, this will be at least as big as mRequestNumOts. - u64 mN = 0; - // The sparse vector size, this will be mN * mScaler. u64 mNoiseVecSize = 0; - // The scaling factor that the sparse vector will be compressed by. - u64 mScaler = 2; - // The size of each regular section of the sparse vector. u64 mSizePer = 0; @@ -100,13 +91,6 @@ namespace osuCrypto // The flag which controls whether the malicious check is performed. SilentSecType mMalType = SilentSecType::SemiHonest; - // The Silver encoder for MultType::slv5, MultType::slv11 -#ifdef ENABLE_INSECURE_SILVER - SilverEncoder mEncoder; -#endif - ExConvCode mExConvEncoder; - EACode mEAEncoder; - // A flag that helps debug bool mDebug = false; @@ -172,7 +156,7 @@ namespace osuCrypto SilentSecType mal = SilentSecType::SemiHonest); // return true if this instance has been configured. - bool isConfigured() const { return mN > 0; } + bool isConfigured() const { return mRequestNumOts > 0; } // Returns how many base OTs the silent OT extension // protocol will needs. diff --git a/libOTe/TwoChooseOne/Silent/SilentOtExtSender.cpp b/libOTe/TwoChooseOne/Silent/SilentOtExtSender.cpp index 09a3417..df84c5e 100644 --- a/libOTe/TwoChooseOne/Silent/SilentOtExtSender.cpp +++ b/libOTe/TwoChooseOne/Silent/SilentOtExtSender.cpp @@ -165,52 +165,10 @@ namespace osuCrypto mMalType = malType; mNumThreads = numThreads; u64 secParam = 128; + mRequestNumOts = numOTs;; + syndromeDecodingConfigure(mNumPartitions, mSizePer, mNoiseVecSize, secParam, mRequestNumOts, mMultType); - switch (mMultType) - { - case osuCrypto::MultType::QuasiCyclic: - - QuasiCyclicConfigure(numOTs, secParam, scaler, - mMultType, - mRequestNumOts, - mNumPartitions, - mSizePer, - mNoiseVecSize, - mN, - mP, - mScaler); - - break; - case osuCrypto::MultType::ExAcc7: - case osuCrypto::MultType::ExAcc11: - case osuCrypto::MultType::ExAcc21: - case osuCrypto::MultType::ExAcc40: - - EAConfigure(numOTs, secParam, mMultType, mRequestNumOts, mNumPartitions, mSizePer, mNoiseVecSize, mN, mEAEncoder); - break; - case osuCrypto::MultType::ExConv7x24: - case osuCrypto::MultType::ExConv21x24: - - ExConvConfigure(numOTs, secParam, mMultType, mRequestNumOts, mNumPartitions, mSizePer, mNoiseVecSize, mN, mExConvEncoder); - break; - case osuCrypto::MultType::Tungsten: - { - double minDist; - mRequestNumOts = numOTs; - mN = roundUpTo(numOTs, 8); - TungstenConfigure(mScaler, minDist); - - mNumPartitions = getRegNoiseWeight(minDist, secParam); - mSizePer = std::max(4, roundUpTo(divCeil(mRequestNumOts * mScaler, mNumPartitions), 2)); - mNoiseVecSize = mSizePer * mNumPartitions; - - break; - } - default: - throw RTE_LOC; - break; - } mGen.configure(mSizePer, mNumPartitions); } @@ -228,12 +186,10 @@ namespace osuCrypto void SilentOtExtSender::clear() { - mN = 0; mNoiseVecSize = 0; mRequestNumOts = 0; mSizePer = 0; mNumPartitions = 0; - mP = 0; mB = {}; @@ -389,7 +345,7 @@ namespace osuCrypto if (isConfigured() == false) { - configure(n, mScaler, mNumThreads, mMalType); + configure(n, 2, mNumThreads, mMalType); } if (n != mRequestNumOts) @@ -485,7 +441,7 @@ namespace osuCrypto #ifdef ENABLE_BITPOLYMUL QuasiCyclicCode code; - code.init(mP, mScaler); + code.init2(mRequestNumOts, mNoiseVecSize); code.dualEncode(mB.subspan(0, code.size())); #else throw std::runtime_error("ENABLE_BITPOLYMUL"); @@ -497,22 +453,35 @@ namespace osuCrypto case osuCrypto::MultType::ExAcc21: case osuCrypto::MultType::ExAcc40: { - if (mTimer) - mEAEncoder.setTimer(getTimer()); - AlignedUnVector B2(mEAEncoder.mMessageSize); - mEAEncoder.dualEncode(mB.subspan(0, mEAEncoder.mCodeSize), B2, {}); + EACode encoder; + u64 expanderWeight = 0, _1; + double _2; + EAConfigure(mMultType, _1, expanderWeight, _2); + encoder.config(mRequestNumOts, mNoiseVecSize, expanderWeight); + + AlignedUnVector B2(encoder.mMessageSize); + encoder.dualEncode(mB, B2, {}); std::swap(mB, B2); break; } case osuCrypto::MultType::ExConv7x24: case osuCrypto::MultType::ExConv21x24: - if (mTimer) - mExConvEncoder.setTimer(getTimer()); - mExConvEncoder.dualEncode(mB.begin(), {}); + { + + u64 expanderWeight = 0, accWeight = 0, _1; + double _2; + ExConvConfigure(mMultType, _1, expanderWeight, accWeight, _2); + + ExConvCode exConvEncoder; + exConvEncoder.config(mRequestNumOts, mNoiseVecSize, expanderWeight, accWeight); + + exConvEncoder.dualEncode(mB.begin(), {}); break; + } case osuCrypto::MultType::Tungsten: { experimental::TungstenCode encoder; + encoder.config(oc::roundUpTo(mRequestNumOts, 8), mNoiseVecSize); encoder.dualEncode(mB.begin(), {}); break; } diff --git a/libOTe/TwoChooseOne/Silent/SilentOtExtSender.h b/libOTe/TwoChooseOne/Silent/SilentOtExtSender.h index 1c81376..1a61d2d 100644 --- a/libOTe/TwoChooseOne/Silent/SilentOtExtSender.h +++ b/libOTe/TwoChooseOne/Silent/SilentOtExtSender.h @@ -77,24 +77,15 @@ namespace osuCrypto // the number of OTs being requested. u64 mRequestNumOts = 0; - // The prime for QuasiCycic encoding - u64 mP = 0; - // The sparse vector size, this will be mN * mScaler. u64 mNoiseVecSize = 0; - // The dense vector size, this will be at least as big as mRequestNumOts. - u64 mN = 0; - // The number of regular section of the sparse vector. u64 mNumPartitions = 0; // The size of each regular section of the sparse vector. u64 mSizePer = 0; - // The scaling factor that the sparse vector will be compressed by. - u64 mScaler = 2; - // The B vector in the relation A + B = C * delta AlignedUnVector mB; @@ -119,9 +110,6 @@ namespace osuCrypto // The flag which controls whether the malicious check is performed. SilentSecType mMalType = SilentSecType::SemiHonest; - ExConvCode mExConvEncoder; - EACode mEAEncoder; - // The OTs send msgs which will be used to create the // secret share of xa * delta as described in ferret. std::vector> mMalCheckOts; @@ -129,7 +117,6 @@ namespace osuCrypto // A flag that helps debug bool mDebug = false; - virtual ~SilentOtExtSender() = default; ///////////////////////////////////////////////////// @@ -192,7 +179,7 @@ namespace osuCrypto SilentSecType malType = SilentSecType::SemiHonest); // return true if this instance has been configured. - bool isConfigured() const { return mN > 0; } + bool isConfigured() const { return mRequestNumOts > 0; } // Returns how many base OTs the silent OT extension // protocol will needs. diff --git a/libOTe/Vole/Silent/SilentVoleReceiver.h b/libOTe/Vole/Silent/SilentVoleReceiver.h index 6755c9d..eafd389 100644 --- a/libOTe/Vole/Silent/SilentVoleReceiver.h +++ b/libOTe/Vole/Silent/SilentVoleReceiver.h @@ -283,33 +283,10 @@ namespace osuCrypto mRequestSize = requestSize; mState = State::Configured; mBaseType = type; - double minDist = 0; - switch (mMultType) - { - case osuCrypto::MultType::ExConv7x24: - case osuCrypto::MultType::ExConv21x24: - { - u64 _1, _2; - ExConvConfigure(mScaler, mMultType, _1, _2, minDist); - break; - } - case MultType::QuasiCyclic: - QuasiCyclicConfigure(mScaler, minDist); - break; - case osuCrypto::MultType::Tungsten: - { - mRequestSize = roundUpTo(mRequestSize, 8); - TungstenConfigure(mScaler, minDist); - break; - } - default: - throw RTE_LOC; - break; - } - mNumPartitions = getRegNoiseWeight(minDist, secParam); - mSizePer = std::max(4, roundUpTo(divCeil(mRequestSize * mScaler, mNumPartitions), 2)); - mNoiseVecSize = mSizePer * mNumPartitions; + + syndromeDecodingConfigure(mNumPartitions, mSizePer, mNoiseVecSize, mSecParam, mRequestSize, mMultType); + mGen.configure(mSizePer, mNumPartitions); } @@ -555,13 +532,11 @@ namespace osuCrypto case osuCrypto::MultType::ExConv7x24: case osuCrypto::MultType::ExConv21x24: { - u64 expanderWeight, accumulatorWeight; + u64 expanderWeight, accumulatorWeight, scaler; double _; - ExConvConfigure(mScaler, mMultType, expanderWeight, accumulatorWeight, _); + ExConvConfigure(mMultType, scaler, expanderWeight, accumulatorWeight, _); ExConvCode encoder; - if (mScaler * mRequestSize > mNoiseVecSize) - throw RTE_LOC; - encoder.config(mRequestSize, mScaler * mRequestSize, expanderWeight, accumulatorWeight); + encoder.config(mRequestSize, mNoiseVecSize, expanderWeight, accumulatorWeight); if (mTimer) encoder.setTimer(getTimer()); @@ -596,7 +571,7 @@ namespace osuCrypto case osuCrypto::MultType::Tungsten: { experimental::TungstenCode encoder; - encoder.config(mRequestSize, mNoiseVecSize); + encoder.config(oc::roundUpTo(mRequestSize, 8), mNoiseVecSize); encoder.dualEncode(mA.begin(), mCtx); encoder.dualEncode(mC.begin(), mCtx); break; diff --git a/libOTe/Vole/Silent/SilentVoleSender.h b/libOTe/Vole/Silent/SilentVoleSender.h index 74e8309..2ad7ab5 100644 --- a/libOTe/Vole/Silent/SilentVoleSender.h +++ b/libOTe/Vole/Silent/SilentVoleSender.h @@ -228,37 +228,13 @@ namespace osuCrypto mRequestSize = requestSize; mState = State::Configured; mBaseType = type; - double minDist = 0; - switch (mMultType) - { - case osuCrypto::MultType::ExConv7x24: - case osuCrypto::MultType::ExConv21x24: - { - u64 _1, _2; - ExConvConfigure(mScaler, mMultType, _1, _2, minDist); - break; - } - case MultType::QuasiCyclic: - QuasiCyclicConfigure(mScaler, minDist); - break; - case osuCrypto::MultType::Tungsten: - { - mRequestSize = roundUpTo(mRequestSize, 8); - TungstenConfigure(mScaler, minDist); - break; - } - default: - throw RTE_LOC; - break; - } - - mNumPartitions = getRegNoiseWeight(minDist, secParam); - mSizePer = std::max(4, roundUpTo(divCeil(mRequestSize * mScaler, mNumPartitions), 2)); - mNoiseVecSize = mSizePer * mNumPartitions; + syndromeDecodingConfigure( + mNumPartitions, mSizePer, mNoiseVecSize, + mSecParam, mRequestSize, mMultType); mGen.configure(mSizePer, mNumPartitions); - } + } // return true if this instance has been configured. bool isConfigured() const { return mState != State::Default; } @@ -408,12 +384,10 @@ namespace osuCrypto case osuCrypto::MultType::ExConv21x24: { ExConvCode encoder; - u64 expanderWeight, accumulatorWeight; + u64 expanderWeight, accumulatorWeight, scaler; double _1; - ExConvConfigure(mScaler, mMultType, expanderWeight, accumulatorWeight, _1); - if (mScaler * mRequestSize > mNoiseVecSize) - throw RTE_LOC; - encoder.config(mRequestSize, mScaler * mRequestSize, expanderWeight, accumulatorWeight); + ExConvConfigure(mMultType, scaler, expanderWeight, accumulatorWeight, _1); + encoder.config(mRequestSize, mNoiseVecSize, expanderWeight, accumulatorWeight); if (mTimer) encoder.setTimer(getTimer()); encoder.dualEncode(mB.begin(), mCtx); @@ -442,7 +416,7 @@ namespace osuCrypto case osuCrypto::MultType::Tungsten: { experimental::TungstenCode encoder; - encoder.config(mRequestSize, mNoiseVecSize); + encoder.config(oc::roundUpTo(mRequestSize, 8), mNoiseVecSize); encoder.dualEncode(mB.begin(), mCtx); break; } diff --git a/libOTe_Tests/EACode_Tests.cpp b/libOTe_Tests/EACode_Tests.cpp index 6347d4d..a66a42c 100644 --- a/libOTe_Tests/EACode_Tests.cpp +++ b/libOTe_Tests/EACode_Tests.cpp @@ -2,6 +2,8 @@ #include "libOTe/Tools/EACode/EACode.h" #include #include "libOTe/Tools/CoeffCtx.h" +#include "libOTe_Tests/ExConvCode_Tests.h" +#include "libOTe/Tools/ExConvCode/ExConvChecker.h" namespace osuCrypto { @@ -84,4 +86,30 @@ namespace osuCrypto } + + void EACode_weight_test(const oc::CLP& cmd) + { + u64 k = cmd.getOr("k", 1ull << cmd.getOr("kk", 6)); + u64 n = k * 2; + u64 bw = cmd.getOr("bw", 21); + bool verbose = cmd.isSet("v"); + + EACode encoder; + encoder.config(k, n, bw); + auto threshold = n / 4 - 2 * std::sqrt(n); + u64 min = 0; + //if (cmd.isSet("x2")) + // min = getGeneratorWeightx2(encoder, verbose); + //else + min = getGeneratorWeight(encoder, verbose); + + if(verbose) + std::cout << min << " / " << n << " = " << double(min) / n << std::endl; + + if (min < threshold) + { + throw RTE_LOC; + } + } + } \ No newline at end of file diff --git a/libOTe_Tests/EACode_Tests.h b/libOTe_Tests/EACode_Tests.h index 95b347b..dbc9234 100644 --- a/libOTe_Tests/EACode_Tests.h +++ b/libOTe_Tests/EACode_Tests.h @@ -7,5 +7,6 @@ namespace osuCrypto void EACode_encode_basic_test(const oc::CLP& cmd); + void EACode_weight_test(const oc::CLP& cmd); } \ No newline at end of file diff --git a/libOTe_Tests/ExConvCode_Tests.cpp b/libOTe_Tests/ExConvCode_Tests.cpp index 49be53e..224c87f 100644 --- a/libOTe_Tests/ExConvCode_Tests.cpp +++ b/libOTe_Tests/ExConvCode_Tests.cpp @@ -1,13 +1,13 @@ #include "ExConvCode_Tests.h" #include "libOTe/Tools/ExConvCode/ExConvCode.h" -#include "libOTe/Tools/ExConvCode/ExConvCode.h" #include #include "libOTe/Tools/CoeffCtx.h" +#include "libOTe/Tools/ExConvCode/ExConvChecker.h" namespace osuCrypto { - std::ostream& operator<<(std::ostream& o, const std::array&a) + std::ostream& operator<<(std::ostream& o, const std::array& a) { o << "{" << a[0] << " " << a[1] << " " << a[2] << "}"; return o; @@ -62,56 +62,61 @@ namespace osuCrypto } CoeffCtx ctx; std::vector rand(divCeil(aw, 8)); - for (i64 i = 0; i < i64(x1.size() - aw - 1); ++i) + for (u64 i = 0; i < n; ++i) { prng.get(rand.data(), rand.size()); - code.accOneGen(x1.data() + i, x1.data()+n, rand.data(), ctx); + code.accOneGen(x1.data(), i, n, rand.data(), ctx); - if (aw == 16) - code.accOne(x2.data() + i, x2.data()+n, rand.data(), ctx); + if (aw == 24) + code.accOne(x2.data(), i, n, rand.data(), ctx); + u64 j = i + 1; - ctx.plus(x3[i + 1], x3[i + 1], x3[i]); - //std::cout << "x" << i + 1 << " " << x3[i + 1] << " -> "; - ctx.mulConst(x3[i + 1], x3[i + 1]); - //std::cout << x3[i + 1] << std::endl;; assert(aw <= 64); u64 bits = 0; memcpy(&bits, rand.data(), std::min(rand.size(), 8)); - for (u64 j = 0; j < aw && (i + j + 2) < x3.size(); ++j) + for (u64 a = 0; a < aw; ++a, ++j) { if (bits & 1) { - ctx.plus(x3[i + j + 2], x3[i + j + 2], x3[i]); + ctx.plus(x3[j % n], x3[j % n], x3[i]); } bits >>= 1; } + ctx.plus(x3[j % n], x3[j % n], x3[i]); + ctx.mulConst(x3[j % n], x3[j % n]); - for (u64 j = i; j < x1.size() && j < i + aw + 2; ++j) + j = i + 1; + for (u64 a = 0; a <= aw; ++a, ++j) { - if (aw == 16 && x1[j] != x2[j]) + //auto j = (i + a + 2) % n; + + if (aw == 24 && x1[j%n] != x2[j % n]) { - std::cout << j << " " << ctx.str(x1[j]) << " " << ctx.str(x2[j]) << std::endl; + std::cout << j % n << " " << ctx.str(x1[j % n]) << " " << ctx.str(x2[j % n]) << std::endl; throw RTE_LOC; } - if (x1[j] != x3[j]) + if (x1[j % n] != x3[j % n]) { - std::cout << j << " " << ctx.str(x1[j]) << " " << ctx.str(x3[j]) << std::endl; + std::cout << j % n << " " << ctx.str(x1[j % n]) << " " << ctx.str(x3[j % n]) << std::endl; throw RTE_LOC; } } } - x4 = x1; - //std::cout << std::endl; - - code.accumulateFixed(x1.data() + accOffset, ctx); + u64 size = n - accOffset; - if (aw == 16) + code.accumulateFixed(x1.data() + accOffset, size, ctx, code.mSeed); + if (code.mAccTwice) + code.accumulateFixed(x1.data() + accOffset, size, ctx, ~code.mSeed); + if (aw == 24) { - code.accumulateFixed(x2.data() + accOffset, ctx); + code.accumulateFixed(x2.data() + accOffset, size, ctx, code.mSeed); + + if (code.mAccTwice) + code.accumulateFixed(x2.data() + accOffset, size, ctx, ~code.mSeed); if (x1 != x2) { @@ -124,43 +129,52 @@ namespace osuCrypto } { - PRNG coeffGen(code.mSeed ^ OneBlock); - u8* mtxCoeffIter = (u8*)coeffGen.mBuffer.data(); - auto mtxCoeffEnd = mtxCoeffIter + coeffGen.mBuffer.size() * sizeof(block) - divCeil(aw, 8); - - auto xi = x3.data() + accOffset; - auto end = x3.data() + n; - while (xi < end) + for (auto r = 0; r < 1 + code.mAccTwice; ++r) { - if (mtxCoeffIter > mtxCoeffEnd) - { - // generate more mtx coefficients - ExConvCode::refill(coeffGen); - mtxCoeffIter = (u8*)coeffGen.mBuffer.data(); - } - - // add xi to the next positions - auto xj = xi + 1; - if (xj != end) - { - ctx.plus(*xj, *xj, *xi); - ctx.mulConst(*xj, *xj); - ++xj; - } - //assert((mtxCoeffEnd - mtxCoeffIter) * 8 >= aw); - u64 bits = 0; - memcpy(&bits, mtxCoeffIter, divCeil(aw,8)); - for (u64 j = 0; j < aw && xj != end; ++j, ++xj) + PRNG coeffGen(r ? ~code.mSeed : code.mSeed); + u8* mtxCoeffIter = (u8*)coeffGen.mBuffer.data(); + auto mtxCoeffEnd = mtxCoeffIter + coeffGen.mBuffer.size() * sizeof(block) - divCeil(aw, 8); + + auto x = x3.data() + accOffset; + u64 i = 0; + while (i < size) { - if (bits &1) + auto xi = x + i; + + if (mtxCoeffIter > mtxCoeffEnd) + { + // generate more mtx coefficients + ExConvCode::refill(coeffGen); + mtxCoeffIter = (u8*)coeffGen.mBuffer.data(); + } + + // add xi to the next positions + auto j = (i + 1) % size; + + u64 bits = 0; + memcpy(&bits, mtxCoeffIter, divCeil(aw, 8)); + for (u64 a = 0; a < aw; ++a) + { + + if (bits & 1) + { + auto xj = x + j; + ctx.plus(*xj, *xj, *xi); + } + bits >>= 1; + j = (j + 1) % size; + } + { + auto xj = x + j; ctx.plus(*xj, *xj, *xi); + ctx.mulConst(*xj, *xj); } - bits >>= 1; - } - ++mtxCoeffIter; + + ++mtxCoeffIter; - ++xi; + ++i; + } } } @@ -174,7 +188,6 @@ namespace osuCrypto } - detail::ExpanderModd expanderCoeff(code.mExpander.mSeed, code.mExpander.mCodeSize); std::vector y1(k), y2(k); if (sys) @@ -193,15 +206,38 @@ namespace osuCrypto code.mExpander.expand(x1.data() + accOffset, y1.data()); } + u64 step, exSize, regCount = 0;; + if (code.mExpander.mRegular) + { + regCount = divCeil(code.mExpander.mExpanderWeight, 2); + exSize = step = code.mExpander.mCodeSize / regCount; + } + else + { + step = 0; + exSize = n; + } + detail::ExpanderModd regExp(code.mExpander.mSeed^ block(342342134, 23421341), exSize); + detail::ExpanderModd fullExp(code.mExpander.mSeed, code.mExpander.mCodeSize); + u64 i = 0; auto main = k / 8 * 8; for (; i < main; i += 8) { - for (u64 j = 0; j < code.mExpander.mExpanderWeight; ++j) + + for (u64 j = 0; j < regCount; ++j) { for (u64 p = 0; p < 8; ++p) { - auto idx = expanderCoeff.get(); + auto idx = regExp.get() + step * j; + ctx.plus(y2[i + p], y2[i + p], x1[idx + accOffset]); + } + } + for (u64 j = 0; j < code.mExpander.mExpanderWeight - regCount; ++j) + { + for (u64 p = 0; p < 8; ++p) + { + auto idx = fullExp.get(); ctx.plus(y2[i + p], y2[i + p], x1[idx + accOffset]); } } @@ -209,9 +245,14 @@ namespace osuCrypto for (; i < k; ++i) { - for (u64 j = 0; j < code.mExpander.mExpanderWeight; ++j) + for (u64 j = 0; j < regCount; ++j) + { + auto idx = regExp.get() + step * j; + ctx.plus(y2[i], y2[i], x1[idx + accOffset]); + } + for (u64 j = 0; j < code.mExpander.mExpanderWeight - regCount; ++j) { - auto idx = expanderCoeff.get(); + auto idx = fullExp.get(); ctx.plus(y2[i], y2[i], x1[idx + accOffset]); } } @@ -245,8 +286,8 @@ namespace osuCrypto // //return _mm_slli_si128(x, 8); // } // //TEMP[i] : = (TEMP1[0] and TEMP2[i]) - // // FOR j : = 1 to i - // // TEMP[i] : = TEMP[i] XOR(TEMP1[j] AND TEMP2[i - j]) + // // FOR a : = 1 to i + // // TEMP[i] : = TEMP[i] XOR(TEMP1[a] AND TEMP2[i - a]) // // ENDFOR // //dst[i] : = TEMP[i] //} @@ -270,4 +311,183 @@ namespace osuCrypto } } + + + Matrix getAccumulator(ExConvCode& encoder) + { + auto k = encoder.mMessageSize;; + auto n = encoder.mCodeSize;; + if (encoder.mSystematic == false) + throw RTE_LOC;//not impl + + auto d = n - k; + Matrix g(d, d); + for (u64 i = 0; i < d; ++i) + { + std::vector x(d); + x[i] = 1; + CoeffCtxGF2 ctx; + encoder.accumulate(x.data(), ctx); + + for (u64 j = 0; j < d; ++j) + { + g(j, i) = x[j]; + } + } + return g; + } + + + u64 getGeneratorWeight_(ExConvCode& encoder, bool verbose) + { + auto k = encoder.mMessageSize; + auto n = encoder.mCodeSize; + auto g = getGenerator(encoder); + //bool failed = false; + u64 min = n; + u64 iMin = 0;; + for (u64 i = 0; i < k; ++i) + { + u64 weight = 0; + for (u64 j = 0; j < n; ++j) + { + //if (verbose) + //{ + // if (g(i, j)) + // std::cout << Color::Green << "1" << Color::Default; + // else + // std::cout << "0"; + //} + assert(g(i, j) < 2); + weight += g(i, j); + } + //if (verbose) + // std::cout << std::endl; + + if (weight < min) + iMin = i; + min = std::min(min, weight); + } + + if (verbose) + { + auto Ex = encoder.mExpander.getMatrix(); + //for (u64 i = 0; i < Ex.cols(); ++i) + //{ + // std::cout << Ex(985, i) << " "; + + //} + //std::cout << " ~ " << k << std::endl; + + std::cout << "i " << iMin << " " << min << " / " << n << " = " << double(min) / n << std::endl; + for (u64 j = 0; j < n; ++j) + { + auto ei = Ex[iMin]; + bool found = std::find(ei.begin(), ei.end(), j - k) != ei.end(); + if (j == iMin + k) + { + std::cout << Color::Blue << int(g(iMin, j)) << Color::Default; + + } + else if (found) + { + std::cout << Color::Red << int(g(iMin, j)) << Color::Default; + + } + else if (g(iMin, j)) + std::cout << Color::Green << "1" << Color::Default; + else + std::cout << "0"; + + if (j == k - 1) + { + std::cout << "\n"; + } + } + std::cout << std::endl << "--------------------------------\n"; + + auto a = getAccumulator(encoder); + + auto ei = Ex[iMin]; + for (auto i : ei) + { + for (u64 j = 0; j < k; ++j) + { + if (a(i, j)) + std::cout << Color::Green << "1" << Color::Default; + else + std::cout << "0"; + } + std::cout << std::endl; + } + } + + return min; + } + + + void ExConvCode_weight_test(const oc::CLP& cmd) + { + u64 k = cmd.getOr("k", 1ull << cmd.getOr("kk", 6)); + u64 n = k * 2; + //u64 aw = cmd.getOr("aw", 24); + //u64 bw = cmd.getOr("bw", 7); + bool verbose = cmd.isSet("v"); + bool accTwice = cmd.getOr("accTwice", 1); + for (u64 aw = 4; aw < 16; aw += 2) + { + for (u64 bw = 3; bw < 11; bw += 2) + { + + ExConvCode encoder; + encoder.config(k, n, bw, aw); + encoder.mAccTwice = accTwice; + + auto threshold = n / 6 - 2 * std::sqrt(n); + u64 min = 0; + //if (cmd.isSet("x2")) + // min = getGeneratorWeightx2(encoder, verbose); + //else + min = getGeneratorWeight_(encoder, verbose); + + if (cmd.isSet("acc")) + { + auto g = getAccumulator(encoder); + + for (u64 i = 0; i < k; ++i) + { + u64 w = 0; + for (u64 j = 0; j < k; ++j) + { + w += g(i, j); + } + //if (w < k / 2.2) + { + //std::cout << i << " " << w << std::endl; + for (u64 j = 0; j < k; ++j) + { + if (g(i, j)) + std::cout << Color::Green << "1" << Color::Default; + else + std::cout << "0"; + } + std::cout << std::endl; + } + } + std::cout << std::endl; + } + + if (verbose) + std::cout << "aw " << aw << " bw " << bw << ": " << min << " / " << n << " = " << double(min) / n << " < threshold " << double(threshold) / n << std::endl; + + if (min < threshold) + { + throw RTE_LOC; + } + + } + } + + } + } \ No newline at end of file diff --git a/libOTe_Tests/ExConvCode_Tests.h b/libOTe_Tests/ExConvCode_Tests.h index 16b530b..d10c96b 100644 --- a/libOTe_Tests/ExConvCode_Tests.h +++ b/libOTe_Tests/ExConvCode_Tests.h @@ -1,11 +1,17 @@ #include "cryptoTools/Common/CLP.h" - +#include +#include "cryptoTools/Common/Matrix.h" +#include "libOTe/Tools/CoeffCtx.h" namespace osuCrypto { - void ExConvCode_encode_basic_test(const oc::CLP& cmd); + + void ExConvCode_encode_basic_test(const oc::CLP& cmd); + + void ExConvCode_weight_test(const oc::CLP& cmd); + } \ No newline at end of file diff --git a/libOTe_Tests/SilentOT_Tests.cpp b/libOTe_Tests/SilentOT_Tests.cpp index d1a9d8c..2bd8dce 100644 --- a/libOTe_Tests/SilentOT_Tests.cpp +++ b/libOTe_Tests/SilentOT_Tests.cpp @@ -183,24 +183,15 @@ void Tools_quasiCyclic_test(const oc::CLP& cmd) QuasiCyclicCode code; - u64 nn = 1 << 10; + u64 k = 1 << 10; u64 t = 1; auto scaler = 2; - //auto secParam = 128; - - auto mP = nextPrime(nn); - auto n = mP * scaler; - //auto mNumPartitions = getPartitions(scaler, mP, secParam); - //auto ss = (mP * scaler + mNumPartitions - 1) / mNumPartitions; - //mSizePer = roundUpTo(ss, 8); - //mNoiseVecSize = mSizePer * mNumPartitions; - //mN = mNoiseVecSize / scaler; - //mScaler = scaler; + auto n = k * scaler; AlignedUnVector A(n), B(n), C(n); PRNG prng(oc::ZeroBlock); - code.init(mP); + code.init2(k, n); for (auto tt : rng(t)) { @@ -218,7 +209,7 @@ void Tools_quasiCyclic_test(const oc::CLP& cmd) code.dualEncode(B); code.dualEncode(C); - for (u64 i : rng(mP)) + for (u64 i : rng(k)) { if (C[i] != (A[i] ^ B[i])) throw RTE_LOC; @@ -239,7 +230,7 @@ void Tools_quasiCyclic_test(const oc::CLP& cmd) code.dualEncode(A); - for (u64 i : rng(mP)) + for (u64 i : rng(k)) { if (A[i] != oc::AllOneBlock && A[i] != oc::ZeroBlock) @@ -254,9 +245,7 @@ void Tools_quasiCyclic_test(const oc::CLP& cmd) { - mP = nextPrime(50); - n = mP * scaler; - code.init(mP); + code.init2(k,n); auto mtx = code.getMatrix(); A.resize(n); auto bb = 10; @@ -273,7 +262,7 @@ void Tools_quasiCyclic_test(const oc::CLP& cmd) code.dualEncode(A); auto A2 = AA * mtx; - for (auto i : rng(mP)) + for (auto i : rng(k)) { for (u64 j : rng(bb)) if (A2(j, i) != *BitIterator((u8*)&A[i], j)) @@ -333,6 +322,9 @@ namespace { throw RTE_LOC; bool passed = true; + auto hamming = choice.hammingWeight(); + if(hamming < n / 2 - std::sqrt(n)) + throw RTE_LOC; for (u64 i = 0; i < n; ++i) { block m1 = messages[i]; @@ -387,6 +379,7 @@ namespace { //bool first = true; block mask = AllOneBlock ^ OneBlock; + u64 hamming = 0; for (u64 i = 0; i < n; ++i) { @@ -415,6 +408,8 @@ namespace { c = choice[i]; } + hamming += c; + std::array eqq{ eq(m1, m2a), eq(m1, m2b) @@ -448,6 +443,9 @@ namespace { if (passed == false) throw RTE_LOC; + + if (n > 100 && hamming < n / 2 - std::sqrt(n)) + throw RTE_LOC; } #endif diff --git a/libOTe_Tests/TungstenCode_Tests.cpp b/libOTe_Tests/TungstenCode_Tests.cpp index 080be8a..0ff1232 100644 --- a/libOTe_Tests/TungstenCode_Tests.cpp +++ b/libOTe_Tests/TungstenCode_Tests.cpp @@ -2,7 +2,10 @@ #include "libOTe/Tools/TungstenCode/TungstenCode.h" #include "cryptoTools/Crypto/PRNG.h" #include "libOTe/Tools/CoeffCtx.h" - +#include "TungstenCode_Tests.h" +#include "ExConvCode_Tests.h" +#include "cryptoTools/Common/Log.h" +#include "libOTe/Tools/ExConvCode/ExConvChecker.h" using namespace oc; using namespace oc::experimental; namespace tests_libOTe @@ -16,7 +19,7 @@ namespace tests_libOTe > void accumulateBlock( span x, - u64 i, + u64 i, Ctx ctx) { auto table = Table::data; @@ -180,10 +183,35 @@ namespace tests_libOTe for (auto k : K) for (auto r : R) { TungstenCode_encode_impl(k, r); - TungstenCode_encode_impl(k,r); + TungstenCode_encode_impl(k, r); TungstenCode_encode_impl(k, r); TungstenCode_encode_impl, CoeffCtxArray>(k, r); } } + void TungstenCode_weight_test(const oc::CLP& cmd) + { + u64 k = cmd.getOr("k", 1ull << cmd.getOr("kk", 6)); + u64 n = k * 2; + bool verbose = cmd.isSet("v"); + TungstenCode encoder; + encoder.config(k, n); + encoder.mNumIter = cmd.getOr("iter", 2); + auto threshold = n / 4 - 2 * std::sqrt(n); + u64 min = 0; + //if(cmd.isSet("x2")) + // min = getGeneratorWeightx2(encoder, verbose); + //else + min = getGeneratorWeight(encoder, verbose); + + if (verbose) + { + std::cout << min << " / " << n << " = " << double(min) / n << " < threshold " << double(threshold) / n << std::endl; + } + + if (min < threshold) + { + throw RTE_LOC; + } + } } \ No newline at end of file diff --git a/libOTe_Tests/TungstenCode_Tests.h b/libOTe_Tests/TungstenCode_Tests.h index 6d8247c..6926bfa 100644 --- a/libOTe_Tests/TungstenCode_Tests.h +++ b/libOTe_Tests/TungstenCode_Tests.h @@ -10,4 +10,5 @@ namespace tests_libOTe { void TungstenCode_encode_test(const oc::CLP& cmd); + void TungstenCode_weight_test(const oc::CLP& cmd); } \ No newline at end of file diff --git a/libOTe_Tests/UnitTests.cpp b/libOTe_Tests/UnitTests.cpp index 85cb614..37d86a7 100644 --- a/libOTe_Tests/UnitTests.cpp +++ b/libOTe_Tests/UnitTests.cpp @@ -43,8 +43,13 @@ namespace tests_libOTe tc.add("Mtx_invert_test ", tests::Mtx_invert_test); tc.add("EACode_encode_basic_test ", EACode_encode_basic_test); + tc.add("EACode_weight_test ", EACode_weight_test); + tc.add("ExConvCode_encode_basic_test ", ExConvCode_encode_basic_test); + tc.add("ExConvCode_weight_test ", ExConvCode_weight_test); + tc.add("TungstenCode_encode_test ", TungstenCode_encode_test); + tc.add("TungstenCode_weight_test ", TungstenCode_weight_test); tc.add("Tools_Pprf_expandOne_test ", Tools_Pprf_expandOne_test); tc.add("Tools_Pprf_inter_test ", Tools_Pprf_inter_test);