IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Contribuez Discussion :

Méthode d'utilisation d'openssl en shell pour cryptage massif de mots de passe


Sujet :

Contribuez

  1. #1
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 278
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 278
    Points : 12 726
    Points
    12 726
    Par défaut Méthode d'utilisation d'openssl en shell pour cryptage massif de mots de passe
    Bonjour,

    Ici, le but est d'avoir par exemple 10 millions de mots de passe à crypter avec openssl dont la commande d'exemple pour un seul mot de passe serait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    echo -n mot_de_passe | openssl enc -aes128 -a -iv d80667e915403ebf5abc787971e6edcd -K 9c2751a06ed8802cb11700498f09d5bd
    E01+Iy+idNeTbXNTyMmcSw==
    Pour les 10 millions de mots de passe, la méthode "naïve" serait par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    while read mdp
    do
      echo -n $mdp | openssl enc -aes128 -a -iv d80667e915403ebf5abc787971e6edcd -K 9c2751a06ed8802cb11700498f09d5bd
    done <mdp.txt >mdp.enc1
    ici, cela fonctionne, mais voyons la durée pour par exemple 1000 mots de passe:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $ wc -l mdp.txt 
    1000 mdp.txt
    $ time while read mdp; do echo -n $mdp | openssl enc -aes128 -a -iv d80667e915403ebf5abc787971e6edcd -K 9c2751a06ed8802cb11700498f09d5bd; done <mdp.txt >mdp.enc1
     
    real	0m9.924s
    user	0m4.356s
    sys	0m1.172s
    On est environ à 9 secondes (je suis gentil) pour 1000 mots de passe, comme ce genre d'algo est linéaire, on peut extrapoler, et dire qu'il faudrait 90 secondes pour 10.000, 900 secondes pour 100.000, 9000 secondes pour 1.000.000 et 90.000 secondes (25 heures) pour nos 10 millions.
    Bon, là, on est sur des temps un peu long, il serait bien de pouvoir réduire ce temps...
    Personnellement, après quelques recherches infructueuse sur le net, j'ai utilisé une autre forme d'écriture d'openssl qui m'a permit de gagner du temps.
    Le code est le suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    mkfifo in0 in1 out0 out1
    rm -f mdp.enc
    openssl < <(
     j=1
     while read mdp
     do
      x=$(( j++ % 2 ))
      echo "enc -aes128 -a -iv d80667e915403ebf5abc787971e6edcd -K 9c2751a06ed8802cb11700498f09d5bd -in in$x -out out$x"
      printf "%s" "$mdp" >in$x
      read res <out$x
      echo $res >>mdp.enc
     done <mdp.txt
    ) >/dev/null
    rm -f in0 in1 out0 out1
    Ce qui donne pour 1000 mot de passe à crypter:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    time { mkfifo in0 in1 out0 out1 ; rm -f mdp.enc ; openssl < <(j=1;while read mdp; do x=$(( j++ % 2 )); echo "enc -aes128 -a -iv d80667e915403ebf5abc787971e6edcd -K 9c2751a06ed8802cb11700498f09d5bd -in in$x -out out$x" ; printf "%s" "$mdp" >in$x ; read res <out$x ; echo $res >>mdp.enc ; done <mdp.txt ) >/dev/null ; rm -f in0 in1 out0 out1 ; }
     
    real	0m0.485s
    user	0m0.064s
    sys	0m0.068s
    Comme on peut le voir, si on extrapole, on passe de 90.000 secondes (25 heures) à 5000 secondes ( ~ 1 heure 30 minutes).

    Ce gain n'est dû qu'a une chose, la version naïve relance la commande openssl autant de fois qu'il y a de mots de passe à traiter tandis que la deuxième version ne lance qu'une seule fois openssl et lui dit de crypter autant de fois qu'il y a de mots de passe à traiter.
    Cordialement.

  2. #2
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 550
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 550
    Points : 19 383
    Points
    19 383
    Par défaut
    Bonjour,

    d'un peu plus d'une journée à moins de deux heures, c'est impressionnant !

    ce code me suggère néanmoins quelques interrogations :
    • les FIFO sont-ils indispensables ? le contenu des fichiers est écrasé à chaque tour de boucle, non ?
    • comment openssl a-t-il connaissance des données de in[0-1], alors que le fichier in* est écrit après l'envoi de la commande à openssl ?
    • pourquoi deux jeux de fichiers in-out ?
    • ne peut-on pas rediriger directement vers mdp.enc plutôt que vers /dev/null ?
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  3. #3
    Expert éminent Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 035
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 035
    Points : 8 400
    Points
    8 400
    Par défaut
    je proteste vigoureusement !

    alors ok, c'est spécifié dans le titre "en shell", mais pourquoi tant de haine ai-je envie de dire ?
    perso dans un cas comme celui là je n'hésite pas à sortir Perl ou Python immédiatement

    pour un fichier généré maison avec la méthode bash je tombe sur ~5min22s, là où un code python de quelques lignes fait le job en moins d'1s

    ledit code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    from Crypto.Cipher import AES
    from binascii import unhexlify
    from base64 import b64encode
     
    fichier = 'mdp.txt'
    key = unhexlify('9c2751a06ed8802cb11700498f09d5bd')
    iv = unhexlify('d80667e915403ebf5abc787971e6edcd')
     
    with open(fichier, 'r') as f:
       encryptor = AES.new(key, AES.MODE_CBC, IV=iv)
       for mdp in f:
          s = mdp.rstrip()
          i = 16 - len(s) % 16
          s += i * chr(i)  # padding, PKCS 5
          print b64encode(encryptor.encrypt(s))
    et l'exécution - excusez l’environnement PowerShell un peu moisi - :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    > Measure-Command { python .\bouzin.py > mdp.enc2 }
    (...)
    TotalMilliseconds : 912,1685

  4. #4
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 278
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 278
    Points : 12 726
    Points
    12 726
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    Bonjour,

    d'un peu plus d'une journée à moins de deux heures, c'est impressionnant !

    ce code me suggère néanmoins quelques interrogations :
    • les FIFO sont-ils indispensables ? le contenu des fichiers est écrasé à chaque tour de boucle, non ?
    • comment openssl a-t-il connaissance des données de in[0-1], alors que le fichier in* est écrit après l'envoi de la commande à openssl ?
    Oui, il est vrai que les fichiers sont écrasé à chaque tour de boucle, mais la particuliarité de la FIFO, c'est qu'elle est bloquante en lecture, ce qui bloque openssl le temps d'écrire dedans la donnée.
    • pourquoi deux jeux de fichiers in-out ?
    Ici, la raison n'est pas très claire, ce que je sais c'est que si on n'utilise qu'un seul jeu de fichiers in-out, on se retrouve dans une situation de "broken pipe" aléatoire et openssl reste bloqué.
    • ne peut-on pas rediriger directement vers mdp.enc plutôt que vers /dev/null ?
    Ici, la redirection est pour la sortie standart de openssl, qui est ni plus ni moins son prompt ( openssl> ), et on perdrait aussi du même coup l'attente du shell (toujours le bloquage FIFO) pour boucler sur le suivant.
    Cordialement.

  5. #5
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 278
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 278
    Points : 12 726
    Points
    12 726
    Par défaut
    Citation Envoyé par BufferBob Voir le message
    je proteste vigoureusement !

    alors ok, c'est spécifié dans le titre "en shell", mais pourquoi tant de haine ai-je envie de dire ?
    perso dans un cas comme celui là je n'hésite pas à sortir Perl ou Python immédiatement

    pour un fichier généré maison avec la méthode bash je tombe sur ~5min22s, là où un code python de quelques lignes fait le job en moins d'1s
    On est ok la-dessus, sauf quand tu n'as pas sur les machines, de quoi developper correctement, ici, le contexte pour en arriver à ça était:
    Un script en java qui a tourner environ 5 jours pour retourner un fichier contenant entre autre une donnée cryptée par lui-même mais avec de mauvais paramètres.
    Résultat: soit on corrige la bouse, puis on repart pour 5 jours, soit on corrige uniquement la donnée erronée.
    A l'équipe de dev java, il leur faut 3 jours pour developper le truc...
    On suggère de le faire comme tu dis en perl (ou pourquoi pas en python), mais bien sur, pas de module de cryptage installé pour perl ou python et il leur faut au moins une semaine pour installer ça ( et oui, vive les environnements professionnel ).
    Et bien sur, c'est urgent (que chez nous, sinon c'est pas marrant), et donc, pourquoi ne pas le faire avec openssl directement...
    Voila, la raison de se dev (qui n'a prit qu'une demi-journée, le temps de comprendre le fonctionnement d'openssl).

    Ici, je ne voulais que faire partager une solution en shell qui est largement plus viable que la forme naïve que l'on retrouve un peu partout sur le net.

    Et il y a aussi une morale à cette histoire: ne pas developper une commande qui ne fait qu'une chose unitaire et non sur un flux pour ensuite utiliser la dite commande pour faire du massif en la rappelant en boucle.
    Cordialement.

  6. #6
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 278
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 278
    Points : 12 726
    Points
    12 726
    Par défaut
    Un petit détail qui peut être important concernant l'exemple de BufferBob, celui-ci n'est qu'un exemple, on n'obtient pas le même crypt que la méthode proposée par openssl, et ceci même si on pad de la même manière.
    Mais cela ne retire rien sur sa remarque exemplaire (quand on peut le faire )
    Cordialement.

  7. #7
    Expert éminent Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 035
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 035
    Points : 8 400
    Points
    8 400
    Par défaut
    Citation Envoyé par disedorgue Voir le message
    on n'obtient pas le même crypt que la méthode proposée par openssl, et ceci même si on pad de la même manière.
    damned
    Nom : 276253_Papel-de-Parede-Meme-Jackie-Chan_1920x1200.jpg
Affichages : 810
Taille : 15,4 Ko

    après analyse rapide, y'a probablement un truc qui vautre quelque part, le 1er mdp est identique des deux côté, c'est à partir du 2ème que ça diffère, on peut envisager que côté openssl l'IV est réinitialisé/mis à jour à chaque mdp avec une dérivation du précédent, je vois que ça

    là où ça m'interroge plus encore c'est qu'ayant relancé la commande plusieurs fois pour en avoir le coeur net, le 1er mdp est systématiquement précédé des octets \xff\xfe, je ne peux que supposer qu'il s'agit d'une BOM qui se retrouve là à cause du redirecteur PowerShell, sinon je vois pas d'où ça peut provenir

    mea maxima culpa

    Edit: bon c'est avéré en fait il suffit de déplacer la ligne encryptor = AES.new(key, AES.MODE_CBC, IV=iv) dans la boucle for pour retomber sur ses pattes, je m'en vais tester sous un linux pour voir si le problème de BOM provient bien de mon env Win
    Edit2: confirmé, sous Linux on obtient bien le fichier attendu sans la BOM, et en moins d'un dixième de seconde (près de 10x plus vite que sous mon env Windows donc)

  8. #8
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 278
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 278
    Points : 12 726
    Points
    12 726
    Par défaut
    Allez, quelque détails supplémentaires:

    Si on utilise la version openssl en perl de l'AES:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    use Crypt::CBC;
    use MIME::Base64;
     
    my $cipher = Crypt::CBC->new(
        {
            'cipher'      => 'Crypt::OpenSSL::AES',
            'key'         => pack("H*",'9c2751a06ed8802cb11700498f09d5bd'),
            'iv'          => pack("H*",'d80667e915403ebf5abc787971e6edcd'),
            'literal_key' => 1,
            'header'      => 'none',
            'padding'     => 'none',
            keysize       => 16
        }
    );
     
    foreach (<>){
        chomp;
        my $result=$cipher->encrypt($_);
        print encode_base64($result);
    }
    Pour 1 millions de cryptage (sans padding: on dira qu'ils sont déjà faits), on obtient:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    real  0m48.101s
    user  0m47.608s
    sys   0m0.452s
    Pour python (code sans padding et sans passer par openssl):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    from Crypto.Cipher import AES
    from binascii import unhexlify
    from base64 import b64encode
     
    fichier = 'mdp_M.txt'
    key = unhexlify('9c2751a06ed8802cb11700498f09d5bd')
    iv = unhexlify('d80667e915403ebf5abc787971e6edcd')
     
    with open(fichier, 'r') as f:
       for mdp in f:
          encryptor = AES.new(key, AES.MODE_CBC, IV=iv)
          s = mdp.rstrip()
          print b64encode(encryptor.encrypt(s))
    On obtient:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    real  0m16.299s
    user  0m15.588s
    sys   0m0.308s
    Ici, on est bien plus rapide que openssl...
    Et une autre en perl, mais cette fois sans openssl:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    use MIME::Base64;
    use Crypt::Mode::CBC;
    my $m = Crypt::Mode::CBC->new('AES',0);
    my $key = pack("H*",'9c2751a06ed8802cb11700498f09d5bd');
    my $iv = pack("H*",'d80667e915403ebf5abc787971e6edcd');
    foreach (<>){
        chomp;
        $m->start_encrypt($key, $iv);
        my $ciphertext = $m->add($_);
        print encode_base64($ciphertext);
    }
    On obtient:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    real  0m11.882s
    user  0m11.256s
    sys   0m0.456s
    Pour ceux qui voudraient tester les codes donnés ou les réutiliser, comme je le disais précédemment, il faut que les données aient déjà le padding de calculés (la chaine doit être un multiple de 16 octets).

    Maintenant, il va falloir que j'arrive à faire mettre en prod, au moins le dernier module perl utilisé ici, même si au final, la version shell présentée au début de la discussion c'est executée en 10 minutes pour 30 Millions de données (en utilisant 16 cores en // )...
    Cordialement.

  9. #9
    Expert éminent Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 035
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 035
    Points : 8 400
    Points
    8 400
    Par défaut
    Citation Envoyé par disedorgue Voir le message
    Maintenant, il va falloir que j'arrive à faire mettre en prod
    du coup, t'es plus à 40s près

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème avec collate pour gérer la casse (mot de passe)
    Par bbr33 dans le forum Développement
    Réponses: 8
    Dernier message: 13/05/2015, 11h12
  2. [XL-2010] Utilisation de modules macro dans des feuilles protégées par mot de passe
    Par davimaje dans le forum Macros et VBA Excel
    Réponses: 32
    Dernier message: 14/11/2014, 17h32
  3. [PHP 5.3] Fonction mail pour une récupération de mot de passe
    Par ciols dans le forum Langage
    Réponses: 13
    Dernier message: 24/10/2013, 10h03
  4. Réponses: 7
    Dernier message: 24/03/2013, 15h08
  5. Script shell et stockage crypté de mot de passe
    Par macben dans le forum Linux
    Réponses: 7
    Dernier message: 11/11/2010, 00h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo