accès aux groupes de discussion, consultation et publication d'articles, recherche de "newsgroups"...
membres, identifiez-vous
é-mail Mot de passe
nouveau ? mot de passe oublié ?
Chargement... Chargement en cours...

Groupes français belges canadiens suisses internationaux Nétiquette
Échangez opinions et commentaires dans les forums de discussion.

Re: Re: Polynôme générateur

 [  Nouvelle Discussion Nouvelle discussion  |  Répondre au groupe Répondre au groupe  |  fr.misc.cryptologie ] 

Retour : Accueil du site fr misc cryptologie   charte stats de ce groupe


  Sujet:   Re: Re: Polynôme générateur  
 De: por...@bolet.org (Thomas Pornin)
 Groupes: fr.misc.cryptologie
 Organisation: Guest of ProXad - France
 Date: 14. Apr 2008, 10:04:43
 References: 1 2 3 4
According to Michelot  <mhostettler@voila.fr>:
> Une question, est-il facile en observant la structure f(X) d'un
> polynôme, de déterminer s'il est primitif ou pas ?

Il faut d'abord déterminer s'il est irréductible. Ça ne se voit pas
"à l'oeil" mais c'est algorithmiquement assez aisé. Ensuite, pour
déterminer s'il est primitif, il faut faire quelques exponentiations.
Par exemple, pour n = 11 et un polynôme irréductible, le groupe des
inversibles a pour cardinal 2047. Le groupe engendré par X a un
cardinal qui divise donc 2047 ; c'est donc 2047 lui-même (auquel cas
le polynôme est primitif), ou alors un des diviseurs stricts de 2047,
i.e. 23 et 89.

Du coup, il suffit de calculer X^23 et X^89 modulo le polynôme, pour
voir si ça donne 1 ou pas. Si aucune des deux exponentiations ne donne
1, alors l'ordre de X n'est ni 23, ni 89 ; c'est donc 2047.

Là encore, algorithmiquement, c'est facile, sous réserve d'avoir
une factorisation de 2^n-1 (ce qui n'est pas un vrai problème pour
les n de moins de 150).


Alors à la main, bof. Mais je me suis fait un petit programme pour ça,
il y a quelques temps. Le voilà :


/*
 * Enumerate irreducible polynomials in Z2[X].
 *
 * Compile with DEGREE defined to the required polynomial degree. This
 * value must lie between 3 and 20 (inclusive).
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

#ifndef DEGREE
#define DEGREE    11
#endif

#define N   (DEGREE + 1)

#if N < 4 || N > 20 || (UINT_MAX >> (N - 1)) == 0
#error DEGREE is out of range
#endif

/* ====================================================================== */

/*
 * Print a polynomial.
 */
static void
print2(unsigned x)
{
	int i, f;

	for (i = N - 1, f = 0; i >= 0; i --) {
		if (!(x & (1U << i)))
			continue;
		if (f)
			fputs(" + ", stdout);
		else
			f = 1;
		if (i == 0)
			putchar('1');
		else if (i == 1)
			putchar('X');
		else
			printf("X^%d", i);
	}
}

/*
 * Get the bit length of the provided number. 0 has bit length 0.
 */
static int
bitlen(unsigned x)
{
	int b = 0;

	if (x > 0x0000FFFF) { x >>= 16; b += 16; }
	if (x > 0x000000FF) { x >>= 8; b += 8; }
	if (x > 0x0000000F) { x >>= 4; b += 4; }
	if (x > 0x00000003) { x >>= 2; b += 2; }
	if (x > 0x00000001) { x >>= 1; b ++; }
	if (x > 0x00000000) { b ++; }
	return b;
}

/*
 * Reduce polynomial a modulo polynomial b.
 */
static unsigned
mod2(unsigned a, unsigned b)
{
	int an = bitlen(a), bn = bitlen(b), i;

	if (bn > an) {
		return a;
	}
	b <<= an - bn;
	for (i = an - bn; i >= 0; i --, b >>= 1) {
		if (a & (1U << (i + bn - 1)))
			a ^= b;
	}
	return a;
}

/*
 * Compute GCD of two polynomials.
 */
