Domanda

Devo implementare HMAC MD5 nella mia app per iPhone. La versione PHP dell'algoritmo (lato server implementato per la verifica) è qui e non posso modificarla (è un'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));
}

Ho trovato un paio di implementazione dell'obiettivo 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;
}

Non ha restituito gli stessi risultati (PHP! = ObjC).

Ho giocato con le implementazioni di ObjC cambiando la lunghezza del digest in 32 (il risultato ha la stessa lunghezza dell'implementazione di PHP), la lunghezza della chiave in 64 (corrispondente al primo str_pad) ma i risultati sono sempre diversi.

Qualcuno può dirmi come avere lo stesso risultato in Objective-C ??

Modifica: poiché le 2 implementazioni in ObjC restituiscono lo stesso risultato solo una è utile qui.

È stato utile?

Soluzione

Secondo la mia risposta precedente, il codice PHP implementa una variante non standard dell'algoritmo HMAC. Questo codice obiettivo C dovrebbe imitarlo. L'ho provato su Mac OS X 10.4.11 con il codice PHP per due combinazioni:

" un tasto breve "
" del testo "

" Questa è una chiave molto lunga. È più lungo di 64 byte, che è la parte importante. & Quot;
" Questo è un testo molto lungo. È più lungo di 64 byte, che è la parte importante. & Quot;

- (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;
}

Altri suggerimenti

Per prima cosa, il tuo “ObjC2” sta usando SHA1, non MD5 (questo significa che probabilmente stai ricevendo un sovraccarico del buffer poiché SHA1 è 20 byte, mentre MD5 è 16 byte).

Secondo, penso che ci sia una variazione non standard nella tua implementazione di PHP HMAC. Notare come tutti tranne le ultime invocazioni di md5 () sono racchiusi in un pacchetto (" H * ", ...)? Tutto tranne l'ultimo proprio prima della codifica Base64, cioè. Penso che ciò significhi che il codice PHP è Base64 che codifica la rappresentazione "esadecimale stampabile" dei dati (32 byte, ciascuno una cifra esadecimale in ASCII) non il valore "grezzo" (16 byte).

Poiché non è possibile modificare l'implementazione di PHP, sarà necessario scrivere un'implementazione HMAC nell'Obiettivo C che presenta la stessa variazione non standard.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top