101 lines
1.8 KiB
C++
101 lines
1.8 KiB
C++
|
|
#include "codecrypt.h"
|
|
|
|
#include "decoding.h"
|
|
|
|
using namespace ccr;
|
|
using namespace ccr::nd;
|
|
|
|
int nd::generate (pubkey&pub, privkey&priv, prng&rng, uint m, uint t)
|
|
{
|
|
//galois field
|
|
priv.fld.create (m);
|
|
|
|
//goppa polynomial
|
|
priv.g.generate_random_irreducible (t, priv.fld, rng);
|
|
|
|
matrix h;
|
|
priv.g.compute_goppa_check_matrix (h, priv.fld);
|
|
|
|
//scrambler
|
|
matrix S;
|
|
S.generate_random_invertible (h.height(), rng);
|
|
S.compute_inversion (priv.Sinv);
|
|
|
|
//permutation
|
|
permutation P;
|
|
P.generate_random (h.width(), rng);
|
|
P.compute_inversion (priv.Pinv);
|
|
|
|
//pubkey
|
|
pub.t = t;
|
|
S.mult (h);
|
|
P.permute (S, pub.H);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int pubkey::encrypt (const bvector& in, bvector&out)
|
|
{
|
|
if (in.size() != plain_size() ) return 1;
|
|
H.mult_vec_right (in, out);
|
|
return 0;
|
|
}
|
|
|
|
int privkey::decrypt (const bvector&in, bvector&out)
|
|
{
|
|
if (in.size() != cipher_size() ) return 2;
|
|
|
|
bvector unsc; //unscrambled
|
|
Sinv.mult_vec_right (in, unsc);
|
|
|
|
bvector ev;
|
|
if (!syndrome_decode (unsc, fld, g, sqInv, ev) )
|
|
return 1;
|
|
|
|
if ( (int) ev.hamming_weight() != g.degree() )
|
|
return 1;
|
|
|
|
Pinv.permute (ev, out);
|
|
return 0;
|
|
}
|
|
|
|
int privkey::sign (const bvector&in, bvector&out, uint delta, uint attempts, prng&rng)
|
|
{
|
|
uint i, s, t;
|
|
|
|
bvector synd_orig, synd, e;
|
|
|
|
s = hash_size();
|
|
if (in.size() != s) return 2;
|
|
|
|
Sinv.mult_vec_right (in, synd_orig);
|
|
|
|
for (t = 0; t < attempts; ++t) {
|
|
|
|
synd = synd_orig;
|
|
for (i = 0; i < delta; ++i) {
|
|
uint pos = rng.random (s);
|
|
synd[pos] = !synd[pos]; //flip a bit
|
|
}
|
|
|
|
if (syndrome_decode (synd, fld, g, sqInv, e, true) ) {
|
|
|
|
Pinv.permute (e, out);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int pubkey::verify (const bvector&in, const bvector&hash, uint delta)
|
|
{
|
|
bvector tmp;
|
|
if (!H.mult_vec_right (in, tmp) ) return 2;
|
|
if (hash.size() != tmp.size() ) return 1;
|
|
tmp.add (hash);
|
|
if (tmp.hamming_weight() > delta) return 1;
|
|
return 0;
|
|
}
|