static unsigned
gcd2(unsigned a, unsigned b)
{
	while (b != 0) {
		unsigned t = mod2(a, b);

		a = b;
		b = t;
	}
	return a;
}

/*
 * Mutiply polynomial z by X modulo m (of degree mn-1)
 */
static unsigned
mulx2(unsigned z, unsigned m, int mn)
{
	z <<= 1;
	if (z & (1U << (mn - 1)))
		z ^= m;
	return z;
}

/*
 * Multiply two polynomials modulo m (of degree mn-1)
 */
static unsigned
mul2(unsigned a, unsigned b, unsigned m, int mn)
{
	unsigned u = a, v = 0U;
	int i, bn = bitlen(b);

	for (i = 0; i < bn; i ++) {
		if (b & (1U << i))
			v ^= u;
		u = mulx2(u, m, mn);
	}
	return v;
}

/*
 * Compute a^e modulo m of degree mn-1
 */
static unsigned
pexp2(unsigned a, unsigned e, unsigned m, int mn)
{
	unsigned u = a, v = 1U;

	while (e > 0) {
		if (e & 1U)
			v = mul2(v, u, m, mn);
		u = mul2(u, u, m, mn);
		e >>= 1;
	}
	return v;
}

/*
 * Check whether the provided polynomial is irreducible.
 */
static int
irred2(unsigned f)
{
	unsigned u = 2U;
	int i, fn;

	fn = bitlen(f);
	for (i = 0; i < (fn - 1) / 2; i ++) {
		u = mul2(u, u, f, fn);
		if (gcd2(f, u ^ 2U) != 1U)
			return 0;
	}
	return 1;
}

/*
 * These are the prime factors of 2^n-1 for n ranging from 0 to 20
 * (without multiplicity).
 */
static unsigned ofactors2[][6] = {
	{ 0, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 0, 0 },
	{ 3, 0, 0, 0, 0, 0 },
	{ 7, 0, 0, 0, 0, 0 },
	{ 3, 5, 0, 0, 0, 0 },
	{ 31, 0, 0, 0, 0, 0 },
	{ 3, 7, 0, 0, 0, 0 },
	{ 127, 0, 0, 0, 0, 0 },
	{ 3, 5, 17, 0, 0, 0 },
	{ 7, 73, 0, 0, 0, 0 },
	{ 3, 11, 31, 0, 0, 0 },
	{ 23, 89, 0, 0, 0, 0 },
	{ 3, 5, 7, 13, 0, 0 },
	{ 8191, 0, 0, 0, 0, 0 },
	{ 3, 43, 127, 0, 0, 0 },
	{ 7, 31, 151, 0, 0, 0 },
	{ 3, 5, 17, 257, 0, 0 },
	{ 131071, 0, 0, 0, 0, 0 },
	{ 3, 7, 19, 73, 0, 0 },
	{ 524287, 0, 0, 0, 0, 0 },
	{ 3, 5, 11, 31, 41, 0 }
};

/*
 * Check if f is primitive. This must be called only if f is known
 * to be irreducible.
 */
static int
primitive2(unsigned f)
{
	int i, fn = bitlen(f);
	unsigned go = (1U << (fn - 1)) - 1;

#if 0
	if (!irred2(f))
		return 0;
#endif
	for (i = 0; ofactors2[fn - 1][i] != 0; i ++) {
		unsigned e = go / ofactors2[fn - 1][i];

		if (e == 1)
			continue;
		if (pexp2(2U, e, f, fn) == 1U) {
			return 0;
		}
	}
	return 1;
}

/* ====================================================================== */

int
main(void)
{
	unsigned u;

	for (u = 1U << (N - 2); u < (1U << (N - 1)); u ++) {
		unsigned p = (u << 1) | 1U;

		if (irred2(p)) {
			print2(p);
			if (primitive2(p))
				printf(" (primitive)\n");
			else
				printf("\n");
		}
	}
	return 0;
}


DateSujet  Auteur
01.01.
o 
Groups Explorer contact votre avis comment ça marche? rechercher un groupe suggérer un groupe abuse accueil du site   Imprimer cette page   Envoyer cette page à un(e) ami(e)