我正在编写一个需要签名的客户端/服务器项目。我使用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代码(从HMAC-SHA1的Objective-C示例代码中复制而来):
(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=
结论:
- 要签名的消息应该使用双方都能识别的utf-8字符串进行编码。
- (感谢DJV)在Python 3中,字符串都是Unicode,因此应该使用“b”或bytearray(感谢Burhan Khalid),或编码为utf-8字符串。
7FH0NG0Ou4nb5luKUyjfrdWunos =
。你是在使用Python 3吗? - dmgget_signature(b'KEY', b'TEXT')
,因为string
是unicode
。 - dmg