我正在编写需要签名的客户端/服务器项目。我使用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 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;
}
求助:谢谢以下所有人。但是我不必告诉你,真正的原因是我在我的python IDE中键入了“TE S T”,而在这篇帖子中输入了“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=
结论:
答案 0 :(得分:3)
你的朋友完全正确,但你也是(sorta)。你的函数在Python 2和Python 3中完全正确。但是,在Python 3中你的调用有点错误。你可以看到,在Python 3中,strings是unicode,所以为了传递一个ASCII字符串(如你的Objective C朋友和你在Python 2)中所做的一样,你需要通过以下方式调用你的函数:
get_signature(b'KEY', b'TEXT')
为了指定这些字符串是bytes a.k.a. ASCII字符串。
编辑:正如Burhan Khalid所述,在Python 3中执行此操作的灵活方法是调用您的函数:
get_signature(key.encode('ascii'), test.encode('ascii'))
或将其定义为:
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())