2012-05-30 62 views
4

我一直試圖在iOS上爲Facebook簽署的請求生成HMAC SHA256數週。我迫切需要幫助。Facebook簽名的請求爲iOS(HMAC SHA256)

Facebook簽名的請求包含兩部分,由句點分隔。第一部分是有效負載的HMAC256,第二部分是有效負載的Base64編碼的字符串。我只能重新創建第二部分。

 
vlXgu64BQGFSQrY0ZcJBZASMvYvTHu9GQ0YM9rjPSso.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsIjAiOiJwYXlsb2FkIn0 

我一直在使用下面的代碼,每個人都使用,但它產生不同的哈希:

#import <CommonCrypto/CommonHMAC.h> 
#import "NSData+Base64.h" 

+(NSString*) hmacForSecret:(NSString*)secret data:(NSString*)data { 

    const char *cKey = [secret cStringUsingEncoding:NSASCIIStringEncoding]; 
    const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding]; 
    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)]; 

    return [HMAC base64EncodedString]; 
} 

根據Facebook的文檔:當使用 https://developers.facebook.com/docs/authentication/signed_request/

正確HMAC256輸出應該是「祕密」作爲關鍵:

vlXgu64BQGFSQrY0ZcJBZASMvYvTHu9GQ0YM9rjPSso 

的有效載荷進行編碼:

{ 
    "algorithm": "HMAC-SHA256", 
    "0": "payload" 
} 

注意:您可以Base64編碼解碼簽名的請求,以獲得該有效載荷的第二部分。

+0

你是從哪裏得到簽名的請求?我似乎無法從Facebook iOS sdk – Tjirp

+0

@Tjirp找到它,它不包含在iOS SDK中。你必須自己生成它。以下是您將如何創建它的方法:https://developers.facebook.com/docs/authentication/signed_request/ –

回答

3

問題出在Base64編碼器上。它需要被編碼爲Base64Url看到: http://en.wikipedia.org/wiki/Base64#URL_applications

這裏的體改base64EncodedString類中的方法:

//NSData+Base64.h 
- (NSString *)base64EncodedString 
{ 
    size_t outputLength; 

    char *outputBuffer = NewBase64Encode([self bytes], [self length], true, &outputLength); 
    NSString *result = [[[NSString alloc] initWithBytes:outputBuffer length:outputLength encoding:NSASCIIStringEncoding] autorelease]; 
    free(outputBuffer); 

    NSString *b64PayloadClean = [[result componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]] componentsJoinedByString:@""]; 

    //do URL encoding by replacing "+" and "/" to "-" and "_" respectively 
    b64PayloadClean = [b64PayloadClean stringByReplacingOccurrencesOfString:@"=" withString:@""]; 
    b64PayloadClean = [b64PayloadClean stringByReplacingOccurrencesOfString:@"+" withString:@"-"]; 
    b64PayloadClean = [b64PayloadClean stringByReplacingOccurrencesOfString:@"/" withString:@"_"]; 

    return b64PayloadClean; 
}