diff --git a/include/codecrypt.h b/include/codecrypt.h index 48c8168..a70cd72 100644 --- a/include/codecrypt.h +++ b/include/codecrypt.h @@ -347,6 +347,7 @@ public: int prepare(); int decrypt (const bvector&, bvector&); + int decrypt (const bvector&, bvector&, bvector&); int sign (const bvector&, bvector&, uint, uint, prng&); uint cipher_size() { @@ -361,6 +362,9 @@ public: uint signature_size() { return plain_size(); } + uint error_count() { + return g.degree(); + } sencode* serialize(); bool unserialize (sencode*); @@ -373,6 +377,7 @@ public: uint t; int encrypt (const bvector&, bvector&, prng&); + int encrypt (const bvector&, bvector&, const bvector&); int verify (const bvector&, const bvector&, uint); uint cipher_size() { @@ -387,6 +392,9 @@ public: uint signature_size() { return plain_size(); } + uint error_count() { + return t; + } sencode* serialize(); bool unserialize (sencode*); @@ -501,6 +509,7 @@ public: std::vector support_pos; int decrypt (const bvector&, bvector&); + int decrypt (const bvector&, bvector&, bvector&); int prepare(); uint cipher_size() { @@ -509,6 +518,9 @@ public: uint plain_size() { return (1 << T) * (hperm.size() - fld.m); } + uint error_count() { + return 1 << T; + } sencode* serialize(); bool unserialize (sencode*); @@ -521,6 +533,7 @@ public: matrix qd_sigs; int encrypt (const bvector&, bvector&, prng&); + int encrypt (const bvector&, bvector&, const bvector&); uint cipher_size() { return plain_size() + qd_sigs[0].size(); @@ -528,6 +541,9 @@ public: uint plain_size() { return (1 << T) * qd_sigs.size(); } + uint error_count() { + return 1 << T; + } sencode* serialize(); bool unserialize (sencode*); diff --git a/lib/mce.cpp b/lib/mce.cpp index 734d737..64c8cf6 100644 --- a/lib/mce.cpp +++ b/lib/mce.cpp @@ -59,12 +59,8 @@ int pubkey::encrypt (const bvector& in, bvector&out, prng&rng) { uint s = cipher_size(); if (t > s) return 1; - if (in.size() != plain_size() ) return 2; - //make a codeword - G.mult_vecT_left (in, out); - - //add error vector + //create error vector bvector e; e.resize (s, 0); for (uint n = t; n > 0;) { @@ -74,11 +70,25 @@ int pubkey::encrypt (const bvector& in, bvector&out, prng&rng) --n; } } - out.add (e); + return encrypt (in, out, e); +} + +int pubkey::encrypt (const bvector&in, bvector&out, const bvector&errors) +{ + if (in.size() != plain_size() ) return 2; + if (errors.size() != cipher_size() ) return 2; + G.mult_vecT_left (in, out); + out.add (errors); return 0; } int privkey::decrypt (const bvector&in, bvector&out) +{ + bvector tmp_errors; + return decrypt (in, out, tmp_errors); +} + +int privkey::decrypt (const bvector&in, bvector&out, bvector&errors) { if (in.size() != cipher_size() ) return 2; @@ -108,6 +118,7 @@ int privkey::decrypt (const bvector&in, bvector&out) //shuffle back into systematic order hperm.permute (canonical, not_permuted); + hperm.permute (ev, errors); //get rid of redundancy bits not_permuted.resize (plain_size() ); diff --git a/lib/mce_qd.cpp b/lib/mce_qd.cpp index b697ff2..e0c6014 100644 --- a/lib/mce_qd.cpp +++ b/lib/mce_qd.cpp @@ -334,7 +334,26 @@ int privkey::prepare() return 0; } -int pubkey::encrypt (const bvector & in, bvector & out, prng & rng) +int pubkey::encrypt (const bvector& in, bvector&out, prng&rng) +{ + uint s = cipher_size(), + t = 1 << T; + if (t > s) return 1; + + //create error vector + bvector e; + e.resize (s, 0); + for (uint n = t; n > 0;) { + uint p = rng.random (s); + if (!e[p]) { + e[p] = 1; + --n; + } + } + return encrypt (in, out, e); +} + +int pubkey::encrypt (const bvector & in, bvector & out, const bvector&errors) { uint t = 1 << T; bvector p, g, r, cksum; @@ -348,6 +367,8 @@ int pubkey::encrypt (const bvector & in, bvector & out, prng & rng) //some checks if (!qd_sigs.width() ) return 1; if (qd_sigs.height() % t) return 1; + if (in.size() != plain_size() ) return 2; + if (errors.size() != cipher_size() ) return 2; uint blocks = qd_sigs.height() / t; cksum.resize (qd_sigs.height(), 0); @@ -370,26 +391,21 @@ int pubkey::encrypt (const bvector & in, bvector & out, prng & rng) } } - //generate t errors - bvector e; - e.resize (cipher_size(), 0); - for (uint n = t; n > 0;) { - uint p = rng.random (e.size() ); - if (!e[p]) { - e[p] = 1; - --n; - } - } - //compute ciphertext out = in; out.insert (out.end(), cksum.begin(), cksum.end() ); - out.add (e); + out.add (errors); return 0; } int privkey::decrypt (const bvector & in, bvector & out) +{ + bvector tmp_errors; + return decrypt (in, out, tmp_errors); +} + +int privkey::decrypt (const bvector & in, bvector & out, bvector & errors) { if (in.size() != cipher_size() ) return 2; polynomial synd; @@ -411,6 +427,8 @@ int privkey::decrypt (const bvector & in, bvector & out) out = in; out.resize (plain_size() ); + errors.clear(); + errors.resize (cipher_size(), 0); //flip error positions of out. for (i = 0; i < ev.size(); ++i) if (ev[i]) { uint epos = support_pos[fld.inv (i)]; @@ -419,6 +437,8 @@ int privkey::decrypt (const bvector & in, bvector & out) out.clear(); return 1; } + if (epos >= cipher_size() ) return 1; + errors[epos] = 1; if (epos < plain_size() ) out[epos] = !out[epos]; }