문제

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

Digest 길이를 32로 변경하는 OBJC 구현 (결과는 PHP 구현과 동일한 길이), 키 길이는 64 (첫 번째 STR_PAD에 해당)를 변경했지만 결과는 항상 다른 것입니다.

누군가가 객관적인 c에서 같은 결과를 얻는 방법을 말해 줄 수 있습니까?

편집 : OBJC의 2 개의 구현이 동일한 결과를 반환하기 때문에 여기에 유용합니다 ..

도움이 되었습니까?

해결책

이전 답변에 따라 PHP 코드는 HMAC 알고리즘의 비표준 변형을 구현합니다. 이 목표 C 코드는이를 모방해야합니다. PHP 코드에 대해 Mac OS X 10.4.11에서 두 가지 조합에 대해 테스트했습니다.

"짧은 키"
"일부 텍스트"

"이것은 매우 긴 열쇠입니다. 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"는 MD5가 아닌 SHA1을 사용하고 있습니다 (SHA1이 20 바이트이므로 MD5가 16 바이트이기 때문에 버퍼 오버런을 받고 있음을 의미합니다).

둘째, PHP HMAC 구현에는 비표준 변동이 있다고 생각합니다. MD5 ()의 마지막 호출을 제외한 모든 부정이 팩 ( "h*",…)으로 어떻게 싸여 있는지 확인하십시오. Base64 인코딩 직전의 마지막 것입니다. 이것은 PHP 코드가 '원시'값 (16 바이트)이 아닌 데이터의 '인쇄 가능한 16 진'표현 (32 바이트, 각각 ASCII)의 '인쇄 가능한 16 진'표현을 인코딩하는 Base64라는 것을 의미합니다.

PHP 구현을 변경할 수 없으므로 동일한 비표준 변동을 갖는 목표 C에 HMAC 구현을 작성해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top