簡體   English   中英

HMAC - 在Objective-C中實現PHP算法

[英]HMAC - Implementation of PHP algorithm in Objective-C

我必須在我的iPhone應用程序中實現HMAC MD5。 PHP版本的算法(用於驗證的服務器端實現)在這里,我無法修改它(它是一個API)

function hmac($key, $data) {
    $b = 64; // byte length for md5
    if (strlen($key) > $b) {
        $key = pack("H*",md5($key));            
    }
    $key = str_pad($key, $b, chr(0x00));
    $ipad = str_pad('', $b, chr(0x36));
    $opad = str_pad('', $b, chr(0x5c));
    $k_ipad = $key ^ $ipad ;
    $k_opad = $key ^ $opad;
    $message = $k_opad . pack("H*",md5($k_ipad . $data));
    return base64_encode(md5($message));
}

我找到了幾個Objective-C實現:

- (NSString *)HMACMD5WithKey:(NSString *)key andData:(NSString *)data
{

    const char *cKey  = [key cStringUsingEncoding:NSASCIIStringEncoding];   
    const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];
    unsigned char cHMAC[CC_MD5_DIGEST_LENGTH];
    CCHmac(kCCHmacAlgMD5, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
    NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
    NSString *hash = [Base64 encode:HMAC];
    return hash;
}

沒有返回相同的結果(PHP!= ObjC)。

我使用ObjC實現將摘要長度更改為32(結果然后具有與PHP實現相同的長度),密鑰長度為64(對應於第一個str_pad)但結果總是不同的。

有人能告訴我如何在Objective-C中獲得相同的結果嗎?

編輯:由於ObjC中的2個實現返回相同的結果,因此這里只有一個有用。

根據我之前的回答,PHP代碼實現了HMAC算法的非標准變體。 這個Objective C代碼應該模仿它。 我在Mac OS X 10.4.11上針對PHP代碼測試了兩種組合:

“一把短信”
“一些文字”

“這是一個非常長的密鑰。它超過64個字節,這是重要的部分。”
“這是一些非常長的文本。它超過64字節,這是重要的部分。”

- (NSString *)HMACMD5WithKey:(NSString *)key andData:(NSString *)data {
    const char *cKey  = [key cStringUsingEncoding:NSASCIIStringEncoding];
    const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];
    const unsigned int blockSize = 64;
    char ipad[blockSize], opad[blockSize], keypad[blockSize];
    unsigned int keyLen = strlen(cKey);
    CC_MD5_CTX ctxt;
    if(keyLen > blockSize) {
        //CC_MD5(cKey, keyLen, keypad);
        CC_MD5_Init(&ctxt);
        CC_MD5_Update(&ctxt, cKey, keyLen);
        CC_MD5_Final((unsigned char *)keypad, &ctxt);
        keyLen = CC_MD5_DIGEST_LENGTH;
    } else {
        memcpy(keypad, cKey, keyLen);
    }
    memset(ipad, 0x36, blockSize);
    memset(opad, 0x5c, blockSize);

    int i;
    for(i = 0; i < keyLen; i++) {
      ipad[i] ^= keypad[i];
      opad[i] ^= keypad[i];
    }

    CC_MD5_Init(&ctxt);
    CC_MD5_Update(&ctxt, ipad, blockSize);
    CC_MD5_Update(&ctxt, cData, strlen(cData));
    unsigned char md5[CC_MD5_DIGEST_LENGTH];
    CC_MD5_Final(md5, &ctxt);

    CC_MD5_Init(&ctxt);
    CC_MD5_Update(&ctxt, opad, blockSize);
    CC_MD5_Update(&ctxt, md5, CC_MD5_DIGEST_LENGTH);
    CC_MD5_Final(md5, &ctxt);

    const unsigned int hex_len = CC_MD5_DIGEST_LENGTH*2+2;
    char hex[hex_len];
    for(i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
        snprintf(&hex[i*2], hex_len-i*2, "%02x", md5[i]);
    }

    NSData *HMAC = [[NSData alloc] initWithBytes:hex length:strlen(hex)];
    NSString *hash = [Base64 encode:HMAC];
    [HMAC release];
    return hash;
}

首先,你的“ObjC2”使用的是SHA1,而不是MD5(這意味着你可能會得到緩沖區溢出,因為SHA1是20字節,而MD5是16字節)。

其次,我認為您的PHP HMAC實現存在非標准變體。 請注意除了md5()的最后一次調用之外的所有調用都是用包(“H *”,...)包裝的? 除了Base64編碼之前的最后一個,就是。 我認為這意味着PHP代碼是Base64編碼數據的'可打印十六進制'表示(32個字節,每個是ASCII中的十六進制數字)而不是'原始'值(16個字節)。

由於您無法更改PHP實現,因此您必須在Objective C中編寫具有相同非標准變體的HMAC實現。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM