From d573d1cfe726d170b981e64af90495fb16ef89fd Mon Sep 17 00:00:00 2001 From: Mirek Kratochvil Date: Tue, 22 May 2012 15:41:56 +0200 Subject: [PATCH] mce: signatures and verification --- include/codecrypt.h | 6 ++--- lib/decoding.cpp | 24 +++++++++++++++--- lib/decoding.h | 2 +- lib/mce.cpp | 62 ++++++++++++++++++++++++++++++++++++++++----- lib/nd.cpp | 2 +- 5 files changed, 82 insertions(+), 14 deletions(-) diff --git a/include/codecrypt.h b/include/codecrypt.h index 8b2fe74..9b9d807 100644 --- a/include/codecrypt.h +++ b/include/codecrypt.h @@ -200,7 +200,7 @@ public: uint t; int encrypt (const bvector&, bvector&, prng&); - int verify (const bvector&, const bvector&, uint, uint); + int verify (const bvector&, const bvector&, uint); uint cipher_size() { return G.width(); @@ -224,7 +224,7 @@ public: // TODO int decrypt (const bvector&, bvector&); - int sign (const bvector&hash, bvector&sig, uint, uint, prng&); + int sign (const bvector&, bvector&, uint, uint, prng&); }; class pubkey @@ -234,7 +234,7 @@ public: uint t; int encrypt (const bvector&, bvector&, prng&); - int verify (const bvector&sig, const bvector&hash, uint, uint); + int verify (const bvector&, const bvector&, uint); }; int generate (pubkey&, privkey&, prng&); diff --git a/lib/decoding.cpp b/lib/decoding.cpp index a1993a9..2d3021a 100644 --- a/lib/decoding.cpp +++ b/lib/decoding.cpp @@ -1,13 +1,13 @@ #include "decoding.h" -void syndrome_decode (bvector&syndrome, gf2m&fld, polynomial& goppa, +bool syndrome_decode (bvector&syndrome, gf2m&fld, polynomial& goppa, std::vector& sqInv, bvector&ev) { ev.clear(); ev.resize (fld.n, 0); - if (syndrome.zero() ) return; + if (syndrome.zero() ) return true; polynomial v; syndrome.to_poly (v, fld); @@ -29,6 +29,24 @@ void syndrome_decode (bvector&syndrome, gf2m&fld, polynomial& goppa, a.make_monic (fld); //now it is the error locator. for (uint i = 0; i < fld.n; ++i) { - if (a.eval (i, fld) == 0) ev[i] = 1; + if (a.eval (i, fld) == 0) { + ev[i] = 1; + + //check if the error locator splits over GF(2^m). + //We simplify it to the assumption that all roots are + //also roots of linear factors. + polynomial t, q, r; + t.resize (2, 0); + t[0] = i; + t[1] = 1; + a.divmod (t, q, r, fld); + if (r.degree() >= 0) { + ev.clear(); + return false; + } + a = q; + } } + + return true; } diff --git a/lib/decoding.h b/lib/decoding.h index 640969a..48bc7a8 100644 --- a/lib/decoding.h +++ b/lib/decoding.h @@ -5,7 +5,7 @@ #include "codecrypt.h" using namespace ccr; -void syndrome_decode (bvector&syndrome, +bool syndrome_decode (bvector&syndrome, gf2m&fld, polynomial& gp, std::vector& sqInv, diff --git a/lib/mce.cpp b/lib/mce.cpp index 6dcb23f..b8526de 100644 --- a/lib/mce.cpp +++ b/lib/mce.cpp @@ -78,7 +78,9 @@ int privkey::decrypt (const bvector&in, bvector&out) //decode bvector ev; - 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() ) @@ -106,14 +108,62 @@ int privkey::prepare () 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, t, s; + bvector p, e, synd, synd2, e2; + std::vector epos; + permutation hpermInv; - return -1; //TODO + s = cipher_size(); + + //TODO check sizes of everything! + + //first, prepare the codeword to canonical form for decoding + Pinv.permute (in, e2); + hperm.compute_inversion (hpermInv); + hpermInv.permute (e2, p); + + //prepare extra error vector + e.resize (s, 0); + epos.resize (delta); + + h.mult_vec_right (p, synd); + + for (t = 0; t < attempts; ++t) { + for (i = 0; i < s; ++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; + } + + //abuse linearity of p+e; it is usually faster. + h.mult_vec_right (e, synd2); + synd2.add (synd); + + if (syndrome_decode (synd2, fld, g, sqInv, e2) ) { + //decoding success! + p.add (e); //add original errors + hperm.permute (p, e2); //back to systematic (e2~=tmp) + Sinv.mult_vecT_left (e2, out); //get a signature + return 0; //OK lol + } + + //if this round failed, we try a new error pattern. + + for (i = 0; i < s; ++i) //clear the errors for the next cycle + e[epos[i]] = 0; + } + return 1; //couldn't decode } -int pubkey::verify (const bvector&in, const bvector&hash, uint delta, uint h) +int pubkey::verify (const bvector&in, const bvector&hash, uint delta) { - - return -1; //TODO + bvector tmp; + //TODO check sizes! + G.mult_vecT_left (in, tmp); + tmp.add (hash); + if (tmp.hamming_weight() > (t + delta) ) return 1; //not a signature + return 0; //sig OK } diff --git a/lib/nd.cpp b/lib/nd.cpp index de8c6ac..2ea7f86 100644 --- a/lib/nd.cpp +++ b/lib/nd.cpp @@ -28,7 +28,7 @@ int privkey::sign (const bvector&in, bvector&out, uint delta, uint h, prng&rng) return -1; //TODO } -int pubkey::verify (const bvector&in, const bvector&hash, uint delta, uint h) +int pubkey::verify (const bvector&in, const bvector&hash, uint delta) { return -1; //TODO