Forum de mathématiques - Bibm@th.net
Vous n'êtes pas identifié(e).
- Contributions : Récentes | Sans réponse
#1 10-02-2009 10:33:24
- yoshi
- Modo Ferox
- Inscription : 20-11-2005
- Messages : 17 233
[Python] Cryptage : méthode de Che Guevara
Bonjour,
Suite à une demande "urgente" (?) sur le forum cryptographie je me suis attelé à la tâche...
Voir http://www.bibmath.net/crypto/moderne/che.php3.
Voici le résultat, la technique indiquée dans le document cité en référence (http://nicolasperdu.free.fr/for_crypto_rapport.pdf) comporte une difficulté : parfois les nombres de la table de transcodage ont 1 chiffre, parfois 2... Comment faire pour avoir un décodage "propre" sans allonger le nombre de lignes de programmation ?
J'ai pris le parti, lorsque le codage donne un nombre à 1 chiffre et non de 2 d'en mettre deux, en ajoutant un zéro devant et de doubler chaque espace : ainsi le décodage se fera facilement sur une boucle avec un pas de 2.
La table de transcodage est un peu différente du codage au décodage, pour un décodage plus rapide...
Codage :
# -*- coding: Latin-1 -*-
def prepare(PhraseEnClair):
li1=["âà","éèêë","îï","ô","ûü","ç","-","'"]
li2=["a","e","i","o","u","c"," "," "]
i=0
# Remplacement des caractères accentués éventuels, des traits d'union et des apostrophes
for mot in li1:
repl=li2[i]
for lettre in mot:
PhraseEnClair=PhraseEnClair.replace(lettre,repl)
i+=1
for lettre in ",;:!?.')(": # Suppression de la ponctuation
PhraseEnClair=PhraseEnClair.replace(lettre,"")
PhraseEnClair=PhraseEnClair.lower() # Passage en minuscules
return PhraseEnClair
Cle=[0,15,98,82,6,43,13,79,18,72,16,25]
LongCle=len(Cle)
TableTranscodage=[6,38,32,4,8,30,36,34,39,31,78,72,70,76,9,79,71,58,2,0,52,50,56,54,1,59]
MessageCrypt=""
MessageClair="L'urgence est une notion toute relative, n'est-ce-pas ?"
PhraseEnClair=prepare(MessageClair) # Je garde la trace du message d'origine avant retouches
LongPhraseEnClair=len(PhraseEnClair)
for i in range(LongPhraseEnClair):
CaractereClair=PhraseEnClair[i]
if CaractereClair == " ":
CaractereCode=" " # Remplacement d'une espace par deux
else:
if LongCle >= LongPhraseEnClair:
j=i
else:
j=i%LongCle
# Les indices de la table de transcodage doivent être compris entre 0 et 25
CaractereCode = (TableTranscodage[ord(CaractereClair)-97]+Cle[j])%100 # 97 code ASCII du a
# Si caractère codé sur 1 chiffre, ajout d'un 0 devant par passage en chaîne de caractères
if CaractereCode < 10:
CaractereCode ="0"+str(CaractereCode)
else:
CaractereCode=str(CaractereCode)
MessageCrypt+=CaractereCode
print " Message d'origine :" # non modifié
print MessageClair
print
print " Message crypté :"
print MessageCrypt
Décodage :
# -*- coding: Latin-1 -*-
Cle=[0,15,98,82,6,43,13,79,18,72,16,25]
LongCle=len(Cle)
TableTranscodage={6:'a',38:'b',32:'c',4:'d',8:'e',30:'f',36:'g',34:'h',39:'i',31:'j',78:'k',\
72:'l',70:'m',76:'n',9:'o',79:'p',71:'q',58:'r',2:'s',0:'t',52:'u',\
50:'v',56:'w',54:'x',1:'y',59:'z'}
MessageCrypt="72 50404251891126 242700 505814 898818112501 1507340651 \
3726442225396506 82 218118 4833 940484"
LongMessageCrypt=len(MessageCrypt)
MessageClair=""
for i in range(0,LongMessageCrypt,2): # Parcourt les caractères par pas de deux
Caractere=MessageCrypt[i:i+2]
if Caractere == " ": # Remplacement de deux espaces consécutifs par un seul
Caractere=" "
else:
if LongCle >= LongMessageCrypt:
j=i/2
else:
j=(i/2)%LongCle # Indice de position de la clé calculée modulo longueur de clé
CaractereCode = (int(Caractere)-Cle[j]+100)%100
Caractere=TableTranscodage[CaractereCode]
MessageClair+=Caractere
print " Message d'origine :" # non modifié
print MessageCrypt
print
print " Message crypté :"
print MessageClair
Questions/Commentaires ?
@+
Arx Tarpeia Capitoli proxima...
En ligne
#4 10-02-2009 14:23:31
- yoshi
- Modo Ferox
- Inscription : 20-11-2005
- Messages : 17 233
Re : [Python] Cryptage : méthode de Che Guevara
Salut,
Je ne connais pas JAVA, mais éventuellement FRED est notre spécialiste maison, ou Galdinx sont susceptibles de t'apporter un coup de main...
Alors, pour que tu fasses le travail de transcription tout seul de Python en Java ou alors que tu jettes un oeil du côté de Jython :
http://opikanoba.org/java/java-et-python.
En attendant, je vais détailler en français les points principaux des deux programmes.
Un point particulier de Python : il utilise un typage dynamique ; pas de besoin de déclarer une variable en chaîne, en entier long, court...
Donc :
1. Les saisies du texte et de la clé représentant une bonne part de pénibilité, je m'en suis abstenu : j'ai procédé par inclusion dans le code.
2. J'ai écrit un sous-programme prepare(texte) destiné à remplacer toutes les lettres accentuées par la minuscule correspondante, le trait d'union et l'apostrophe par des espaces, et les signes de ponctuation par rien.
3. Avant l'appel du sous-programme, je stocke la phrase d'origine dans une autre variable, de façon, à la fin, à la réafficher sans les modifs préparatoires au traitement.
4. Je démarre une boucle de 0 à Longueur de la phrase -1 ---> for i in range(LongPhraseEnClair):
5. Pas besoin de l'instruction classique (pour moi qui vient du BASIC : MID$), on extrait simplement de la chaîne nommée PhraseEnClair le caractère placé en position i ---> CaractereClair=PhraseEnClair[i] (comme si c'était un tableau)
6. Je teste CaractereClair : si c'est un espace, je le double et je file à la fin, dans le cas contraire je le traite.
7. Ensuite je prévois le cas (pas vraiment utile ?) où la longueur de la clé est >= à celle du texte et je ramène l'index de contrôle à i
8. Si la longueur de la Clé est inférieure alors l'index j de contrôle de position dans la clé ne doit pas excéder la longueur de la clé et repartir à 0 au delà : c'est le rôle j=i%LongCle % c'est modulo.
9. La table de transcodage est rangée dans une liste (un "tableau") répondant un index ramené entre 0 à 25 par soustraction de 97 (qui est le code ASCII du a) : je prends le code ASCII de la lettre par ord(CaractereClair) (en BASIC ou PASCAL ce doit être ASC(Caractere)) puis j'enlève 97. J'obtiens alors le code du CaractereClair auquel j'ajoute la clé correspondante et je ramène le tout modulo 100 ---> CaractereCode = (TableTranscodage[ord(CaractereClair)-97]+Cle[j])%100.
10. Ensuite, c'est ma petite nouveauté destinée à me simplifier la vie au décodage. Je teste le code obtenu pour savoir s'il est inférieur à 10 ou pas.
Si oui, je le tranforme en une chaîne et devant j'ajoute un 0..
Si non, je transforme directement en Chaîne.
11. Je concatène ensuite dans la variable chaîne MessageCrypt (déclarée vide au départ) chaque chaîne de deux caractères précédemment créée...
12. Enfin, affichage...
Ok ,
Décodage :
1. Les saisies du texte et de la clé représentant là aussi une bonne part de pénibilité, je m'en suis également abstenu abstenu : j'ai procédé par inclusion dans le code.
2. Petite nouveauté : la table de transcodage se présente comme un "dictionnaire", il me suffit de prendre comme index le nombre et il me renvoie la lettre correspondante. C'est là que s'est trouvée la "grosse" pierre d'achoppement dans la réalisation du module, une autre solution plus lourde aurait de créer une liste de 100 éléments, comprenant 26 lettres de a à z et 74 autres symboles tous identiques pour ne pas se casser la tête... Autre idée : ajouter 97 au code, puis 100 et de ramener le tout modulo 100 ne me donne que 6 pour a, Et j'ai encore besoin de savoir dans la table quelle position occupe ce 6... Donc, j'ai triché !
3. Je lance la boucle de 0 à Longueur du texte (s'arrête dans les faits à longueur -1) avec un pas de 2 ---> for i in range(0,LongMessageCrypt,2):
4. J'extrais les caractères par deux à la fois ---> Caractere=MessageCrypt[i:i+2]
5. Test de longueur : si Caractere est égal à deux espaces je le ramène à une.
6. De nouveau le test de longueur de clé pas vraiment utile puis je divise l'index i par 2 et je le ramène modulo LongCle : ---> j=(i/2)%LongCle
7. Ensuite je convertis le groupe de 2 caractères alphanumériques en nombre (via int), j'enlève la clé je rajoute 100 et je ramène le tout modulo 100
8. Maintenant, j'extrais de mon dictionnaire, la lettre correspondant au code obtenu ci-dessus. Ca peut se faire en une fois mais moins lisible :
---> Caractere=TableTranscodage[ (int(Caractere)-Cle[j]+100)%100]
9. Je concatène à la variable chaîne MessageClair (déclarée comme vide au début) ledit Caractere à chaque itération de la boucle.
10. Affichage.
Voilà, je pense avoir tout décrit dans le détail...
Questions ?
Bon courage,
@+
Arx Tarpeia Capitoli proxima...
En ligne
#6 11-02-2009 10:21:25
- hard
- Membre
- Inscription : 08-02-2009
- Messages : 10
Re : [Python] Cryptage : méthode de Che Guevara
voila le code j'espère que quelqu'un le corrige !!
public class Untitled1 {
public Untitled1() {
}
public static void main(String[] args) {
Untitled1 untitled11 = new Untitled1();
String text;
int tcle[] = { //stock le clé dans un tab
10, 16, 20};
int t[] = {}; //déclaration d'un tab
text = "ABCD"; //exemple du chaine a crypter
for (int i = 0; i < text.length()-1; i++) {
t[i] = text.charAt(i); //parcour du chaine et les stocké dans t
int textasc=(int) t[i]; //code ascii
}
for (int i = 0; i < t.length-1; i++) {
switch (text.charAt(i)) {
//tanscodage selon t[i]
case 65:
t[i] = 6;
break;
case 66:
t[i] = 38;
break;
case 67:
t[i] = 38;
break;
case 68:
t[i] = 4;
break;
default:
text = "jhkj";
break;
}
}
for (int i = 0; i < t.length-1; i++) {
for (int j = 0; i < tcle.length-1; j++) {
if (tcle.length >= t.length) { //si l taille du clé >= taille de text
j = i;
}
else { //si nn j repartie du 0
j=i%tcle.length;
}
t[i]=t[i]+tcle[j]; //ajout du clé
}
}
for (int i = 0; i < t.length-1; i++) // modulo 100
{
if (t[i]==100)
{
t[i]=0;
}
if (t[i]>100)
{
t[i]=t[i]%100;
}
if (t[i]<100)
{
t[i]=t[i];
}
}
//afiichage
}
}
Hors ligne
#7 11-02-2009 10:38:30
Re : [Python] Cryptage : méthode de Che Guevara
Bonjour,
J'y jetterai un coup d'oeil a l'occasion (je n'ai pas spécialement le temps en ce moment).
Cependant, ce qui me chagrine plus, c'est que tu as utilisé l'outil de transformation Jython et "Ca a l'air plein d'erreurs" ; le code de yoshi me semble aps d'une extrême complexité (l'algo peut être plus mais maintenant qu'il t'est donné sous forme python et même littéralement par la suite, tu n'as même plus besoin de réfléchir dessus) et je trouverais normal que tu cherches d'abord de ton coté les erreurs et que tu les corriges avant de nous donner en pâture un code buggué de partout. N'hésite pas a faire des tests de compilation, cela donne de nombreuses indication sur la nature des erreurs.
A++
Galdinx.
Hors ligne
#8 11-02-2009 10:49:11
- hard
- Membre
- Inscription : 08-02-2009
- Messages : 10
Re : [Python] Cryptage : méthode de Che Guevara
Bonjour,
J'y jetterai un coup d'oeil a l'occasion (je n'ai pas spécialement le temps en ce moment).
Cependant, ce qui me chagrine plus, c'est que tu as utilisé l'outil de transformation Jython et "Ca a l'air plein d'erreurs" ; le code de yoshi me semble aps d'une extrême complexité (l'algo peut être plus mais maintenant qu'il t'est donné sous forme python et même littéralement par la suite, tu n'as même plus besoin de réfléchir dessus) et je trouverais normal que tu cherches d'abord de ton coté les erreurs et que tu les corriges avant de nous donner en pâture un code buggué de partout. N'hésite pas a faire des tests de compilation, cela donne de nombreuses indication sur la nature des erreurs.
A++
Galdinx.
salut
j'ai po utilisé l'outil de transformation Jython! je sai po comment elle fonctionne! :(
Hors ligne
#9 11-02-2009 12:58:24
- yoshi
- Modo Ferox
- Inscription : 20-11-2005
- Messages : 17 233
Re : [Python] Cryptage : méthode de Che Guevara
Re,
Je plussoie Galdinx...
Les programmes en Python que je t'ai fournis reprennent une base déjà existante crée pour Code César,code masque jetable et pourtant ça n'a pas tourné du 1er coup...
Donc un seul conseil, élimine au départ toutes les complications dues à ma préparation de la phrase à coder pour traitement :
- Commence avec la phrase "attaquez asterix" en minuscules sans accents, ni ponctuation
- prends une clé courte
Code et lance le prgm et corrige un pb à la fois selon les messages d'erreur fournis...
Je ne saisis pas dans ton programme ton traitement du modulo... Le modulo fonctionne comme ça (tout seul) :
i% 5 0 1 2 3 4 0 1 2 3 4 0 1 2 3
Pas besoin de tester plusieurs cas...
D'autre part, tu utilises 3 boucles dont deux imbriquées là où je n'en utilise qu'une ?
for (int j = 0; i < tcle.length-1; j++) {
if (tcle.length >= t.length) { //si l taille du clé >= taille de text
j = i;
}
else { //si nn j repartie du 0
j=i%tcle.length;
}
t[i]=t[i]+tcle[j]; //ajout du clé
}
}
for (int i = 0; i < t.length-1; i++) // modulo 100
{
if (t[i]==100)
{
t[i]=0;
}
if (t[i]>100)
{
t[i]=t[i]%100;
}
if (t[i]<100)
{
t[i]=t[i];
}
A cause de l'extraction du caractère dans i-eme position dans une chaîne ? Il n'existe pas de mot-clé, de fonction pour ce faire ? Java étant un langage évolué, ça me surprend : voir http://www.netline.be/presse/inside_internet/java4.htm
@+
Arx Tarpeia Capitoli proxima...
En ligne
#11 13-02-2009 21:12:29
- yoshi
- Modo Ferox
- Inscription : 20-11-2005
- Messages : 17 233
Re : [Python] Cryptage : méthode de Che Guevara
Salut,
ok, c'est bien...
Mais à part ça, où en es-tu ?
Si ça peut t'aider je peux réduire mon code à son expression minimale... ? Quitte à l'enrichir par la suite, une fois sûr que le code marche : c'est ainsi d'ailleurs que souvent je procède.
@+
Arx Tarpeia Capitoli proxima...
En ligne
#12 13-02-2009 22:56:54
- hard
- Membre
- Inscription : 08-02-2009
- Messages : 10
Re : [Python] Cryptage : méthode de Che Guevara
salut
j'ai 1 blém sur ce code
String crypto="165016";
int taille=crypto.length();
String [] t= new String[taille];
for (int i=0,j=0; i<crypto.length()-1;i++,j++)
{
if(i==0){
c=crypto.substring(i,i+2);
t[i]=c;
}
else
{
c=crypto.substring(i,i+2);
t[i]=c;
}
}
for (int i=0; i<t.length;i++)
{
System.out.println(t[i]);
}
il m'affiche sa
16
65
50
01
16
null
mais j veuu que le pas de i=2 j veu affiché
16
50
16
Hors ligne
#13 14-02-2009 13:12:03
- yoshi
- Modo Ferox
- Inscription : 20-11-2005
- Messages : 17 233
Re : [Python] Cryptage : méthode de Che Guevara
Salut,
Voici le prog de codage réduit au strict minimum :
# -*- coding: Latin-1 -*-
Cle=[0,15,98,82,6,43,13,79,18,72,16,25]
LongCle=len(Cle)
TableTranscodage=[6,38,32,4,8,30,36,34,39,31,78,72,70,76,9,79,71,58,2,0,52,50,56,54,1,59]
MessageCrypt=""
PhraseEnClair="la notion d urgence est une notion toute relative n est ce pas"
LongPhraseEnClair=len(PhraseEnClair)
for i in range(LongPhraseEnClair):
CaractereClair=PhraseEnClair[i]
if CaractereClair == " ":
CaractereCode=" "
else:
j=i%LongCle
# On retire 97 : les indices de la table de transcodage doivent être compris entre 0 et 25
CaractereCode = (TableTranscodage[ord(CaractereClair)-97]+Cle[j])%100
if CaractereCode < 10:
CaractereCode ="0"+str(CaractereCode)
else:
CaractereCode=str(CaractereCode)
MessageCrypt+=CaractereCode
print " Message d'origine :" # non modifié
print PhraseEnClair
print
print " Message crypté :"
print MessageCrypt
Et celui de décryptage simplifié aussi :
# -*- coding: Latin-1 -*-
Cle=[0,15,98,82,6,43,13,79,18,72,16,25]
LongCle=len(Cle)
TableTranscodage={6:'a',38:'b',32:'c',4:'d',8:'e',30:'f',36:'g',34:'h',39:'i',31:'j',78:'k',\
72:'l',70:'m',76:'n',9:'o',79:'p',71:'q',58:'r',2:'s',0:'t',52:'u',\
50:'v',56:'w',54:'x',1:'y',59:'z'}
MessageCrypt="7221 581543528894 20 52733490827521 267416 529106 825213182748 2509679890 0121512472557508 74 144513 5080 040617"
LongMessageCrypt=len(MessageCrypt)
MessageClair=""
for i in range(0,LongMessageCrypt,2):
Caractere=MessageCrypt[i:i+2]
if Caractere == " ":
Caractere=" "
else:
j=(i/2)%LongCle
CaractereCode = (int(Caractere)-Cle[j]+100)%100
Caractere=TableTranscodage[CaractereCode]
MessageClair+=Caractere
print " Message d'origine :" # non modifié
print MessageCrypt
print
print " Message crypté :"
print MessageClair
Ca fonctionne, j'ai testé...
il m'affiche sa
16
65
50
01
16
null
A partir de quoi ? C'est du codage ?
mais j veuu que le pas de i=2 j veu affiché
16
50
16
Je ne comprends rien à t problème, évite le SMS quand on s'explique, ça complique les choses et ne donne pas envie d'aller plus loin...
1. Avec mon système, le pas de 2 est obligatoire au décodage, puisqu'au codage, chaque nombre est codé sur 2 caractères :
- un nombre à 1 chiffre est ramené à 2 en codant, puisque j'ajoute un 0 devant,
- une espace au codage est remplacé par deux pour la même raison : avoir 2 caractères...
2. Si j'ai bien compris l'affichage de 65 et de 01 est en trop : ces deux nombres correspondent à quoi ? Pourquoi apparaissent-ils ? Si ce sont des espaces, ils ne devraient pas apparaître...
@+
PS
J'ai vu : tu souhaites avoir un pas de 2 !
Bon, je ne connais pas les boucles java, mais je résume que i++ incrémente i de 1 à chaque passage, pas de 2 signifie qu'on incrémente i de 2 à chaque passage !
Quant à j++ pourquoi l'incrémenter dans la boucle ? Puisque j qui te sert à te déplacer dans la clé est fonction de i modulo longueurclé ?
Je présume que String crypto="165016" est la clé ?
Si oui, alors il te faut aussi te déplacer par pas de 2... C'est pour ça que j'avais rangé ma clé dans un tableau, ainsi cle[0] me donnait 16, cle[1] donnait 50 et cle[2] donnait 16.
Si ce n'est pas la clé mais une partie de ta table de transcodage : elle ne doit pas contenir 2 fois le même nombre de 0 à 100.
Si c'est un morceau de ton "cryptogramme", alors en revient à ce que j'ai écrit ci-dessus pour i++.
L'option step dans une boucle n'existe-t-elle pas en Java ?
PS2
Encore un point : le null m'interpelle : signifie-t-il que tu arrives en fin de fichier ? Qu'il y a un problème ? Vois-tu ceci me chiffonne : i<crypto.length()-1 il ne doit pas s'arrêter à n-2 mais à n-1 (et traiter n-1) : ainsi de 0 à n-1, il y a bien n items...
Essaie donc avec i<crypto.length(), ainsi il traitera crypto.length()-1 et sortira de la boucle en arrivant sur i==crypto.length() et non plus sur i==crypto.length()-1
Arx Tarpeia Capitoli proxima...
En ligne