2013-03-14 2 views
3

J'écris un projet client/serveur qui nécessite une signature. J'utilise base64(hmac-sha1(key, data)) pour générer une signature. Mais je suis arrivé différentes signatures entre code python et code c objectif:Pourquoi mon code python et objectif-c obtient-il un résultat hmac-sha1 différent?

get_signature('KEY', 'TEXT') //python get 'dAOnR2oXWP9xa4vUBdDvVXTpzQo=' 
[self hmacsha1:@"KEY" @"TEXT"] //obj-c get '7FH0NG0Ou4nb5luKUyjfrdWunos=' 

Non seulement les valeurs de base64 sont différentes, le HMAC-SHA1 valeurs sont différentes aussi. J'essaie de travailler avec mon ami pendant quelques heures, je ne comprends toujours pas. Où est le problème de mon code?

Mon code python:

import hmac 
import hashlib 
import base64 
def get_signature(key, msg): 
    return base64.b64encode(hmac.new(key, msg, hashlib.sha1).digest()) 

Mon ami de code c objectif (copie de Objective-C sample code for HMAC-SHA1):

(NSString *)hmac_sha1:(NSString *)key text:(NSString *)text{ 

    const char *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding]; 
    const char *cData = [text cStringUsingEncoding:NSASCIIStringEncoding]; 

    unsigned char cHMAC[CC_SHA1_DIGEST_LENGTH]; 
    CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData), cHMAC); 

    NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)]; 
    NSString *hash = [GTMBase64 stringByEncodingData:HMAC]; 
    return hash; 
} 

RESOLU: Merci pour tout le monde ci-dessous. Mais je ne dois vous dire que la vraie raison est que je tapais « TE S T » dans mon python IDE en typé « TE X T » dans ce post: P

Pour ne pas perdre votre temps, J'ai fait quelques tests et a obtenu une solution plus agréable, la base de vos réponses:

print get_signature('KEY', 'TEXT')       
# 7FH0NG0Ou4nb5luKUyjfrdWunos= 

print get_signature(bytearray('KEY'), bytearray('TEXT')) 
# 7FH0NG0Ou4nb5luKUyjfrdWunos= 

print get_signature('KEY', u'你好'.encode('utf-8')) # best solution, i think! 
# PxEm7Oibj7ijZ55ko7V3isSkD1Q= 

print get_signature('KEY', bytearray(u'你好'))   
# TypeError: unicode argument without an encoding 

print get_signature('KEY', u'你好')      
# UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128) 

print get_signature(u'KEY', 'TEXT')      
# TypeError: character mapping must return integer, None or unicode 

print get_signature(b'KEY', b'TEXT')      
# 7FH0NG0Ou4nb5luKUyjfrdWunos= 

Conclusion:

  1. Le message à la signature doit être codé à chaîne utf-8 avec les deux côtés.
  2. (Merci à DJV) En python 3, les chaînes sont toutes unicode, elles doivent donc être utilisées avec 'b', ou bytearray (grâce à Burhan Khalid), ou encodées en chaîne utf-8.
+0

Selon [ce site] (http://hash.online-convert.com/sha1-generator), votre ami est le bon – dmg

+0

Eh bien, c'était bizarre, votre code produit '7FH0NG0Ou4nb5luKUyjfrdWunos =' aussi bien sur Python 2. Êtes-vous en utilisant Python 3? – dmg

+2

Ok, dernier suivi. Si vous utilisez Python 3, vous devriez l'appeler comme 'get_signature (b'KEY ', b'TEXT')' comme 'string's sont' unicode' – dmg

Répondre

3

Votre ami a tout à fait raison, mais vous aussi (sorta). Votre fonction est complètement correcte à la fois dans Python 2 et Python 3. Cependant, votre appel est un peu erroné dans Python 3. Vous voyez, dans Python 3, strings sont unicode, donc afin de passer une chaîne ASCII (comme votre ami Objective C fait et comme vous le feriez en Python 2), vous devez appeler votre fonction avec:

get_signature(b'KEY', b'TEXT') 

afin de préciser que ces chaînes sont des chaînes bytes aka ASCII.

EDIT: Comme Burhan Khalid noté, la souplesse de le faire en Python 3 est soit appeler votre fonction comme ceci:

get_signature(key.encode('ascii'), test.encode('ascii')) 

ou le définir comme:

def get_signature(key, msg): 
    if(isinstance(key, str)): 
     key = key.encode('ascii') 
    if(isinstance(msg, str)): 
     msg = msg.encode('ascii') 
    return base64.b64encode(hmac.new(key, msg, hashlib.sha1).digest()) 
+2

Cette réponse est correcte, mais pour l'appliquer dans votre méthode, vous devrait utiliser 'bytearray (clé)' et 'bytearray (msg)' –

+0

merci! voir ma mise à jour ~ – clark

Questions connexes