1
0
mirror of https://github.com/biergaizi/codecrypt synced 2024-06-30 02:43:06 +00:00
codecrypt/lib/polynomial.cpp

229 lines
5.0 KiB
C++
Raw Normal View History

2012-04-01 11:51:59 +00:00
#include "codecrypt.h"
using namespace ccr;
2012-04-01 22:44:19 +00:00
int polynomial::degree() const
{
int r = -1;
2012-04-01 21:44:18 +00:00
for (uint i = 0; i < size(); ++i) if (item (i) ) r = i;
return r;
}
void polynomial::strip()
{
resize (degree() + 1);
}
2012-04-01 22:44:19 +00:00
bool polynomial::zero() const
{
for (uint i = 0; i < size(); ++i) if (item (i) ) return false;
return true;
}
2012-04-03 09:08:52 +00:00
void polynomial::add (const polynomial&f, gf2m&fld)
2012-04-01 21:44:18 +00:00
{
2012-04-01 22:44:19 +00:00
int df = f.degree();
2012-04-01 21:44:18 +00:00
if (df > degree() ) resize (df + 1);
2012-04-03 10:13:51 +00:00
for (int i = 0; i <= df; ++i) item (i) = fld.add (item (i), f[i]);
2012-04-01 21:44:18 +00:00
}
2012-04-03 09:08:52 +00:00
void polynomial::mod (const polynomial&f, gf2m&fld)
2012-04-01 21:44:18 +00:00
{
2012-04-01 22:44:19 +00:00
int df = f.degree();
int d;
2012-04-03 09:08:52 +00:00
uint hi = fld.inv (f[df]);
2012-04-01 21:44:18 +00:00
// while there's place to substract, reduce by x^(d-df)-multiply of f
2012-04-03 09:08:52 +00:00
for (d = degree(); d >= df; --d)
if (item (d) ) {
uint t = fld.mult (item (d), hi);
2012-04-04 21:01:55 +00:00
2012-04-03 09:08:52 +00:00
for (int i = 0; i <= df; ++i)
2012-04-03 10:13:51 +00:00
item (i + d - df) = fld.add (item (i + d - df),
fld.mult (t, f[i]) );
2012-04-03 09:08:52 +00:00
}
2012-04-01 21:44:18 +00:00
strip();
}
2012-04-03 09:08:52 +00:00
void polynomial::mult (const polynomial&b, gf2m&fld)
2012-04-01 21:44:18 +00:00
{
polynomial a = *this;
clear();
uint i, j, da, db;
da = a.degree();
db = b.degree();
resize (da + db + 1, 0);
for (i = 0; i <= da; ++i)
if (a[i]) for (j = 0; j <= db; ++j)
2012-04-03 09:08:52 +00:00
item (i + j) = fld.add (item (i + j),
fld.mult (a[i], b[j]) );
2012-04-01 21:44:18 +00:00
}
2012-04-03 09:08:52 +00:00
polynomial polynomial::gcd (polynomial b, gf2m&fld)
2012-04-01 11:51:59 +00:00
{
2012-04-01 21:44:18 +00:00
polynomial a = *this;
2012-04-01 11:51:59 +00:00
2012-04-01 21:44:18 +00:00
//eukleides
if (a.degree() < 0) return b;
for (;;) {
2012-04-01 22:44:19 +00:00
if (b.zero() ) return a;
2012-04-03 09:08:52 +00:00
a.mod (b, fld);
2012-04-01 22:44:19 +00:00
if (a.zero() ) return b;
2012-04-03 09:08:52 +00:00
b.mod (a, fld);
2012-04-01 21:44:18 +00:00
}
//unreachable
return polynomial();
2012-04-01 11:51:59 +00:00
}
2012-04-04 21:01:55 +00:00
bool polynomial::is_irreducible (gf2m&fld) const
2012-04-01 11:51:59 +00:00
{
2012-04-01 21:44:18 +00:00
//Ben-Or irreducibility test
polynomial xi; //x^(2^i) in our case
polynomial xmodf, t;
2012-04-01 11:51:59 +00:00
2012-04-01 22:44:19 +00:00
xmodf.resize (2); //precompute (x mod f) although it is usually just x
2012-04-01 21:44:18 +00:00
xmodf[0] = 0;
xmodf[1] = 1; //x
2012-04-01 22:44:19 +00:00
xi = xmodf;
2012-04-03 09:08:52 +00:00
xmodf.mod (*this, fld); //mod f
2012-04-01 21:44:18 +00:00
2012-04-03 09:08:52 +00:00
uint d = degree();
for (uint i = 1; i <= d / 2; ++i) {
2012-04-01 21:44:18 +00:00
t = xi;
2012-04-03 09:08:52 +00:00
t.mult (xi, fld); //because mult would destroy xi on xi.mult(xi)
t.mod (*this, fld);
2012-04-01 21:44:18 +00:00
xi = t;
2012-04-03 09:08:52 +00:00
t.add (xmodf, fld);
2012-04-01 21:44:18 +00:00
2012-04-03 09:08:52 +00:00
t = t.gcd (*this, fld);
2012-04-04 21:01:55 +00:00
if (t.degree() > 0) //gcd(f,x^2^i - x mod f) is polynomial
2012-04-01 21:44:18 +00:00
return false;
}
return true;
}
2012-04-03 10:13:51 +00:00
void polynomial::generate_random_irreducible (uint s, gf2m&fld, prng& rng)
2012-04-01 21:44:18 +00:00
{
resize (s + 1);
item (s) = 1; //degree s
2012-04-03 09:08:52 +00:00
item (0) = 1 + rng.random (fld.n - 1); //not divisible by x^1
for (uint i = 1; i < s; ++i) item (i) = rng.random (fld.n);
while (!is_irreducible (fld) ) {
uint pos = rng.random (s);
item (pos) = pos == 0 ?
(1 + rng.random (fld.n - 1) ) : rng.random (fld.n);
2012-04-01 21:44:18 +00:00
}
2012-04-01 11:51:59 +00:00
}
2012-04-03 10:51:23 +00:00
bool polynomial::compute_square_root_matrix (vector<polynomial>&r, gf2m&fld)
2012-04-02 17:16:32 +00:00
{
2012-04-03 10:51:23 +00:00
// step 1, generate a square matrix of squares mod poly.
2012-04-02 17:16:32 +00:00
int d = degree();
2012-04-03 10:51:23 +00:00
if (d < 0) return false;
vector<polynomial>l;
l.resize (d);
2012-04-02 17:16:32 +00:00
polynomial col, t;
for (int i = 0; i < d; ++i) {
col.clear();
col.resize (i + 1, 0);
col[i] = 1;
t = col;
2012-04-03 09:08:52 +00:00
col.mult (t, fld);
col.mod (*this, fld);
2012-04-02 17:16:32 +00:00
col.resize (d, 0);
2012-04-03 10:51:23 +00:00
l[i] = col;
}
// step 2, gauss-jordan inverse to unit matrix
2012-04-04 21:01:55 +00:00
r.resize (d);
for (int i = 0; i < d; ++i) {
2012-04-03 10:51:23 +00:00
r[i].clear();
2012-04-04 21:01:55 +00:00
r[i].resize (d, 0);
r[i][i] = 1;
2012-04-03 10:51:23 +00:00
}
#define add_row_mult(from,to,coeff) \
for(int c=0;c<d;++c) { \
l[c][to]=fld.add(l[c][to],fld.mult(l[c][from],coeff));\
r[c][to]=fld.add(r[c][to],fld.mult(r[c][from],coeff));\
}
#define row_mult(row,coeff) \
for(int c=0;c<d;++c) {\
l[c][row]=fld.mult(l[c][row],coeff);\
r[c][row]=fld.mult(r[c][row],coeff);\
}
2012-04-04 21:01:55 +00:00
2012-04-03 10:51:23 +00:00
//gauss
uint a;
2012-04-04 21:01:55 +00:00
int i, j;
for (i = 0; i < d; ++i) {
if (l[i][i] == 0) {
2012-04-03 10:51:23 +00:00
//find nonzero
2012-04-04 21:01:55 +00:00
for (j = i + 1; j < d; ++j) if (l[i][j] != 0) {
add_row_mult (j, i, 1);
break;
}
if (j == d) return false;
a = fld.inv (l[i][i]); //normalize
row_mult (i, a);
2012-04-03 10:51:23 +00:00
//zero the col
2012-04-04 21:01:55 +00:00
for (j = i + 1; j < d; ++j) if (l[i][j] != 0) {
a = l[i][j]; //"minus". luckily on GF(2^m) x+x=0.
add_row_mult (i, j, a);
}
2012-04-03 10:51:23 +00:00
}
2012-04-02 17:16:32 +00:00
}
2012-04-03 09:08:52 +00:00
2012-04-03 10:51:23 +00:00
//jordan
2012-04-04 21:01:55 +00:00
for (i = d - 1; i >= 0; --i)
for (j = 0; j < i; ++j) {
a = l[i][j];
if (a == 0) continue;
add_row_mult (i, j, a);
2012-04-03 10:51:23 +00:00
}
return true;
2012-04-02 17:16:32 +00:00
}
2012-04-04 21:01:55 +00:00
uint polynomial::eval (uint x, gf2m&fld) const
{
uint r = 0;
//horner
for (int i = degree(); i >= 0; --i)
r = fld.add (item (i), fld.mult (r, x) );
return r;
}
void polynomial::compute_goppa_check_matrix (matrix&r, gf2m&fld)
{
if (degree() < 0) return; //wrongly initialized polynomial
uint t = degree();
vector<vector<uint> > yz, h;
uint i, j, k;
yz.resize (t);
h.resize (t);
for (i = 0; i < t; ++i) {
yz[i].resize (fld.n);
h[i].resize (fld.n, 0);
}
//create Y*Z
for (i = 0; i < fld.n; ++i) yz[0][i] = fld.inv (eval (i, fld) );
for (i = 1; i < t; ++i) for (j = 0; j < fld.n; ++j)
yz[i][j] = fld.mult (yz[i-1][j], j);
//X*Y*Z = h
for (i = 0; i < t; ++i)
for (j = 0; j < fld.n; ++j)
for (k = 0; k <= i; ++k)
h[i][j] = fld.add (h[i][j], fld.mult
(yz[k][j],
item (t + k - i) ) );
//now convert to binary
r.resize (fld.n);
for (i = 0; i < fld.n; ++i) {
r[i].resize (fld.m * t, 0);
for (j = 0; j < fld.m * t; ++j)
r[i][j] = (h[j/fld.m][i] >> (j % fld.m) ) & 1;
}
}