【问题标题】:Matching Base64 encoded HMAC-SHA1 strings in iOS/Objective-c Ruby/Rails在 iOS/Objective-c Ruby/Rails 中匹配 Base64 编码的 HMAC-SHA1 字符串
【发布时间】:2014-03-03 21:44:28
【问题描述】:

我知道有很多关于将 NSData 转换为 NSString、将 NSData 转换为 Base64 编码字符串、生成 HMAC 等的帖子,但似乎没有一个回答如何在 iOS 和 Rails 中生成匹配的 Base64 编码 HMAC-SHA1 字符串。

使用下面的代码,签名不匹配。

iOS 代码:

NSString *secret = @"xxx";
NSString *data = @"http://someurl?someparams";
const char *cKey = [secret cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [data 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 *signature = [HMAC base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];

Rails 代码:

secret = "xxx";
data = "http://someurl?someparams";
hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('sha1'), secret.encode("ASCII"), data.encode("ASCII"))
signature = Base64.encode64(hmac)
puts "HMAC #{hmac}"
puts "Signature #{signature}"

iOS 输出:

HMAC <05651433 c9a3d449 5816ded7 80bef87f dc903e4a> 
Signature BWUUM8mj1ElYFt7XgL74f9yQPko=

轨道输出:

HMAC 05651433c9a3d4495816ded780bef87fdc903e4a
Signature MDU2NTE0MzNjOWEzZDQ0OTU4MTZkZWQ3ODBiZWY4N2ZkYzkwM2U0YQ==

使用以下代码,我可以让它们匹配。但这感觉很老套(在 iOS 端使用描述和字符串替换,在 Rails 中使用 chomp):

iOS 代码:

NSString *secret = @"xxx";
NSString *data = @"http://someurl?someparams";
const char *cKey = [secret cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [data 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 *HMACStr = [[HMAC description] stringByReplacingOccurrencesOfString:@"<" withString:@""];
HMACStr = [HMACStr stringByReplacingOccurrencesOfString:@">" withString:@""];
HMACStr = [HMACStr stringByReplacingOccurrencesOfString:@" " withString:@""];
HMAC = [HMACStr dataUsingEncoding:NSASCIIStringEncoding];
NSString *signature = [HMAC base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
NSLog(@"HMAC %@", [HMAC description]);
NSLog(@"Signature %@", signature);

Rails 代码:

secret = "xxx"
data = "http://someurl?someparams"
hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('sha1'), secret.encode("ASCII"), data.encode("ASCII"))
signature = Base64.encode64(hmac).chomp
puts "HMAC #{hmac}"
puts "Signature #{signature}"

iOS 输出:

HMAC <30353635 31343333 63396133 64343439 35383136 64656437 38306265 66383766 64633930 33653461> 
Signature MDU2NTE0MzNjOWEzZDQ0OTU4MTZkZWQ3ODBiZWY4N2ZkYzkwM2U0YQ== 

轨道输出:

HMAC 05651433c9a3d4495816ded780bef87fdc903e4a
Signature MDU2NTE0MzNjOWEzZDQ0OTU4MTZkZWQ3ODBiZWY4N2ZkYzkwM2U0YQ==

如何在不使用 hack 的情况下生成匹配的签名?

【问题讨论】:

标签: ios ruby-on-rails base64 hmac


【解决方案1】:

我不熟悉 Rails,但在我看来

hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('sha1'), secret.encode("ASCII"), data.encode("ASCII"))

将摘要计算为 十六进制字符串,而

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)];

将摘要计算为NSData 对象,它只是一个包装器 任意字节序列。

您可能应该更改 Rails 代码以将摘要计算为 字节,而不是十六进制字符串(也许使用digest 而不是hexdigest?)

【讨论】:

  • 谢谢!!使用 digest 而不是 hexdigest 有效。我不再需要在 iOS 端进行任何字符串替换等操作。我仍然需要在 Rails 上敲击签名以使其匹配。不知道为什么 base64 编码会在 rails 的末尾添加一个空格,而在 iOs 中却没有。
  • 看来OpenSSL::Digest::Digest 已被弃用:stackoverflow.com/questions/21184960/…
  • 替代已弃用的OpenSSL::Digest::Digest:stackoverflow.com/a/24904850/144088
猜你喜欢
  • 1970-01-01
  • 2012-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-19
  • 2018-08-03
  • 2013-05-22
相关资源
最近更新 更多