1
0
mirror of https://github.com/biergaizi/codecrypt synced 2024-06-28 09:53:46 +00:00

mce_qd: encryption

This commit is contained in:
Mirek Kratochvil 2012-09-30 11:55:23 +02:00
parent ec81c53463
commit 09538f45d8
4 changed files with 175 additions and 14 deletions

@ -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&);

53
lib/fwht.cpp Normal file

@ -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;
}

13
lib/fwht.h Normal file

@ -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

@ -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;
}