Partage
  • Partager sur Facebook
  • Partager sur Twitter

Lecture de code

Sujet résolu
    4 février 2013 à 19:58:45

    Bonjour à vous, j'aimerai traduire un code écrit en python vers le langage Java. Seul problème, j'ai un peu de mal à lire du python. Quelqu'un pourrait-il me commencer chaque ligne de ce que fait le code ci-dessous ? ainsi que le type des valeurs en entrée/sortie des fonctions. J'ai souvent du mal avec le sucre syntaxe de python.

    from Crypto.Cipher import AES
    from Crypto.PublicKey import RSA
    from Crypto.Util import Counter
     
    import base64
    import binascii
    import json
    import os
    import random
    import struct
    import sys
    import urllib
     
    sid = ''
    seqno = random.randint(0, 0xFFFFFFFF)
     
    master_key = ''
    rsa_priv_key = ''
     
    def base64urldecode(data):
      data += '=='[(2 - len(data) * 3) % 4:]
      for search, replace in (('-', '+'), ('_', '/'), (',', '')):
        data = data.replace(search, replace)
      return base64.b64decode(data)
     
    def base64urlencode(data):
      data = base64.b64encode(data)
      for search, replace in (('+', '-'), ('/', '_'), ('=', '')):
        data = data.replace(search, replace)
      return data
     
    def a32_to_str(a):
      return struct.pack('>%dI' % len(a), *a)
     
    def a32_to_base64(a):
      return base64urlencode(a32_to_str(a))
     
    def str_to_a32(b):
      if len(b) % 4: # Add padding, we need a string with a length multiple of 4
        b += '\0' * (4 - len(b) % 4)
      return struct.unpack('>%dI' % (len(b) / 4), b)
     
    def base64_to_a32(s):
      return str_to_a32(base64urldecode(s))
     
    def aes_cbc_encrypt(data, key):
      encryptor = AES.new(key, AES.MODE_CBC, '\0' * 16)
      return encryptor.encrypt(data)
     
    def aes_cbc_decrypt(data, key):
      decryptor = AES.new(key, AES.MODE_CBC, '\0' * 16)
      return decryptor.decrypt(data)
     
    def aes_cbc_encrypt_a32(data, key):
      return str_to_a32(aes_cbc_encrypt(a32_to_str(data), a32_to_str(key)))
     
    def aes_cbc_decrypt_a32(data, key):
      return str_to_a32(aes_cbc_decrypt(a32_to_str(data), a32_to_str(key)))
     
    def stringhash(s, aeskey):
      s32 = str_to_a32(s)
      h32 = [0, 0, 0, 0]
      for i in xrange(len(s32)):
        h32[i % 4] ^= s32[i]
      for _ in xrange(0x4000):
        h32 = aes_cbc_encrypt_a32(h32, aeskey)
      return a32_to_base64((h32[0], h32[2]))
     
    def prepare_key(a):
      pkey = [0x93C467E3, 0x7DB0C7A4, 0xD1BE3F81, 0x0152CB56]
      for _ in xrange(0x10000):
        for j in xrange(0, len(a), 4):
          key = [0, 0, 0, 0]
          for i in xrange(4):
            if i + j < len(a):
              key[i] = a[i + j]
          pkey = aes_cbc_encrypt_a32(pkey, key)
      return pkey
     
    def encrypt_key(a, key):
      return sum((aes_cbc_encrypt_a32(a[i:i+4], key) for i in xrange(0, len(a), 4)), ())
     
    def decrypt_key(a, key):
      return sum((aes_cbc_decrypt_a32(a[i:i+4], key) for i in xrange(0, len(a), 4)), ())
     
    def mpi2int(s):
      return int(binascii.hexlify(s[2:]), 16)
     
    def get_chunks(size):
      chunks = {}
      p = pp = 0
      i = 1
     
      while i <= 8 and p < size - i * 0x20000:
        chunks[p] = i * 0x20000;
        pp = p
        p += chunks[p]
        i += 1
     
      while p < size:
        chunks[p] = 0x100000;
        pp = p
        p += chunks[p]
     
      chunks[pp] = size - pp
      if not chunks[pp]:
        del chunks[pp]
     
      return chunks


    Merci d'éclairer ma lanterne

    -
    Edité par willard <3 4 février 2013 à 20:31:47

    • Partager sur Facebook
    • Partager sur Twitter
    J'ai tous les badges d'OpenClassrooms.
      4 février 2013 à 22:10:43

      Tu es mauvais

      #Je ne vais pas détailer les modules, on verra au moment voulu
      
      #ceux là sont d'un package externe (PyCrypto)
      from Crypto.Cipher import AES
      from Crypto.PublicKey import RSA
      from Crypto.Util import Counter
      
      #ceux là de la lib standard
      import base64
      import binascii
      import json
      import os
      import random
      import struct
      import sys
      import urllib
        
      sid = ''                                # initialise une chaine de caractere vide, mais tu t'en doute, non ?
      seqno = random.randint(0, 0xFFFFFFFF)   # tire un nombre entier aléatoire entre 0 et  0xFFFFFFFF (les deux compris : 0 <= seqno <= 0xFFFFFFFF) 
      # bon je suppose que tu sais que 0xFFFFFFFF est un nombre en notation hexa... Mais je fais peut etre beaucoup de supposition là
        
      master_key = ''     # idem sid
      rsa_priv_key = ''   # idem sid
         
      def base64urldecode(data):
        # a priori data est une string(une url encodé en base64 je dirais même  )
        
        # Un peu bizarre la ligne suivante... 
        # En gros rajoute :
        #   * "==" à la fin de la chaine pour toutes les chaine dont la longueur est de la forme 4*N+2 (Chaine de longueur 2, 6, 10, ...)
        #   * "=" à la fin de la chaine pour toutes les chaine dont la longueur est de la forme 4*N+3 (Chaine de longueur 3, 7, 11, ...)
        #   * ne rajoute rien sinon...
        # Etrange car j'ai du mal à voir la logique mais c'est pas vraiment mon prob...
        data += '=='[(2 - len(data) * 3) % 4:]        
        
        # Les 2 lignes suivantes remplacent dans data :
        # Les «-» par des «+», les «_» par des «/» et supprime les «,»
        for search, replace in (('-', '+'), ('_', '/'), (',', '')):
          data = data.replace(search, replace)
        
        #decode et retourne 'data' considéré encodé en base64 ( RFC 3548 ) (une chaine de caractère donc)
        return base64.b64decode(data)
        
      def base64urlencode(data):
        # a priori data est une string (une url je dirais même  )
        
        # encode 'data' en base64 ( RFC 3548 )
        data = base64.b64encode(data)
        
        # Les 2 lignes suivantes remplacent dans data :
        # Les «+» par des «-», les «/» par des «_» et supprime les «=»
        for search, replace in (('+', '-'), ('/', '_'), ('=', '')):
          data = data.replace(search, replace)
        # et on retourne la chaine
        return data # (une chaine de caractère donc)
        
      def a32_to_str(a):
        # a est une liste d'entiers 
        
        # convertis tous les entiers en une longue chaine de caractères.
        # Chaque entier dans la liste est considéré comme un "unsigned int" de 32bits et est convertis en 4 caractères.
        # Tous les groupes de 4 caractères sont concaténés
        return struct.pack('>%dI' % len(a), *a)
        
      def a32_to_base64(a):
        # pas besoin de décrire ça, donc ? avec les fonctions precedentes
        return base64urlencode(a32_to_str(a))
        
      def str_to_a32(b):
        # Les lignes suivantes rajoutent des caractères nuls ('\0') à la fin pour que la chaine soit une chaine de longueur multiple de 4
        if len(b) % 4: # Add padding, we need a string with a length multiple of 4
          b += '\0' * (4 - len(b) % 4)
        # fait l'inverse de a32_to_str(). Chaque groupe de 4 caractères sont regroupés pour formés un mot de 32 bits interprété comme un unsigned int. 
        # On obtient donc une liste d'entiers, chaque entier etant le decodage de 4 caracteres
        return struct.unpack('>%dI' % (len(b) / 4), b)
        
      def base64_to_a32(s):
        # pas besoin de décrire ça, donc ? avec les fonctions precedentes
        return str_to_a32(base64urldecode(s))
        
      def aes_cbc_encrypt(data, key):
        # data est une chaine de caracteres à encoder, key la clé (chaine aussi). Depuis la doc :
        #   The secret key to use in the symmetric cipher. It must be 16 (AES-128), 24 (AES-192), or 32 (AES-256) bytes long.
        # le mode CBC :
        #   Cipher-Block Chaining (CBC). Each of the ciphertext blocks depends on the current and all previous plaintext blocks. An Initialization Vector (IV) is required.
        #   The IV is a data block to be transmitted to the receiver. The IV can be made public, but it must be authenticated by the receiver and it should be picked randomly.
        #   See NIST SP800-38A , Section 6.2 .
        # Je n'y connait pas grand chose en codage donc je te laisse interpreter ce "cryptage"
        encryptor = AES.new(key, AES.MODE_CBC, '\0' * 16)
        return encryptor.encrypt(data)
        
      def aes_cbc_decrypt(data, key):
        # Fait l'inverse de la fonction precedente
        decryptor = AES.new(key, AES.MODE_CBC, '\0' * 16)
        return decryptor.decrypt(data)
        
      def aes_cbc_encrypt_a32(data, key):
        # pareil que aes_cbc_encrypt mais les paremetres et le retour sont des suites d'entiers
        return str_to_a32(aes_cbc_encrypt(a32_to_str(data), a32_to_str(key)))
        
      def aes_cbc_decrypt_a32(data, key):
        # pareil que aes_cbc_decrypt mais les paremetres et le retour sont des suites d'entiers
        return str_to_a32(aes_cbc_decrypt(a32_to_str(data), a32_to_str(key)))
        
      def stringhash(s, aeskey):
        # Converti la chaine s en liste d'entiers
        s32 = str_to_a32(s)
        #initialisation...
        h32 = [0, 0, 0, 0]
        # Pour i allant de 0 à la taille de s32...
        for i in xrange(len(s32)):
          # ... L'élément (i modulo 4) de h32 est le XOR de sa valeur precedente avec l'entier numero i de s32
          h32[i % 4] ^= s32[i]
        # applique 16384 fois consécutivement un aes_cbc_encrypt_a32 depuis h32 avec la clé passé en paramètre
        for _ in xrange(0x4000):
          h32 = aes_cbc_encrypt_a32(h32, aeskey)
        # Renvois une chaine de 8 caractères à partir du decodage des entiers d'index 0 et 2 de h32
        return a32_to_base64((h32[0], h32[2]))
        
      def prepare_key(a):
        # a doit etre une liste d'entiers
        
        #initialisation...
        pkey = [0x93C467E3, 0x7DB0C7A4, 0xD1BE3F81, 0x0152CB56]
        # On applique 65536 fois la meme boucle
        for _ in xrange(0x10000):
          
          # Tous les 4 entiers...
          for j in xrange(0, len(a), 4):
            # On mets les 4 entiers dans "key"
            key = [0, 0, 0, 0]
            for i in xrange(4):
              if i + j < len(a):
                key[i] = a[i + j]
            # On encode "pkey" avec la "key" de 4 entiers formé juste avant qui devient la nouvelle "pkey"
            pkey = aes_cbc_encrypt_a32(pkey, key)
        return pkey
        
      def encrypt_key(a, key):
        # forme une liste concaténation de toutes les listes d'entiers renvoyé par aes_cbc_encrypt_a32 appliqué par paquet de 4 caractères
        return sum((aes_cbc_encrypt_a32(a[i:i+4], key) for i in xrange(0, len(a), 4)), ())
        
      def decrypt_key(a, key):
        # pareil que precedement, mais en appel avec aes_cbc_decrypt_a32
        return sum((aes_cbc_decrypt_a32(a[i:i+4], key) for i in xrange(0, len(a), 4)), ())
        
      def mpi2int(s):
        # s est une chaine de caractere
        # binascii.hexlify() va convertir tous les caractères, à partir du 2eme, un à un et les concaténer. 
        # Chaque conversion converti le caractère courant vers le nombre ascii correspondant sous forme de char.
        #  Donc '0' devient '30', '1' devient '31',... 'A' devient '41', 'm' devient '6D'
        # Donc binascii.hexlify(s[2:]) avec une chaine de la forme "??01Am" va devenir la chaine '3031416D'. (je te rappel que les 2 premiers caractères sont ignorés)
        
        # Enfin la chaine de caractere est interprété comme un nombre hexa et est converti en entier
        return int(binascii.hexlify(s[2:]), 16)
        
      def get_chunks(size):   # size est un entier
        chunks = {}           # chunks est un dictionnaire (a priori association entre un entier et un autre entier)
        p = pp = 0
        i = 1
        # Tu devrait le comprendre seul ces boucles, non ?
        while i <= 8 and p < size - i * 0x20000:
          chunks[p] = i * 0x20000;
          pp = p
          p += chunks[p]
          i += 1
        
        while p < size:
          chunks[p] = 0x100000;
          pp = p
          p += chunks[p]
        
        chunks[pp] = size - pp
        # Si chunks[pp] est nul, on le supprime du dico
        if not chunks[pp]:
          del chunks[pp]
        
        return chunks
      



      • Partager sur Facebook
      • Partager sur Twitter
        4 février 2013 à 22:39:24

        Je savais que je pouvais compter sur toi. Tu as fais tu très beau boulot, je devrais traduire normalement tout ça comme il faut
        • Partager sur Facebook
        • Partager sur Twitter
        J'ai tous les badges d'OpenClassrooms.
          5 février 2013 à 16:04:13

          La logique d'une évolution vertueuse aurait voulu que tu fisses la conversion inverse. :)

          -
          Edité par nohar 5 février 2013 à 16:33:09

          • Partager sur Facebook
          • Partager sur Twitter
          Zeste de Savoir, le site qui en a dans le citron !
            5 février 2013 à 17:00:15

            ouais enfin willard quoi !

            S'il avait un quelconque sens de la vertue, ça se saurait...

            -
            Edité par Dr. kristofjé 5 février 2013 à 17:06:30

            • Partager sur Facebook
            • Partager sur Twitter
              5 février 2013 à 17:14:12

              Je posterai le code converti une fois qu'ils sera fait hein.
              • Partager sur Facebook
              • Partager sur Twitter
              J'ai tous les badges d'OpenClassrooms.
                5 février 2013 à 17:57:34

                Qui aurait envie de traduire du Java en Python ???

                En plus tu aurais pu le donner à jython qui t'aurait fais ça gentiment en une ou deux micro seconde.

                • Partager sur Facebook
                • Partager sur Twitter
                I <3 Ge0 | nohar | Shig was here -> .
                Anonyme
                  5 février 2013 à 19:06:27

                  willard a écrit:

                  Je posterai le code converti une fois qu'ils sera fait hein.

                  Puisse-t-il avoir un soupçon de compassion à notre égare pour nous épargner. Amen !

                  -
                  Edité par Anonyme 5 février 2013 à 19:09:56

                  • Partager sur Facebook
                  • Partager sur Twitter
                    5 février 2013 à 19:21:58

                    Toshy62 a écrit:

                    En plus tu aurais pu le donner à jython qui t'aurait fais ça gentiment en une ou deux micro seconde.

                    Meme avec PyChrypto qui est une lib externe ?

                    Non mais wilalrd, je te l'ai fait pour que tu me doive quelques pintes de bières, mais je me passerais volontié du code Java hein

                    • Partager sur Facebook
                    • Partager sur Twitter
                      5 février 2013 à 20:21:05

                      kristofjé a écrit:

                      Meme avec PyChrypto qui est une lib externe ?

                      Visiblement écrite en C, d'ailleurs. M'étonnerait que Jython embarque le runtime de CPython...

                      • Partager sur Facebook
                      • Partager sur Twitter
                      Zeste de Savoir, le site qui en a dans le citron !
                        6 février 2013 à 10:34:44

                        oui c'est ce qui me faisait réagir. Pour moi Jython n'est qu'une reprise du Python sur la JVM, il utilise la syntaxe mais quoi d'autres ? Peut etre une partie de la lib standard (et encore?) mais je doute fortement qu'il soit compatible avec les modules externes natifs

                        • Partager sur Facebook
                        • Partager sur Twitter
                          6 février 2013 à 10:54:10

                          Il me semble (ça fait longtemps que j'ai pas consulté la mailing list) que la communauté fait un gros effort pour porter la majorité des modules de la bibliothèque standard en pur Python, quitte à proposer des alternatives en natif pour CPython (genre ElementTree vs. cElementTree), de façon à ne pas mettre trop de bâtons dans les roues à Pypy et Jython.

                          Je vois aussi Jython comme un compilo Python vers du bytecode Java.

                          Pour les bibliothèques externes en natif, je pense aussi que c'est mort.

                          -
                          Edité par nohar 6 février 2013 à 10:55:25

                          • Partager sur Facebook
                          • Partager sur Twitter
                          Zeste de Savoir, le site qui en a dans le citron !

                          Lecture de code

                          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                          × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                          • Editeur
                          • Markdown