60 votes

Convertir un long/int python en tableau d'octets de taille fixe

J'essaie d'implémenter l'échange de clés RC4 et DH en python. Le problème est que je n'ai aucune idée de la façon de convertir le long/int python de l'échange de clés en tableau d'octets dont j'ai besoin pour l'implémentation RC4. Existe-t-il un moyen simple de convertir un long en tableau d'octets de la longueur requise ?

Mise à jour J'ai oublié de mentionner que les nombres avec lesquels je travaille sont des entiers non signés de 768 bits.

0 votes

Je ne suis pas sûr que cela puisse vous aider, mais vérifiez la section struct module : docs.python.org/library/struct.html

7voto

Eduardo Ivanec Points 6244

Vous pouvez essayer d'utiliser struct :

import struct
struct.pack('L',longvalue)

1 votes

Malheureusement, non, erreur : l'entier est hors de portée pour le code de format 'L'. C'est un long 768 bits, ce qui est un peu plus grand que le unsigned int de 4 octets.

1 votes

Dévalorisé parce que les Python long int sont des entiers arbitrairement longs. Considérez-les comme un tableau d'entiers de 32 (ou plus) bits. Un long C est un type de données défini par sa taille. Avec cette réponse, vous confondez les deux.

7voto

scornwell Points 268

Little-endian, inversez le résultat ou la plage si vous voulez Big-endian :

def int_to_bytes(val, num_bytes):
    return [(val & (0xff << pos*8)) >> pos*8 for pos in range(num_bytes)]

Big-endian :

def int_to_bytes(val, num_bytes):
    return [(val & (0xff << pos*8)) >> pos*8 for pos in reversed(range(num_bytes))]

3voto

martineau Points 21665

Ce que vous devez faire, c'est convertir l'int/long dans sa représentation en base 256 -- c'est-à-dire un nombre dont les "chiffres" vont de 0 à 255. Voici un moyen assez efficace de faire quelque chose comme ça :

def base256_encode(n, minwidth=0): # int/long to byte array
    if n > 0:
        arr = []
        while n:
            n, rem = divmod(n, 256)
            arr.append(rem)
        b = bytearray(reversed(arr))
    elif n == 0:
        b = bytearray(b'\x00')
    else:
        raise ValueError

    if minwidth > 0 and len(b) < minwidth: # zero padding needed?
        b = (minwidth-len(b)) * '\x00' + b
    return b

Vous n'avez souvent pas besoin du reversed() en fonction du caractère endian souhaité (ce qui nécessiterait que le remplissage soit également effectué différemment). Notez également que tel qu'il est écrit, il ne gère pas les nombres négatifs.

Vous pouvez également jeter un coup d'œil sur le site similaire mais hautement optimisé de long_to_bytes() dans le number.py qui fait partie de l'application open source Boîte à outils de cryptographie Python . Il convertit en fait le nombre en une chaîne de caractères, et non en un tableau d'octets, mais c'est un problème mineur.

2voto

GP Eckersley Points 29

Python 2.7 n'implémente pas la méthode int.to- very slow_bytes().

J'ai essayé 3 méthodes :

  1. déballage/emballage de l'hexagone : très lent
  2. décalage d'octet 8 bits à la fois : nettement plus rapide.
  3. en utilisant un module "C" et en l'empaquetant dans les octets inférieurs (7 ia64 ou 3 i32). C'était environ deux fois plus rapide que 2/ . C'est l'option la plus rapide, mais elle est encore trop lente.

Toutes ces méthodes sont très inefficaces pour deux raisons :

  • Python 2.7 ne supporte pas cette opération utile.
  • c ne supporte pas l'arithmétique de précision étendue utilisant les drapeaux carry/borrow/overflow disponibles sur la plupart des plateformes.

0voto

user1025874 Points 157
i = 0x12345678
s = struct.pack('<I',i)
b = struct.unpack('BBBB',s)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X