2014-02-06 33 views
2

我知道有很多關於將NSData轉換爲NSString,NSData轉換爲Base64編碼字符串,生成HMAC等的帖子,但似乎沒有回覆在iOS和Rails中生成匹配的Base64編碼的HMAC-SHA1字符串。在iOS/Objective-C Ruby/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== 

如何在不使用黑客的情況下生成匹配的簽名?

+1

對於任何人尋求的解決方案,我已經發佈一個要點在這裏:https://gist.github.com/septerr/8851146 – septerr

回答

4

我不熟悉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?),而不是一個十六進制字符串

+0

謝謝!使用'digest'而不是'hexdigest'工作。我不再需要在iOS端進行任何字符串替換等。我仍然需要在Rails上簽名才能使它匹配。不知道爲什麼base64編碼在rails中最後添加空格,而不在iOs中。 – septerr