niederreiter + various related fixes
This commit is contained in:
		
							parent
							
								
									7b3d2f69ce
								
							
						
					
					
						commit
						c9df69a83f
					
				| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										38
									
								
								lib/mce.cpp
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								lib/mce.cpp
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										85
									
								
								lib/nd.cpp
									
									
									
									
									
								
							
							
						
						
									
										85
									
								
								lib/nd.cpp
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue