[maths]Cryptage de vigenère!

ViPHP
ViPHP | 3607 Messages

24 janv. 2007, 19:20

Bonjour à tous,
ne sacahnt que faire cet aprem, j'ai essayer de faire deux fonctions de cryptage/decryptage avec le chiffre de vigenère
j'ai donc lu l'article pour me raffarichire la mémoire sur la méthode utilisée...
et je ne voulais pas faire une méthode lourde avec un tableau à deux dimensions.... bref je tombe la-dessus!
Parfait ça à l'air d'être ce qu'il me faut!
je me met à coder une focntion de cryptage, et après un peu d'arrangement et tout et tout... j'aboutit à ceci:
function vigenere_crypt($texte,$cle){
    $tab=array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','_','.','@','-',' ','\'','"');
    $temp='';
    $j=0;
    for($i=0;$i<strlen($texte);$i++){
        $t=array_keys($tab,$texte{$i});
        $c=array_keys($tab,$cle{j});
        $temp.= $tab[($t[0]+$c[0])%count($tab)];
        $j=(($j<strlen($cle)) ? $j+1 : 0);
    }
    return $temp;
}
qui à l'air de fonctionner... (j'ai eu un peu de mal avec "l'additionnement" des lettres...)
bon maintenant je me dit j'ai fait le plus dur, j'inverse le processus, et tout devrait rouler, seulement, je sais exprimer une variable en fonctions d'autres variables dans beaucoups de cas....
mais pas lorsqu'il y a un modulo :? en gros ce que je souhaite, c'est pouvoir à partir de cette expressions:

Code : Tout sélectionner

TexteCodé = (TexteOriginal + Clé) % 26
pouvoir exprimé

Code : Tout sélectionner

TexteOriginal=....
mais là je bloque complet :shock:
merci d'avance à ceux qui aurait la bosse des maths ;-)

ViPHP
ViPHP | 3607 Messages

24 janv. 2007, 19:41

bon j'ai un peu avancé, mais je n'ai finallement que déplacé le problème...
j'ai transformé

Code : Tout sélectionner

TexteCodé = (TexteOriginal + Clé) % 26
en

Code : Tout sélectionner

TexteCodé = ( TexteOriginal + Clé) - 26 floor((TexteOriginal + Clé)/26)
Donc bon je peut sortir un TexteOriginal, mais il y en a un qui reste dans la fonction floor(), et j'arrive pas à exprimer floor(a/b) avec uniquement des +-/*....

Modérateur PHPfrance
Modérateur PHPfrance | 6373 Messages

24 janv. 2007, 23:56

Je dirais ça :

Code : Tout sélectionner

TexteDécodé = Clé % 26 + TexteCodé
Ta fonction doit pouvoir se simplifier un peu je pense. En tout cas, les noms ne sont pas très explicites, à mon avis dans un mois il faudra un petit temps de réflexion avant de se remettre dedans :P

ViPHP
ViPHP | 3607 Messages

25 janv. 2007, 12:04

Bonjour,
tout d'abord merci d'avoir cherché un peu ;-)
Mais visiblement ça ne fonctionne pas, voici le code que 'jai actuellement (j'ai changer les noms de variable :p )
function vigenere_crypt($texteOriginal,$cle){
    
    //liste des caractères autorisé
    $caracteres=array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','_','.','@','-',' ','\'','"');
    //longueur du tableau des caractères autorisé
    $longueurTabcaracteres=count($caracteres);
    //initialisation de la variable destinée à contenir le texte codé...
    $texteCode='';
    //initialisation de $j, compteur de la clé
    $j=0;
    //$longueur du texte original
    $longeurTexteOriginal=strlen($texteOriginal);
    
    //pour chaque lettre du texte original on effectue les calculs ci-dessous
    for($i=0;$i<$longeurTexteOriginal;$i++){
    
        //récupération des clés du tableau correspondant à la lettre courante du texte original et de la clé
        $key_texteOriginal=array_keys($caracteres,$texteOriginal{$i});
        $key_cle=array_keys($caracteres,$cle{$j});

        //Calcul de la correspondance
        $texteCode.= $caracteres[($key_texteOriginal[0]+$key_cle[0])%$longueurTabcaracteres];
        
        // si la clé est plus courte que le texte, on revient au début de la clé.
        $j=(($j<(strlen($cle)-1)) ? $j+1 : 0);
    }
    return $texteCode;
}

function vigenere_decrypt($texteCode,$cle){
    
    //liste des caractères autorisé
    $caracteres=array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','_','.','@','-',' ','\'','"');
    //longueur du tableau des caractères autorisé
    $longueurTabcaracteres=count($caracteres);
    //initialisation de la variable destinée à contenir le texte codé...
    $texteDecode='';
    //initialisation de $j, compteur de la clé
    $j=0;
    //$longueur du texte original
    $longeurTexteCode=strlen($texteCode);
    
    //pour chaque lettre du texte original on effectue les calculs ci-dessous
    for($i=0;$i<$longeurTexteCode;$i++){
    
        //récupération des clés du tableau correspondant à la lettre courante du texte original et de la clé
        $key_texteCode=array_keys($caracteres,$texteCode{$i});
        $key_cle=array_keys($caracteres,$cle{$j});
        
        //Calcul de la correspondance
        $texteDecode.= $caracteres[$key_cle[0]%$longueurTabcaracteres+$key_texteCode[0]];
        
        // si la clé est plus courte que le texte, on revient au début de la clé.
        $j=(($j<(strlen($cle)-1)) ? $j+1 : 0);
    }
    return $texteDecode;
}

$code=vigenere_crypt('Je m\'appelle louis','roi');
$decode=vigenere_decrypt($code,'roi');
echo "texte codé: ".$code."<br />texte décodé: ".$decode;
Donc la première fonctione m'a toujours l'air correcte, elle renvoi le même nombre de caractères en tout cas... mais la seconde... ne va pas du tout je pense qu'il y a des "sorties de tableau"...
je vois mal comment je vais résoudre mon problème...

ViPHP
ViPHP | 3607 Messages

25 janv. 2007, 15:05

bon j'ai changer un peu mes fonctions..
j'ai étendue mes caractères à la table ascii (de 0 à 255)
voici ce que ça donne:
function vigenere_crypt($texteOriginal,$cle){
    
    //longueur du tableau des caractères autorisé
    $longueurTabcaracteres=255;
    //initialisation de la variable destinée à contenir le texte codé...
    $texteCode='';
    //initialisation de $j, compteur de la clé
    $j=0;
    //$longueur du texte original
    $longeurTexteOriginal=strlen($texteOriginal);
    
    //pour chaque lettre du texte original on effectue les calculs ci-dessous
    for($i=0;$i<$longeurTexteOriginal;$i++){

        //Calcul de la correspondance
        $texteCode.= chr((ord($texteOriginal{$i})+ord($cle{$j}))%$longueurTabcaracteres);
        
        // si la clé est plus courte que le texte, on revient au début de la clé.
        $j=(($j<(strlen($cle)-1)) ? $j+1 : 0);
    }
    return $texteCode;
}

function vigenere_decrypt($texteCode,$cle){
    
    //longueur du tableau des caractères autorisé
    $longueurTabcaracteres=255;
    //initialisation de la variable destinée à contenir le texte codé...
    $texteDecode='';
    //initialisation de $j, compteur de la clé
    $j=0;
    //$longueur du texte original
    $longeurTexteCode=strlen($texteCode);
    
    //pour chaque lettre du texte original on effectue les calculs ci-dessous
    for($i=0;$i<$longeurTexteCode;$i++){
    
        
        //Calcul de la correspondance
        $texteDecode.= chr( ord($cle{$j}) % $longueurTabcaracteres  + $texteCode{$i});
        
        // si la clé est plus courte que le texte, on revient au début de la clé.
        $j=(($j<(strlen($cle)-1)) ? $j+1 : 0);
    }
    return $texteDecode;
}
Bon la fonction de décryptage ne fonctionne toujours pas ^^'
et je pense que c'est le calcul qui est mauvais, j'en viens à me demander si il est seulement possible d'exprimer mon calcul comme je le souhaite... :roll:

ViPHP
ViPHP | 3607 Messages

25 janv. 2007, 15:25

mauvaise nouvelle :cry:
Je viens de penser à utiliser ma calculatrice formelle (ti-89)...
j'ai donc rentré

Code : Tout sélectionner

solve(x=mod(y+z,255),y)
ce qui veut dire résoud moi l'équation x = (y+z)%255, en fonction de y.
Et bien aucun résultats.... :cry:
donc si la calculette ne sait pas faire, c'est que soit ça n'est pas possible, soit c'est extrêmement difficile (en tout cas trop pour moi...).
Je vais donc retourner voir le carré de vigenère

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

25 janv. 2007, 16:08

Normal que ta calculatrice t'envoi promener : il est impossible de retrouver ta valeur initiale, le modulo n'a pas de fonction inverse.

4 % 3 = 1
7 % 3 = 1
10 % 3 = 1
...

Comment veux-tu pouvoir retrouver le nombre initial à partir du reste (=1) et du modulo (=3), il y a une infinité de possibilité :)

Je ne me souviens plus bien du fonctionnement du cryptage, mais de mémoire c'était juste un décallage de n lettres en plus et il te suffisait de connaitre N pour le décoder... je vais jeter un coup d'oeil à tes liens
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Modérateur PHPfrance
Modérateur PHPfrance | 6373 Messages

25 janv. 2007, 16:22

En même temps, tu conclus que le calcul est mauvais mais comment peux-tu savoir ?

Ta fonction ne marche pas avec l'alphabet, et hop toi tu étends ça à tout l'ascii :lol:

Pourquoi faire simple quand on peut faire compliqué hein ;)

ViPHP
ViPHP | 3607 Messages

25 janv. 2007, 17:26

En même temps, tu conclus que le calcul est mauvais mais comment peux-tu savoir ?
parce que

MessagePosté le: 25 Jan 2007, 15:08 Sujet du message:
Normal que ta calculatrice t'envoi promener : il est impossible de retrouver ta valeur initiale, le modulo n'a pas de fonction inverse.

4 % 3 = 1
7 % 3 = 1
10 % 3 = 1
...

Comment veux-tu pouvoir retrouver le nombre initial à partir du reste (=1) et du modulo (=3), il y a une infinité de possibilité Smile
:-)
Bon du coup vos différents post m'ont fait me rendre compte qu'il est possible de crypter un texte par une formule mathématique, mais pas de le décrypter....(je parle pour la méthode de vigenère)
Il va donc falloir que je me rabate sur la méthode traditionnelle, c'est à dire construire un grand tableau à deux dimensions... etc etc.
Je regarde ça et je vous tient au courant ;-)

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

25 janv. 2007, 18:01

Euh ben non... tu peux très bien crypter et décrypter avec Vigenère.. c'est juste ton histoire de modulo qu'à rien à faire là :)

C'est un cryptage tout simple qui consiste à décaler chaque lettre affichée de 1 (A) à 26 (Z) positions
(et toujours du même nombre tant que t'es pas arrivé au bout de ton message ! ;)).

Le décryptage consiste en l'opération inverse, au lieu de décaler de +5, tu décales de -5 et le tour est joué :)

Je t'ai écrit une fonction de cryptage et de décryptage selon ce principe, en fait je suis quasiment retombé sur la première que tu as posté.
Mais tu as mal compris l'usage du modulo, il sert en effet à gérer les dépassements dans le tableau lors du cryptage,
et il faut bricoler un truc pour faire de même dans l'autre sens (valeur négatives) lors du décryptage :)

C'est fait alors, cadooooo ;)
$alphabet = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z');

function vig_crypt($str, $cle) {
	global $alphabet;

	$str = strToLower($str);

	$newStr = '';
	for($i=0;$i<strlen($str);$i++){
		// recherche la position dans le tableau de la lettre $str{$i}
		$position = array_search($str{$i}, $alphabet);
		if($position!==FALSE) {
			// détermine la lettre de remplacement
			$newPosition = ($position + $cle) % count($alphabet); // le modulo permet de gérer les dépassement
			$newStr.= $alphabet[$newPosition];
		}
		else // caractère non alphabétique (non présent dans le tableau)
			$newStr.= $str{$i};
	}
	return $newStr;
}

function vig_decrypt($str, $cle) {
	global $alphabet;

	$str = strToLower($str);

	$newStr = '';
	for($i=0;$i<strlen($str);$i++){
		// recherche la position dans le tableau de la lettre $str{$i}
		$position = array_search($str{$i}, $alphabet);
		if($position!==FALSE) {
			// détermine la lettre de remplacement
			$newPosition = $position - $cle;
			while ($newPosition < 0) { // gestion des dépassement
				$newPosition = count($alphabet) + $newPosition;
			}
			$newStr.= $alphabet[$newPosition];
		}
		else // caractère non alphabétique (non présent dans le tableau)
			$newStr.= $str{$i};
	}
	return $newStr;
}


$str = 'Hello World';
$crypt = vig_crypt($str, 5);
echo $crypt; // affiche 'mjqqt btwqi'
$decrypt = vig_decrypt($crypt, 5);
echo $decrypt; // affiche 'hello wolrd'
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Modérateur PHPfrance
Modérateur PHPfrance | 6373 Messages

25 janv. 2007, 18:40

Mon calcul semblait marcher chez moi :|

ViPHP
ViPHP | 3607 Messages

25 janv. 2007, 19:15

rebonsoir!
Bon en fait, j'ai pas étudié à fond ta solution à fond Ryle... Mais c'est plutôt le cryptage de césar que tu appliques là... et la différences est que pour le chiffre de vigenère, la clé varie en quelque sorte...
Je tache de faire un court exemple pour te montrer...

ViPHP
ViPHP | 3607 Messages

25 janv. 2007, 19:38

ayé!!
j'ai une version simplifiée du script...
pour un alphabet réduit aux 6 lettres abcdef.
voici le script qui fonctionne:
$carreVigenere = array(
                    'a'=>array('a','b','c','d','e','f'),
                    'b'=>array('b','c','d','e','f','a'),
                    'c'=>array('c','d','e','f','a','b'),
                    'd'=>array('d','e','f','a','b','c'),
                    'e'=>array('e','f','a','b','c','d'),
                    'f'=>array('f','a','b','c','d','e')
                );

function vig_crypt($texteaCrypter,$Cle){
    global $carreVigenere;
    $texteCrypter=='';
    $j=0;
    for($i=0;$i<strlen($texteaCrypter);$i++){
    
        // on cherche la position de la lettre du texte à crypter dans la première ligne
        $key=array_keys($carreVigenere['a'],$texteaCrypter{$i});
        
        //on "descend" à la ligne correspondant à la lettre de la cle et ça nous donne la lettre cryptée
        $texteCrypter.=$carreVigenere[$Cle{$j}][$key[0]];
        
        //gestion de la rotation de la clé
        $j=(($j<(strlen($Cle)-1)) ? $j+1 : 0);
    }
    return $texteCrypter;
}

function vig_decrypt($texteaDecrypter,$Cle){
    global $carreVigenere;
    $texteDecrypter='';
    $j=0;
    for($i=0;$i<strlen($texteaDecrypter);$i++){
        
        //on cherche la position de la lettre du texte crypté dans la ligne correspondant à la lettre de la clé
        $key=array_keys($carreVigenere[$Cle{$j}],$texteaDecrypter{$i});
        
        // on "remonte" à la première ligne et ça nous donne la lettre décryptée
        $texteDecrypter.=$carreVigenere['a'][$key[0]];
        
        //rotation de la clé
        $j=(($j<(strlen($Cle)-1)) ? $j+1 : 0);
    }
    return $texteDecrypter;
}

$texte='fabce';
$cle='cd';

echo 'Texte d\'origine: '.$texte.'<br />';
$crypt=vig_crypt('fabce','cd');
echo 'Texte crypté: '.$crypt.'<br />';
echo 'Texte décrypté: '.vig_decrypt($crypt,$cle);
l'inconvénient que je trouve à cette solution, c'est que pour un alphabet plus important, ça fait vite un $carreVigenere lourd...
Mais j'ai une petite idée...
Si j'étend l'alphabet à toute la table ascii, les positions des lettres que je cherche avec array_keys... seront disponible imédiatement...,
je n'aurai pas non plus à faire un tableau associatif, car l'indice des sous-tableau correspondra à un code ascii...
à suivre pour la version complete ;-)

ViPHP
ViPHP | 3607 Messages

25 janv. 2007, 19:52

Re AYé!!!
j'ai fait le même script que précédemment mais étendue à toute la table ascii...
le voici:
$carreVigenere=array();
for($i=0;$i<=255;$i++){
    $carreVigenere[$i]=array();
    $x=$i;
    for($j=0;$j<=255;$j++){
        $carreVigenere[$i][]=chr($x);
        $x=(($x<255) ? $x+1 : 0);
    }
}

function vig_crypt($texteaCrypter,$Cle){
    global $carreVigenere;
    $texteCrypter=='';
    $j=0;
    for($i=0;$i<strlen($texteaCrypter);$i++){
        
        //on "descend" à la ligne correspondant à la lettre de la cle et ça nous donne la lettre cryptée
        $texteCrypter.=$carreVigenere[ord($Cle{$j})][ord($texteaCrypter{$i})];
        
        //gestion de la rotation de la clé
        $j=(($j<(strlen($Cle)-1)) ? $j+1 : 0);
    }
    return $texteCrypter;
}

function vig_decrypt($texteaDecrypter,$Cle){
    global $carreVigenere;
    $texteDecrypter='';
    $j=0;
    for($i=0;$i<strlen($texteaDecrypter);$i++){
        
        //on cherche la position de la lettre du texte crypté dans la ligne correspondant à la lettre de la clé
        $key=array_keys($carreVigenere[ord($Cle{$j})],$texteaDecrypter{$i});
        
        // on "remonte" à la première ligne et ça nous donne la lettre décryptée
        $texteDecrypter.=$carreVigenere[0][$key[0]];
        
        //rotation de la clé
        $j=(($j<(strlen($Cle)-1)) ? $j+1 : 0);
    }
    return $texteDecrypter;
}

$texte='Bonjour je m\'appelle Pablo!';
$cle='picasso';

echo 'Texte d\'origine: '.$texte.'<br />';
$crypt=vig_crypt($texte,$cle);
echo 'Texte crypté: '.$crypt.'<br />';
echo 'Texte décrypté: '.vig_decrypt($crypt,$cle);
La seule lenteur, c'est la génération du tableau et les dernier array_keys que je n'arrive pas à enlever...
Voilà!