diff --git a/include/codecrypt.h b/include/codecrypt.h index a8462e9..ffcc6db 100644 --- a/include/codecrypt.h +++ b/include/codecrypt.h @@ -388,6 +388,8 @@ public: std::vector<uint> Hsig; //signature of canonical H matrix std::vector<uint> support; //computed goppa support polynomial g; //computed goppa polynomial + std::vector<polynomial> sqInv; + int decrypt (const bvector&, bvector&); int prepare(); @@ -404,6 +406,7 @@ class pubkey { public: uint T; + uint k; std::vector<bvector> qd_sigs; int encrypt (const bvector&, bvector&, prng&); diff --git a/lib/fwht.cpp b/lib/fwht.cpp new file mode 100644 index 0000000..e913c52 --- /dev/null +++ b/lib/fwht.cpp @@ -0,0 +1,53 @@ + +#include "fwht.h" + +#include <vector> +using namespace std; + +/* + * we count on that all integers are sufficiently large. + * They should be, largest value occuring should be O(k*n) if initial vector is + * consisted only from {0,1}^n, and we don't usually have codes of this size. + */ + +static void fwht (vector<int> x, vector<int>&r) +{ + int bs, s; + s = x.size(); + r.resize (s); + bs = s >> 1; + r.swap (x); + while (bs) { + x.swap (r); + for (uint i = 0; i < s; ++i) { + if ( (i / bs) & 1) + r[i] = x[i-bs] - x[i]; + else + r[i] = x[i] + x[i+bs]; + } + bs >>= 1; + } +} + +//we expect correct parameter size and preallocated out. +void fwht_dyadic_multiply (const bvector& a, const bvector& b, bvector& out) +{ + + //lift everyting to Z. + vector<int> t, A, B; + uint i; + + for (i = 0; i < a.size(); ++i) t[i] = a[i]; + fwht (t, A); + + for (i = 0; i < b.size(); ++i) t[i] = b[i]; + fwht (t, B); + + //multiply diagonals to A + for (i = 0; i < A.size(); ++i) A[i] *= B[i]; + fwht (A, t); + + uint bitpos = a.size(); //no problem as a.size() == 1<<m == 2^m + for (i = 0; i < t.size(); ++i) out[i] = (t[i] & bitpos) ? 1 : 0; +} + diff --git a/lib/fwht.h b/lib/fwht.h new file mode 100644 index 0000000..a7e51d1 --- /dev/null +++ b/lib/fwht.h @@ -0,0 +1,13 @@ + +#ifndef _fwht_h_ +#define _fwht_h_ + +#include "codecrypt.h" + +using namespace ccr; + +//parameters MUST be of 2^m size. +void fwht_dyadic_multiply (const bvector&, const bvector&, bvector&); + +#endif + diff --git a/lib/mce_qd.cpp b/lib/mce_qd.cpp index de1203f..aba93b7 100644 --- a/lib/mce_qd.cpp +++ b/lib/mce_qd.cpp @@ -70,18 +70,18 @@ int mce_qd::generate (pubkey&pub, privkey&priv, prng&rng, used.insert (fld.inv (essence[s]) ); for (uint j = 1; j < i; ++j) { - Hsig[i+j] = fld.inv ( - fld.add ( - fld.inv (Hsig[i]), - fld.add ( - fld.inv (Hsig[j]), - essence[m-1] - ) ) ); + Hsig[i+j] = fld.inv + (fld.add + (fld.inv (Hsig[i]), + fld.add ( + fld.inv (Hsig[j]), + essence[m-1] + ) ) ); used.insert (Hsig[i+j]); - used.insert (fld.inv ( - fld.add ( - fld.inv (Hsig[i+j]), - essence[m-1]) ) ); + used.insert (fld.inv + (fld.add + (fld.inv (Hsig[i+j]), + essence[m-1]) ) ); } } @@ -182,6 +182,7 @@ int mce_qd::generate (pubkey&pub, privkey&priv, prng&rng, */ pub.T = T; + pub.k = (block_count - fld.m) * block_size; pub.qd_sigs.resize (ri.width() / t); for (uint i = 0; i < ri.width(); i += t) pub.qd_sigs[i/t] = ri[i]; @@ -192,14 +193,105 @@ int mce_qd::generate (pubkey&pub, privkey&priv, prng&rng, int privkey::prepare() { - //TODO compute H signature from essence - //TODO compute goppa code support + //compute H signature from essence + Hsig.resize (fld.n / 2); + Hsig[0] = fld.inv (essence[fld.m-1]); + for (uint s = 0; s < fld.m - 1; ++s) { + uint i = 1 << s; //i = 2^s + + //TODO verify this + Hsig[i] = fld.inv (fld.add (essence[s], essence[fld.m-1]) ); + + for (uint j = 1; j < i; ++j) + Hsig[i+j] = fld.inv + (fld.add + (fld.inv (Hsig[i]), + fld.add ( + fld.inv (Hsig[j]), + essence[fld.m-1] + ) ) ); + } + + //compute the support + support.resize (fld.n / 2); + for (uint i = 0; i < fld.n / 2; ++i) { + support[i] = fld.add + (fld.inv (Hsig[i]), + essence[fld.m-1]); + + } + + //goppa polynomial + g.clear(); + g.resize (1, 1); + polynomial tmp; + tmp.resize (2, 1); + uint t = 1 << T; + for (uint i = 0; i < t; ++i) { + tmp[0] = fld.inv (Hsig[i]); + g.mult (tmp, fld); + } + + //sqInv + g.compute_square_root_matrix (sqInv, fld); + return 0; } +#include "fwht.h" + int pubkey::encrypt (const bvector& in, bvector&out, prng&rng) { - //TODO FWHT + uint t = 1 << T; + bvector p, g, r, cksum; + + /* + * shortened checksum pair of G is computed blockwise accordingly to + * the t-sized square dyadic blocks. + */ + + //some checks + if (in.size() != k) return 1; + if (!qd_sigs.size() ) return 1; + if (qd_sigs[0].size() % t) return 1; + + uint blocks = qd_sigs[0].size() / t; + cksum.resize (qd_sigs[0].size(), 0); + + p.resize (t); + g.resize (t); + r.resize (t); + + for (uint i = 0; i < blocks; ++i) { + //plaintext block + for (uint k = 0; k < t; ++k) p[k] = in[k+i*t]; + + for (uint j = 0; j < qd_sigs.size(); ++j) { + //checksum block + for (uint k = 0; k < t; ++k) g[k] = qd_sigs[i][k+j*t]; + + //block result + fwht_dyadic_multiply (p, g, r); + cksum.add_offset (r, t * j); + } + } + + //generate t errors + bvector e; + e.resize (k + qd_sigs[0].size(), 0); + for (uint n = t; n > 0;) { + uint p = rng.random (e.size() ); + if (!e[p]) { + e[p] = 1; + --n; + } + } + + //compute ciphertext + out = in; + out.insert (out.end(), cksum.begin(), cksum.end() ); + out.add (e); + return 0; }