2013-01-05 90 views
1

我試圖從Objective C(CCHmac)和PHP(hash_hmac)實現HMAC驗證。我得到了不同的散列結果。有沒有人可以幫助我?我不知道爲什麼要得到不同的哈希結果?以下是我的代碼(Objective-c & PHP)供您參考。請!在目標C和PHP(hash_hmac)中生成的HMAC SHA-1哈希不匹配

PHP:

$APIConsumerSecret ="DcmzvkQC7Sno+lxnbDG0hTtZ0WTQn9T2T9DJxEmcB0"; 
$APIConsumerSecret = urlencode($APIConsumerSecret).'&'; 
$BaseString="GET&http%3A%2F%2Fboday.api.simppo.com%2Foauth%2Frequest_token&oauth_consumer_key%3DCN6W1I8E2CEWZJNQI2KA7KY3%26oauth_nonce%3DlxTSJL%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1357268295%26oauth_version%3D1.0"; 

echo base64_encode(hash_hmac('sha1',$BaseString,$APIConsumerSecret,true)); 

PHP結果:xJ5Ya4u4ghH4ugIieGIb9AcFpD0=

目標C

- (NSString*)flickr_oauthSignatureFor:(NSString*)dataString withKey:(NSString*)secret 
{ 
    NSData* secretData = [secret dataUsingEncoding:NSUTF8StringEncoding]; 
    NSData* stringData = [dataString dataUsingEncoding:NSUTF8StringEncoding]; 

    const void* keyBytes = [secretData bytes]; 
    const void* dataBytes = [stringData bytes]; 

    ///#define CC_SHA1_DIGEST_LENGTH 20   /* digest length in bytes */ 
    void* outs = malloc(CC_SHA1_DIGEST_LENGTH); 

    CCHmac(kCCHmacAlgSHA1, keyBytes, [secretData length], dataBytes, [stringData length], outs); 

    // Soluion 1 
    NSData* signatureData = [NSData dataWithBytesNoCopy:outs length:CC_SHA1_DIGEST_LENGTH freeWhenDone:YES]; 

    NSLog(@"D1-0: signatureData %@", signatureData); 
    NSLog(@"base64:%@", [signatureData base64EncodedString]); 

    return [signatureData base64EncodedString]; 
} 

Objective-C的結果:

D1-0: <59052771 e670a04b 3a2e87db 3d7965be 1aed112e> 
base64: WQUnceZwoEs6LofbPXllvhrtES4= 

回答

5

在該示例PHP是URL編碼,ObjectiveC不是。

最好從一個簡單的例子開始,短的字符串並跳過base64編碼,然後比較結果。當這項工作開始添加額外的操作,如url編碼和base 64.

對於PHP開始:echo hash_hmac('sha1','test string','secret');和objc一樣。

這是一個出發點是一致的PHP:

NSString* phpsignatureData = @"dd26bfddf122c1055d4cd5b054227727e1e3eecf"; 
NSLog(@"phpsignatureData: %@", phpsignatureData); 

NSData* secretData = [@"secret" dataUsingEncoding:NSUTF8StringEncoding]; 
NSData* stringData = [@"test string" dataUsingEncoding:NSUTF8StringEncoding]; 
NSMutableData *signatureData = [NSMutableData dataWithLength:CC_SHA1_DIGEST_LENGTH]; 
CCHmac(kCCHmacAlgSHA1, secretData.bytes, secretData.length, stringData.bytes, stringData.length, signatureData.mutableBytes); 

NSLog(@"secretData %@", secretData); 
NSLog(@"stringData %@", stringData); 
NSLog(@"signatureData %@", signatureData); 

的NSLog輸出:

phpsignatureData: dd26bfddf122c1055d4cd5b054227727e1e3eecf 
secretData <73656372 6574> 
stringData <74657374 20737472 696e67> 
signatureData <dd26bfdd f122c105 5d4cd5b0 54227727 e1e3eecf> 
+0

喜Zaph, 感謝您的幫助,我遵循你的建議從簡單的例子(短字符串,並跳過base64編碼)。我得到了根路線,我的baseEncode字符串中丟失了一個字符串「&」。到目前爲止,輸出是正確的,再次感謝您的幫助。 –

+0

知道了!非常感謝。 –

0

你可以試試這個:(目標C)

-(NSString *)DATA_TO_HeX_With_HmacDigestData:(NSData *)digestData{ 
    const unsigned char *dataBuffer = (const unsigned char *)[digestData bytes]; 
    NSUInteger   dataLength = [digestData length]; 
    NSMutableString  *hexString = [NSMutableString stringWithCapacity:(dataLength * 2)]; 
    for (int i = 0; i < dataLength; ++i) 
    { 
     [hexString appendFormat:@"%02x", (unsigned int)dataBuffer[i]]; 
    } 
    return [NSString stringWithString:hexString]; 
} 

-(NSString *)HMAC_CREATOR:(NSString *)str andKeyData:(NSData *)keyData { 

    NSData *signatureData = [str dataUsingEncoding:NSUTF8StringEncoding]; 
    uint8_t digest[CC_SHA256_DIGEST_LENGTH]={0}; 
    CCHmacContext context; 
    CCHmacInit(&context, kCCHmacAlgSHA256, keyData.bytes, keyData.length); 
    CCHmacUpdate(&context, signatureData.bytes, signatureData.length); 
    CCHmacFinal(&context, digest); 
    NSData *digestData = [NSData dataWithBytes:digest length:sizeof(digest)]; 
    return [self DATA_TO_HeX_With_HmacDigestData:digestData]; 
}