2015-10-31 1 views
2

J'ai la ligne de code suivante:signe Python 3 un message avec SHA512 clés

return hmac.new(self.Secret.upper() , message , hashlib.sha512).digest().encode("base64").replace("\n","") 

Cela fonctionne très bien dans python2, mais pas en Python 3. Dès que je tente en Python 3, je suis:

TypeError: key: expected bytes or bytearray, but got 'str' 

de hmac.py. J'ai bien sûr essayé de convertir self.Secret et message en utilisant bytes() et bytearray(), mais cela n'a pas fonctionné non plus.

J'ai également essayé d'utiliser hashlib.sha512 pour générer la clé, mais ce n'est pas très clair pour moi. J'ai une clé API secrète qui doit être utilisée pour signer les données POST et la seule façon claire de le faire est d'utiliser hmac.new(), mais quand je reçois finalement quelque chose qui peut être passé sous forme de chaîne, il ne ressemble à rien, et comme prévu, je ne peux pas m'authentifier avec.

Une autre tentative a été:

sign = hashlib.sha512(message_to_sign) 
sign.update(self.Secret.upper()) 

Cela produit aussi une chaîne qui ne ressemble en rien la clé de travail qui vient du code d'origine en Python 2.7.

J'ai aussi essayé beaucoup d'autres variations, mais aucune d'entre elles ne me donne quelque chose qui fonctionne.

+0

En python3, hmac.new (**) accepte ** clé ** comme octets/bytearray, pas de chaîne (comme l'erreur suggérée, et différences entre py2 manipulant des chaînes/octets). Donc vous avez probablement besoin de le convertir comme 'bytes (self.Secret(). Upper()," utf-8 ")' ... – Anzel

+0

Oui, j'ai essayé ça. C'est ce que je voulais dire quand j'ai dit que j'avais essayé de les convertir. J'ai utilisé bytearray() et bytes(), mais pas non plus pour moi. Cependant, j'ai maintenant une clé de recherche valide, je ne suis pas sûr que ce soit correct parce que je n'utilise pas ma clé pour signer les données de publication. Je reçois également une nouvelle erreur de l'API concernant un nom d'en-tête invalide, ce qui n'a aucun sens puisque j'inclue seulement ceux qu'ils me disent d'utiliser. Cela arrive si j'utilise python-requests ou pycurl. –

Répondre

2

Celui-ci travaille pour moi python 3.4.2:

print((base64.b64encode(hmac.new(bytearray("SECRET".upper(), "ASCII") , bytearray("TEST","ASCII") , hashlib.sha512).digest())).decode("ASCII").replace("\n", "")) 

... et calcule un bon HMAC.

Vous souhaiterez peut-être remplacer "ASCII" par un autre codage.

+0

Enfin! J'y suis allé pendant des heures. Freaking ASCII, j'ai continué à essayer unicode et base64 sur tout, et seulement ASCII une fois. Merci beaucoup! –

+0

Je ne vois pas comment b64encode est justifié ici. Le code python2 ne le fait pas. Le codage doit correspondre à tous les autres bits de code qui vérifient la signature. – tdelaney

+0

Le code Python2 le fait, juste après digest() –

2

hmac Le hachage fonctionne avec des clés binaires et des données. Dans python2, str est une séquence de caractères de 8 bits qui est interchangeable avec binaire donc tout fonctionne. Dans python3, str est une séquence de caractères Unicode et doit être codé en binaire pour fonctionner. Cela devrait fonctionner:

return hmac.new(bytes(self.Secret.upper().encode('ascii')) , bytes(message.encode('ascii') , hashlib.sha512).digest().encode("base64").replace("\n","") 

Avis I utilisé ascii le codage, mais qui est juste une supposition. Vos chaînes python2 peuvent être votre page de codes locale et votre message peut déjà être un blob binaire. Vous devrez formaliser l'encodage utilisé pour que les destinataires sachent comment vérifier la signature.

+0

Oui, c'était le codage ascii. Merci! –

+0

'utf-8' peut être un meilleur choix à long terme, mais vous pouvez constater que les vieux trucs que vous avez déjà signés ne fonctionneront pas. – tdelaney