Я пишу клиент-серверный проект, которому нужна подпись. Я использую base64(hmac-sha1(key, data))
для создания подписи. Но у меня разные подписи между кодом Python и кодом objective-c:
get_signature('KEY', 'TEXT') //python get 'dAOnR2oXWP9xa4vUBdDvVXTpzQo='
[self hmacsha1:@"KEY" @"TEXT"] //obj-c get '7FH0NG0Ou4nb5luKUyjfrdWunos='
Различаются не только значения base64, но и значения дайджеста hmac-sha1. Я пытаюсь разобраться с моим другом в течение нескольких часов, но все равно не понимаю. В чем проблема моего кода?
Мой код на Python:
import hmac
import hashlib
import base64
def get_signature(key, msg):
return base64.b64encode(hmac.new(key, msg, hashlib.sha1).digest())
Код моего друга objective-c (скопируйте из образца кода Objective-C для 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;
}
РЕШЕНИЕ: Спасибо всем ниже. Но я не должен говорить вам, что настоящая причина в том, что я набрал «TE S T» в своей среде разработки Python, а в этом сообщении набрал «TE X T»: P
Чтобы не тратить ваше время зря, я провел несколько тестов и получил более приятное решение, основанное на ваших ответах:
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=
Вывод:
- Сообщение для подписи должно быть закодировано в строку utf-8 с обеих сторон.
- (Благодаря DJV) В python 3 все строки являются Unicode, поэтому их следует использовать с 'b' или bytearray (благодаря Бурхану Халиду) или закодирован в строку utf-8.
7FH0NG0Ou4nb5luKUyjfrdWunos=
на Python 2. Вы используете Python 3? - person dmg   schedule 14.03.2013get_signature(b'KEY', b'TEXT')
, посколькуstring
s - этоunicode
- person dmg   schedule 14.03.2013