3

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)。

ダイジェストの長さを 32 (結果は PHP の実装と同じ長さ) に変更し、キーの長さを 64 (最初の str_pad に対応) に変更して ObjC 実装を試してみましたが、結果は常に異なります。

誰かがObjective-Cで同じ結果を得る方法を教えてもらえますか??

編集: ObjC の 2 つの実装は同じ結果を返すため、ここでは 1 つだけが役に立ちます..

4

2 に答える 2

4

私の以前の回答によると、PHP コードは HMAC アルゴリズムの非標準バリアントを実装しています。この Objective C コードは、それを模倣する必要があります。Mac OS X 10.4.11 で、2 つの組み合わせの 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;
}
于 2009-10-27T13:10:56.413 に答える
2

まず、「ObjC2」は MD5 ではなく SHA1 を使用しています (これは、SHA1 が 20 バイトであり、MD5 が 16 バイトであるため、おそらくバッファー オーバーランが発生していることを意味します)。

次に、PHP HMAC 実装に非標準のバリエーションがあると思います。md5() の最後の呼び出し以外はすべて pack("H*",…) でラップされていることに注意してください。Base64エンコーディングの直前の最後のものを除くすべて、つまり。これは、PHP コードがデータの「印刷可能な 16 進」表現 (32 バイト、それぞれ ASCII の 16 進数) ではなく、「生の」値 (16 バイト) をエンコードする Base64 であることを意味すると思います。

PHP 実装を変更することはできないため、これと同じ非標準のバリエーションを持つ Objective C で HMAC 実装を作成する必要があります。

于 2009-10-27T08:26:29.250 に答える