niederreiter + various related fixes

This commit is contained in:
Mirek Kratochvil 2012-06-01 23:49:07 +02:00
parent 7b3d2f69ce
commit c9df69a83f
5 changed files with 149 additions and 34 deletions

View file

@ -4,7 +4,7 @@
#include <vector>
//STL wraparound, because writing (*this)[i] everywhere is clumsy
//little STL helper, because writing (*this)[i] everywhere is clumsy
#define _ccr_declare_vector_item \
inline reference item(size_type n) \
{ return (*this)[n]; }; \
@ -233,10 +233,33 @@ namespace nd
class privkey
{
public:
// TODO
matrix Sinv;
permutation Pinv;
polynomial g;
gf2m fld;
//derivable.
std::vector<polynomial> sqInv;
int decrypt (const bvector&, bvector&);
int sign (const bvector&, bvector&, uint, uint, prng&);
int prepare();
uint cipher_size() {
return Pinv.size();
}
uint plain_size() {
return Sinv.width();
}
uint plain_weight() {
return g.degree();
}
uint hash_size() {
return cipher_size();
}
uint signature_size() {
return plain_size();
}
};
class pubkey
@ -245,11 +268,27 @@ public:
matrix H;
uint t;
int encrypt (const bvector&, bvector&, prng&);
int encrypt (const bvector&, bvector&);
int verify (const bvector&, const bvector&, uint);
uint cipher_size() {
return H.height();
}
uint plain_size() {
return H.width();
}
uint plain_weight() {
return t;
}
uint hash_size() {
return cipher_size();
}
uint signature_size() {
return plain_size();
}
};
int generate (pubkey&, privkey&, prng&);
int generate (pubkey&, privkey&, prng&, uint m, uint t);
}
} //namespace ccr

View file

@ -50,5 +50,10 @@ bool syndrome_decode (bvector&syndrome, gf2m&fld, polynomial& goppa,
}
}
if (check_failure && a.degree() > 0) {
ev.clear();
return false;
}
return true;
}

View file

@ -6,7 +6,7 @@ using namespace ccr::mce;
#include "decoding.h"
int ccr::mce::generate (pubkey&pub, privkey&priv, prng&rng, uint m, uint t)
int mce::generate (pubkey&pub, privkey&priv, prng&rng, uint m, uint t)
{
//finite field
priv.fld.create (m);
@ -80,9 +80,8 @@ int privkey::decrypt (const bvector&in, bvector&out)
//decode
bvector ev;
if (!syndrome_decode (syndrome, fld, g, sqInv, ev) ) {
if (!syndrome_decode (syndrome, fld, g, sqInv, ev) )
return 1; //if decoding somehow failed, fail as well.
}
// check the error vector, it should have exactly t == deg (g) errors
if ( (int) ev.hamming_weight() != g.degree() )
@ -112,8 +111,8 @@ int privkey::prepare ()
int privkey::sign (const bvector&in, bvector&out, uint delta, uint attempts, prng&rng)
{
uint i, t, s;
bvector p, e, synd, synd2, e2;
uint i, s, t;
bvector p, e, synd, synd_orig, e2;
std::vector<uint> epos;
permutation hpermInv;
@ -130,33 +129,38 @@ int privkey::sign (const bvector&in, bvector&out, uint delta, uint attempts, prn
e.resize (s, 0);
epos.resize (delta, 0);
h.mult_vec_right (p, synd);
h.mult_vec_right (p, synd_orig);
for (t = 0; t < attempts; ++t) {
synd = synd_orig;
for (i = 0; i < delta; ++i) {
epos[i] = rng.random (s);
/* we don't care about (unlikely) error bit collisions
(they actually don't harm anything) */
e[epos[i]] = 1;
synd.add (h[epos[i]]);
}
//abuse linearity of p+e; it is usually faster.
h.mult_vec_right (e, synd2);
synd2.add (synd);
if (syndrome_decode (synd, fld, g, sqInv, e2, true) ) {
if (syndrome_decode (synd2, fld, g, sqInv, e2) ) {
//decoding success!
p.add (e); //add original errors
hperm.permute (p, e2); //back to systematic (e2 is tmp)
e2.resize (signature_size() ); //strip redundancy
Sinv.mult_vecT_left (e2, out); //get a signature
return 0; //OK lol
//create the decodable message
p.add(e);
p.add(e2);
hperm.permute (p, e2); //back to systematic
e2.resize (signature_size() ); //strip checks
Sinv.mult_vecT_left (e2, out); //signature
return 0;
}
//if this round failed, we try a new error pattern.
for (i = 0; i < delta; ++i) //clear the errors for the next cycle
for (i = 0; i < delta; ++i) {
//clear the errors for next cycle
e[epos[i]] = 0;
}
}
return 1; //couldn't decode
}

View file

@ -1,35 +1,100 @@
#include "codecrypt.h"
#include "decoding.h"
using namespace ccr;
using namespace ccr::nd;
int nd::generate (pubkey&pub, privkey&priv, prng&rng)
int nd::generate (pubkey&pub, privkey&priv, prng&rng, uint m, uint t)
{
//galois field
priv.fld.create (m);
return -1; //TODO
//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, prng&rng)
int pubkey::encrypt (const bvector& in, bvector&out)
{
return -1; //TODO
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;
return -1; //TODO
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 h, prng&rng)
int privkey::sign (const bvector&in, bvector&out, uint delta, uint attempts, prng&rng)
{
uint i, s, t;
return -1; //TODO
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)
{
return -1; //TODO
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;
}

View file

@ -26,7 +26,7 @@ int main()
ccr::mce::privkey priv;
ccr::mce::pubkey pub;
ccr::mce::generate (pub, priv, r, 7, 4);
ccr::mce::generate (pub, priv, r, 7, 2);
cout << "PRIVATE KEY" << endl;
cout << priv.fld;
@ -38,6 +38,8 @@ int main()
cout << pub.t << endl;
cout << pub.G;
/* mce encryption test */
ccr::bvector plain;
plain.resize (pub.plain_size(), 0);
plain[0] = 1;
@ -71,9 +73,9 @@ int main()
hash[2] = 1;
cout << "SIGNING" << endl << hash;
priv.sign (hash, signature, 2, priv.hash_size() *priv.hash_size(), r);
priv.sign (hash, signature, 3, priv.hash_size() *priv.hash_size(), r);
cout << "SIGNATURE" << endl << signature;
if (pub.verify (signature, hash, 2) )
if (pub.verify (signature, hash, 3) )
cout << "VERIFY FAIL" << endl;
else cout << "VERIFY OK" << endl;
return 0;