Annonce

Réduire
Aucune annonce.

[C] Implémentation du chiffre de Vernam

Réduire
X
 
  • Filtre
  • Heure
  • Afficher
Tout nettoyer
nouveaux messages

  • [C] Implémentation du chiffre de Vernam

    Bonjour, Bonsoir

    Aujourd'hui je vais vous présenter mon implémentation en C du chiffre de Vernam ou l'opération XOR qui découle de ce chiffrement, j'y ai vraiment mis du plaisir à le faire, pour une fois :-), c'est une implémentation relativement simple, relativement oui, j'en ai chier pour en venir à bout.

    Donc pour présenter le chiffrement de Vernam c'est un algorithme de chiffrement tout bête qui est "incassable", "inviolable", que ce soit par bruteforce ou autre techniques version grand-maître du cryptanalyste.
    On part du fait qu'il est impossible de trouver les additions qui ont formés une somme d'un entier:

    ? + ? = 100 | Où le premier point d'interrogation est le message original, et l'autre point d'interrogation, le masque jetable/clé, et 100 le message chiffré. Comment est-ce possible ? C'est effectivement impossible de retrouver le message original du fait que toute les possibilités sont possiblement possibles:

    50+50 ; 51+49 ; 52+48 ; 53+47 ; etc...

    Plutôt bête non ? :-)

    Mais cependant on peut pas laisser un tel algorithme nous passer entre les doigts sans lui donner quelques (légers) désavantages.

    -Le masque/clé doit faire la même taille que le message original (oui, le chiffre de vernam est une opération bit à bit).

    -La clé doit être choisit aléatoirement.

    -Le masque/clé ne doit servir uniquement qu'une fois

    Et si on respecte scrupuleusement toutes ces conditions, on a le droit à une sécurité absolue, il parait.

    J'vous fait un exemple en live avec de l'ascii (non-étendu, de 0 à 127):

    On va prendre le chiffre à chiffrer M=1337 et la clé aléatoire (à 100%) C=FAAG , si on additionne ça (avec les correspondances décimales):

    49|51|51|55
    +
    70|65|65|71
    ___________
    119|116|116|126 , ce qui donne en ASCII: wtt~

    Et s'il venait que votre addition dépasse la table ascii, auquel vous auriez une addition comme ceci:

    49|51|51|105
    +
    70|65|65|71
    ___________
    119|116|116|176

    Ne vous inquiétez pas, nul besoin d'utiliser ascii étendu qui va jusqu'à 255, vous avez juste besoin de faire un modulo (ou une soustraction) du nombre maximum de caractères ascii ou de la norme sur laquelle vous travaillez, (si ça avait été du base64, un modulo 64 tout simplement) et en non étendu c'est 128, donc ça fait:

    176%128 = 48

    Maintenant place au code de mon implémentation, je doute qu'il soit digne d'un ingénieur informatique, donc n'hésitez pas à critiquer ou à me poser des questions si ça vous chagrine.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <string.h>
     
    /**Implémentation personnelle du chiffre de vernam**/
     
    int generate_mask(int len_c,unsigned char *mask)
    {
        srand (time(NULL));
        int i;
        for(i=0;i<len_c;++i)
            mask[i]=rand()% 255 + 1;   // clé aléatoire comprise entre 1 et 255, ascii étendu, d'où les unsigned char, les signed ne vont que jusqu'à +127 (ascii non étendu)
                                      //  je pars de 1 et pas de 0, parce qu'en ASCII, le 0 vaut NULL et si jme tape ça dans ma string, le C va penser que mon string est trop court ( :-) )                  
     
        mask[len_c]='\0';
     
        return 0;
    }
     
     
    int generate_encryption(unsigned char *cipher,unsigned char *mask,unsigned char *crypted,int len_c)
    {
     
        int i;
        for(i=0;i<len_c;++i)
           {
               if( (mask[i]+cipher[i]) > 255 ) // Le résultat de l'addition est-il plus grand que la table ?
                    crypted[i]=(mask[i]+cipher[i]) % 255; // si oui je fais un modulo
               else
                    crypted[i]=mask[i]+cipher[i]; // sinon je mets ça dans crypted sans modulo
           }
     
        crypted[len_c]='\0';
     
        return 0;
    }
     
    int main(int argc, char *argv[])
    {
    if(argc == 2)
       {
        int len_c=strlen(argv[1]);
        unsigned char *mask=(unsigned char *)malloc(sizeof(char)*len_c+1);
        unsigned char *crypted=(unsigned char *)malloc(sizeof(char)*len_c+1);
     
     
        generate_mask(len_c,mask);
     
        generate_encryption((unsigned char *)argv[1],mask,crypted,len_c);
     
        printf("Message: %s\n Mask: %s\n Crypted: %s\n",argv[1],mask,crypted);
        free(mask);
        free(crypted);
       }
     
    else
        fprintf(stderr,"Usage: ./<executable> <text to encrypt>");
    }
    Dernière modification par EpicOut, 28 août 2014, 03h22.

  • #2
    Sympa ! Merci pour le partage !

    petite remarque : dans cette portion de code =>
    for(i=0;i<len_c;++i)
    {
    if( (mask[i]+cipher[i]) > 255 ) // Le résultat de l'addition est-il plus grand que la table ?
    crypted[i]=(mask[i]+cipher[i]) % 255; // si oui je fais un modulo
    else
    crypted[i]=mask[i]+cipher[i]; // sinon je mets ça dans crypted sans modulo
    }
    il me semble que la condition est superflu (mais je peux me tromper). Ne suffit-il pas d'appliquer le modulo en permanence ?
    Si le résultat de
    mask[i]+cipher[i]
    est inférieur à 255 lui appliquer un modulo 255 ne le modifiera pas. Après niveau ressource, je sais pas ce qui est le plus lourd un "if else" ou un modulo.
    Mais bon c'est du chipotage !

    Commentaire


    • #3
      il me semble que la condition est superflu (mais je peux me tromper). Ne suffit-il pas d'appliquer le modulo en permanence ?
      Si,

      Pour le code je regarderais par la suite, mais en l'état il est pas testable et par défaut C89, il n'est pas compilable, donc faudrait donner l'info sur la norme avec laquelle on compile (C90?)

      Pour le reste je verrais, mais il y a sans doute mieux en jouant avec binaire + XOR, bref à plus

      Voilà ma solution,

      Code:
      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      #include <time.h>
      
      #define ASCII 62
      #define ALPHABET "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
      
      char *getMask(const char *s);
      char *cypher(const char *s);
      
      int main(int argc, char *argv[])
      {
          if (argc == 2)
          {
              char *res = cypher(argv[1]);
              printf("%s\n", res);
              free(res);
          }
      
          return 0;
      }
      
      char *getMask(const char *s)
      {
          size_t length = strlen(s);
      
          char *result = malloc(sizeof(char) * (length+1));
      
          int i, n;
      
          if (length == 0) return NULL;
      
          srand(time(NULL));
      
          for (i=0; s[i] != '\0'; i++)
          {
              n = rand() % ASCII;
              result[i] = ALPHABET[n];
          }
      
          result[i] = '\0';
      
          return result;
      }
      
      char *cypher(const char *s)
      {
          char *mask = getMask(s);
          size_t length = strlen(mask);
      
          char *res = malloc(sizeof(char) * (length+1));
      
          int i, c;
      
          for (i=0; i<(int)length; i++)
          {
              c = (s[i] + mask[i]) % ASCII;
              res[i] = ALPHABET[c];
          }
      
          res[i] = '\0';
      
          free(mask);
      
          return res;
      }
      Elle est simple mais surtout je pense ne posera jamais de problème car on aura toujours des caractères imprimables sur la console (variable ALPHABET).

      Par la suite je regarderais le code du PO, sachant qu'ici il est question de manipuler la mémoire avec malloc, les risques d'erreur sont doublés, voir triplés, je guetterais cela...

      EDIT: Code du PO gère bien la mémoire, pas de soucis à ce niveau, par contre la gestion des caractères spéciaux n'est pas faite ce qui sort forcément des sigles que la console ne peut lire.
      Dernière modification par fred, 29 août 2014, 16h09.

      Commentaire


      • #4
        belle version aussi ! J'ai tout compris ... c'est dire si c'est limpide.
        pour se passer de l'alphabet on pourrait peut-être, en restant sur l'idée du modulo, faire un c = (s[i] + mask[i]) % 93+33;
        Ce qui pourrait permettre d'obtenir tous les caractères affichables de la table ASCII non étendue.
        Une solution axée sur de la manipulation de bits est-elle possible ?

        Commentaire


        • #5
          Une solution axée sur de la manipulation de bits est-elle possible ?
          C'est sans doute possible, je ne suis pas à l'aise avec... Par contre la manipulation de bits sera plus rapide, mais j'en verrais pas trop l'intérêt sachant que même pour un texte très grand, c'est assez rapide.

          Si le cœur t'en dis, tu peux l'implémenter

          faire un c = (s[i] + mask[i]) % 93+33
          C'est pas gênant pour inclure les entiers ? Qui puis est 62 est plus sympa que 93 + 33, non?
          Dernière modification par fred, 29 août 2014, 08h52.

          Commentaire


          • #6
            C'est pas gênant pour inclure les entiers ?
            je vois pas vraiment où pourrait se situer le problème le code ascii des entiers est bien compris entre 33 et 126

            Qui puis est 62 est plus sympa que 93 + 33, non?
            Des gouts et des couleurs on ne discute pas.
            Après je préfère aussi un "% 93 +33" à l'ajout d'un tableau contenant toutes les lettres de mon alphabet.
            Encore une fois c'est du chipotage, je ne pense pas que du point de vu des ressources ça joue.

            Commentaire


            • #7
              Après je préfère aussi un "% 93 +33" à l'ajout d'un tableau contenant toutes les lettres de mon alphabet.
              Ce n'est plus le même code, mon alphabet n'est plus le tiens

              !"#$%&\'()*+,-./0123456789:;<=>[email protected][\\]^_`abcdefghijklmnopqrstuvwxyz{|}~
              Après pourquoi pas, seulement, ce n'est pas équivalent

              Encore une fois c'est du chipotage, je ne pense pas que du point de vu des ressources ça joue.
              Là c'est évident que ça ne joue pas effectivement

              Commentaire

              Chargement...
              X