niederreiter + various related fixes
This commit is contained in:
		
							parent
							
								
									7b3d2f69ce
								
							
						
					
					
						commit
						c9df69a83f
					
				| 
						 | 
					@ -4,7 +4,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <vector>
 | 
					#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 \
 | 
					#define _ccr_declare_vector_item \
 | 
				
			||||||
	inline reference item(size_type n) \
 | 
						inline reference item(size_type n) \
 | 
				
			||||||
		{ return (*this)[n]; }; \
 | 
							{ return (*this)[n]; }; \
 | 
				
			||||||
| 
						 | 
					@ -233,10 +233,33 @@ namespace nd
 | 
				
			||||||
class privkey
 | 
					class privkey
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	// TODO
 | 
						matrix Sinv;
 | 
				
			||||||
 | 
						permutation Pinv;
 | 
				
			||||||
 | 
						polynomial g;
 | 
				
			||||||
 | 
						gf2m fld;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//derivable.
 | 
				
			||||||
 | 
						std::vector<polynomial> sqInv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int decrypt (const bvector&, bvector&);
 | 
						int decrypt (const bvector&, bvector&);
 | 
				
			||||||
	int sign (const bvector&, bvector&, uint, uint, prng&);
 | 
						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
 | 
					class pubkey
 | 
				
			||||||
| 
						 | 
					@ -245,11 +268,27 @@ public:
 | 
				
			||||||
	matrix H;
 | 
						matrix H;
 | 
				
			||||||
	uint t;
 | 
						uint t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int encrypt (const bvector&, bvector&, prng&);
 | 
						int encrypt (const bvector&, bvector&);
 | 
				
			||||||
	int verify (const bvector&, const bvector&, uint);
 | 
						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
 | 
					} //namespace ccr
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										38
									
								
								lib/mce.cpp
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								lib/mce.cpp
									
									
									
									
									
								
							| 
						 | 
					@ -6,7 +6,7 @@ using namespace ccr::mce;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "decoding.h"
 | 
					#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
 | 
						//finite field
 | 
				
			||||||
	priv.fld.create (m);
 | 
						priv.fld.create (m);
 | 
				
			||||||
