我正在玩 iPhone 上的请求签名。我有一个简单的 PHP 脚本正在运行,它将根据标头中的签名验证传入的 JSON 数据(总而言之,它与两条腿的 OAuth 非常相似)。
以下 Obj-C 代码生成签名:
const char *cKey = [kConsumerSecret cStringUsingEncoding:NSUTF8StringEncoding];
const char *cData = [payload cStringUsingEncoding:NSUTF8StringEncoding];
NSLog(@"Payload: %s", cData);
unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
NSData *hmac = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
NSString *signature = [hmac base64EncodedString];
验证 PHP 代码如下所示:
$originalPayload = '{"name":"Ben’s iPhone"}'; // The message received from iOS
$hash = hash_hmac("sha256", $originalPayload, "Secret Key", TRUE);
$signature = strtr(base64_encode($hash), array('=' => '', '+' => '-', '/' => '_'));
使用 ASCII 字符时,这些函数可以正常工作。但是当它们包含 UTF-8 字符时,iOS 会根据以下内容计算签名:
Ben’s iPhone
虽然 PHP 计算它基于:
Ben\u2019s iPhone
使签名无效。我尝试了多种方法,但都没有产生任何结果。有谁知道如何解决这个问题?
备注:是的,我可以简单地使用 OAuth,但我只是对如何自己实现它感到好奇。
更新:我已将问题追踪到代码中的一部分,该部分修改了 PHP 代码中已解析的 JSON 数组。为了散列但不包含在正文中,我添加了包含 UTC 时间戳的临时索引“时间”。对原始数组的修改使 PHP 改变了字符表示(转义 UTF-8 字符)。只需附加时间戳即可。
尽管如此,这些功能应该产生相同的结果,不是吗?