diff --git a/lib/decoding.cpp b/lib/decoding.cpp index fe3db95..6ac5359 100644 --- a/lib/decoding.cpp +++ b/lib/decoding.cpp @@ -1,14 +1,15 @@ #include "decoding.h" -bool syndrome_decode (bvector&syndrome, gf2m&fld, polynomial& goppa, - std::vector& sqInv, bvector&ev, - bool check_failure) - +void compute_error_locator (bvector&syndrome, gf2m&fld, polynomial& goppa, + std::vector& sqInv, polynomial&out) { - ev.clear(); - ev.resize (fld.n, 0); - if (syndrome.zero() ) return true; + if (syndrome.zero() ) { + //ensure no roots + out.resize (1); + out[0] = 1; + return; + } polynomial v; syndrome.to_poly (v, fld); @@ -28,20 +29,26 @@ bool syndrome_decode (bvector&syndrome, gf2m&fld, polynomial& goppa, a.add (b, fld); //new a = a^2 + x b^2 a.make_monic (fld); //now it is the error locator. + out = a; +} + +bool evaluate_error_locator_dumb (polynomial&a, bvector&ev, gf2m&fld) +{ + ev.clear(); + ev.resize (fld.n, 0); for (uint i = 0; i < fld.n; ++i) { if (a.eval (i, fld) == 0) { ev[i] = 1; - if (!check_failure) continue; - //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. + //divide the polynomial by (found) linear factor polynomial t, q, r; t.resize (2, 0); t[0] = i; t[1] = 1; a.divmod (t, q, r, fld); + + //if it doesn't divide, die. if (r.degree() >= 0) { ev.clear(); return false; @@ -50,7 +57,8 @@ bool syndrome_decode (bvector&syndrome, gf2m&fld, polynomial& goppa, } } - if (check_failure && a.degree() > 0) { + //also if there's something left, die. + if (a.degree() > 0) { ev.clear(); return false; } diff --git a/lib/decoding.h b/lib/decoding.h index fcdee96..57eeba2 100644 --- a/lib/decoding.h +++ b/lib/decoding.h @@ -5,11 +5,14 @@ #include "codecrypt.h" using namespace ccr; -bool syndrome_decode (bvector&syndrome, - gf2m&fld, - polynomial& gp, - std::vector& sqInv, - bvector&ev, - bool check_failure = true); + +void compute_error_locator (bvector&syndrome, + gf2m&fld, + polynomial&goppa, + std::vector& sqInv, + polynomial&loc); + +bool evaluate_error_locator_dumb (polynomial&el, bvector&ev, gf2m&fld); +bool evaluate_error_locator_trace (polynomial&el, bvector&ev, gf2m&fld); #endif diff --git a/lib/mce.cpp b/lib/mce.cpp index 5bdf726..926df3b 100644 --- a/lib/mce.cpp +++ b/lib/mce.cpp @@ -79,13 +79,18 @@ int privkey::decrypt (const bvector&in, bvector&out) h.mult_vec_right (canonical, syndrome); //decode + polynomial loc; + compute_error_locator (syndrome, fld, g, sqInv, loc); + bvector ev; - if (!syndrome_decode (syndrome, fld, g, sqInv, ev) ) + if (!evaluate_error_locator_dumb (loc, ev, fld) ) 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() ) return 1; + //TODO cryptoanalysis suggests omitting this check for preventing + //bit-flipping attack //correct the errors canonical.add (ev); @@ -115,6 +120,7 @@ int privkey::sign (const bvector&in, bvector&out, uint delta, uint attempts, prn bvector p, e, synd, synd_orig, e2; std::vector epos; permutation hpermInv; + polynomial loc; s = hash_size(); @@ -143,7 +149,9 @@ int privkey::sign (const bvector&in, bvector&out, uint delta, uint attempts, prn synd.add (h[epos[i]]); } - if (syndrome_decode (synd, fld, g, sqInv, e2, true) ) { + compute_error_locator (synd, fld, g, sqInv, loc); + + if (evaluate_error_locator_dumb (loc, e2, fld) ) { //create the decodable message p.add (e); diff --git a/lib/nd.cpp b/lib/nd.cpp index 78b746b..0afdc8d 100644 --- a/lib/nd.cpp +++ b/lib/nd.cpp @@ -58,8 +58,11 @@ int privkey::decrypt (const bvector&in, bvector&out) bvector unsc; //unscrambled Sinv.mult_vec_right (in, unsc); + polynomial loc; + compute_error_locator (unsc, fld, g, sqInv, loc); + bvector ev; - if (!syndrome_decode (unsc, fld, g, sqInv, ev) ) + if (!evaluate_error_locator_dumb (loc, ev, fld) ) return 1; if ( (int) ev.hamming_weight() != g.degree() ) @@ -75,6 +78,8 @@ int privkey::sign (const bvector&in, bvector&out, uint delta, uint attempts, prn bvector synd_unsc, synd, e; + polynomial loc; + s = hash_size(); if (in.size() != s) return 2; @@ -88,7 +93,9 @@ int privkey::sign (const bvector&in, bvector&out, uint delta, uint attempts, prn Sinv.mult_vec_right (synd, synd_unsc); - if (syndrome_decode (synd_unsc, fld, g, sqInv, e, true) ) { + compute_error_locator (synd_unsc, fld, g, sqInv, loc); + + if (evaluate_error_locator_dumb (loc, e, fld) ) { Pinv.permute (e, out); return 0;