| 
						 | 
					@ -80,9 +80,8 @@ int privkey::decrypt (const bvector&in, bvector&out)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//decode
 | 
						//decode
 | 
				
			||||||
	bvector ev;
 | 
						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.
 | 
							return 1; //if decoding somehow failed, fail as well.
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// check the error vector, it should have exactly t == deg (g) errors
 | 
						// check the error vector, it should have exactly t == deg (g) errors
 | 
				
			||||||
	if ( (int) ev.hamming_weight() != g.degree() )
 | 
						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)
 | 
					int privkey::sign (const bvector&in, bvector&out, uint delta, uint attempts, prng&rng)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint i, t, s;
 | 
						uint i, s, t;
 | 
				
			||||||
	bvector p, e, synd, synd2, e2;
 | 
						bvector p, e, synd, synd_orig, e2;
 | 
				
			||||||
	std::vector<uint> epos;
 | 
						std::vector<uint> epos;
 | 
				
			||||||
	permutation hpermInv;
 | 
						permutation hpermInv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -130,33 +129,38 @@ int privkey::sign (const bvector&in, bvector&out, uint delta, uint attempts, prn
 | 
				
			||||||
	e.resize (s, 0);
 | 
						e.resize (s, 0);
 | 
				
			||||||
	epos.resize (delta, 0);
 | 
						epos.resize (delta, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	h.mult_vec_right (p, synd);
 | 
						h.mult_vec_right (p, synd_orig);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (t = 0; t < attempts; ++t) {
 | 
						for (t = 0; t < attempts; ++t) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							synd = synd_orig;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (i = 0; i < delta; ++i) {
 | 
							for (i = 0; i < delta; ++i) {
 | 
				
			||||||
			epos[i] = rng.random (s);
 | 
								epos[i] = rng.random (s);
 | 
				
			||||||
			/* we don't care about (unlikely) error bit collisions
 | 
								/* we don't care about (unlikely) error bit collisions
 | 
				
			||||||
			   (they actually don't harm anything) */
 | 
								   (they actually don't harm anything) */
 | 
				
			||||||
			e[epos[i]] = 1;
 | 
								e[epos[i]] = 1;
 | 
				
			||||||
 | 
								synd.add (h[epos[i]]);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		//abuse linearity of p+e; it is usually faster.
 | 
							if (syndrome_decode (synd, fld, g, sqInv, e2, true) ) {
 | 
				
			||||||
		h.mult_vec_right (e, synd2);
 | 
					 | 
				
			||||||
		synd2.add (synd);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (syndrome_decode (synd2, fld, g, sqInv, e2) ) {
 | 
								//create the decodable message
 | 
				
			||||||
			//decoding success!
 | 
								p.add(e);
 | 
				
			||||||
			p.add (e); //add original errors
 | 
								p.add(e2);
 | 
				
			||||||
			hperm.permute (p, e2); //back to systematic (e2 is tmp)
 | 
					
 | 
				
			||||||
			e2.resize (signature_size() ); //strip redundancy
 | 
								hperm.permute (p, e2); //back to systematic
 | 
				
			||||||
			Sinv.mult_vecT_left (e2, out); //get a signature
 | 
								e2.resize (signature_size() ); //strip checks
 | 
				
			||||||
			return 0; //OK lol
 | 
								Sinv.mult_vecT_left (e2, out); //signature
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		//if this round failed, we try a new error pattern.
 | 
							//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;
 | 
								e[epos[i]] = 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return 1; //couldn't decode
 | 
						return 1; //couldn't decode
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										85
									
								
								lib/nd.cpp
									
									
									
									
									
								
							
							
						
						
									
										85
									
								
								lib/nd.cpp
									
									
									
									
									
								
							| 
						 | 
					@ -1,35 +1,100 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "codecrypt.h"
 | 
					#include "codecrypt.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "decoding.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace ccr;
 | 
					using namespace ccr;
 | 
				
			||||||
using namespace ccr::nd;
 | 
					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)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						if (in.size() != plain_size() ) return 1;
 | 
				
			||||||
	return -1; //TODO
 | 
						H.mult_vec_right (in, out);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int privkey::decrypt (const bvector&in, bvector&out)
 | 
					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)
 | 
					int pubkey::verify (const bvector&in, const bvector&hash, uint delta)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						bvector tmp;
 | 
				
			||||||
	return -1; //TODO
 | 
						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;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,7 +26,7 @@ int main()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ccr::mce::privkey priv;
 | 
						ccr::mce::privkey priv;
 | 
				
			||||||
	ccr::mce::pubkey pub;
 | 
						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 << "PRIVATE KEY" << endl;
 | 
				
			||||||
	cout << priv.fld;
 | 
						cout << priv.fld;
 | 
				
			||||||
| 
						 | 
					@ -38,6 +38,8 @@ int main()
 | 
				
			||||||
	cout << pub.t << endl;
 | 
						cout << pub.t << endl;
 | 
				
			||||||
	cout << pub.G;
 | 
						cout << pub.G;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* mce encryption test */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ccr::bvector plain;
 | 
						ccr::bvector plain;
 | 
				
			||||||
	plain.resize (pub.plain_size(), 0);
 | 
						plain.resize (pub.plain_size(), 0);
 | 
				
			||||||
	plain[0] = 1;
 | 
						plain[0] = 1;
 | 
				
			||||||
| 
						 | 
					@ -71,9 +73,9 @@ int main()
 | 
				
			||||||
	hash[2] = 1;
 | 
						hash[2] = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cout << "SIGNING" << endl << hash;
 | 
						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;
 | 
						cout << "SIGNATURE" << endl << signature;
 | 
				
			||||||
	if (pub.verify (signature, hash, 2) )
 | 
						if (pub.verify (signature, hash, 3) )
 | 
				
			||||||
		cout << "VERIFY FAIL" << endl;
 | 
							cout << "VERIFY FAIL" << endl;
 | 
				
			||||||
	else	cout << "VERIFY OK" << endl;
 | 
						else	cout << "VERIFY OK" << endl;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue