Question

Je dois implémenter le HMAC MD5 dans mon application iPhone. La version PHP de l'algorithme (côté serveur implémenté pour la vérification) est là et je ne peux pas le modifier (c'est une 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));
}

J'ai trouvé quelques exemples de mise en œuvre de l'objectif 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;
}

N'a pas renvoyé les mêmes résultats (PHP! = ObjC).

J'ai joué avec les implémentations ObjC en modifiant la longueur du résumé en 32 (le résultat a alors la même longueur que celle en PHP), la longueur de la clé en 64 (correspondant au premier str_pad), mais les résultats sont toujours différents.

Quelqu'un peut-il me dire comment obtenir le même résultat en Objective-C ??

Edit: puisque les 2 implémentations dans ObjC renvoient le même résultat, un seul est utile ici.

Était-ce utile?

La solution

Comme indiqué dans ma réponse précédente, le code PHP implémente une variante non standard de l'algorithme HMAC. Ce code objectif C devrait l'imiter. Je l'ai testé sous Mac OS X 10.4.11 par rapport au code PHP pour deux combinaisons:

"une touche courte"
"du texte"

"Ceci est une très longue clé. Il est plus long que 64 octets, ce qui est la partie importante. "
"Ceci est un texte très long. Il est plus long que 64 octets, ce qui est la partie importante. "

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

Autres conseils

Tout d’abord, vos & # 8220; ObjC2 & # 8221; utilise SHA1, pas MD5 (cela signifie que vous obtenez probablement un dépassement de tampon puisque SHA1 est de 20 octets, alors que MD5 est de 16 octets).

Deuxièmement, je pense qu’il existe une variation non standard de votre implémentation PHP HMAC. Notez que toutes les invocations de md5 (), à l'exception des dernières, sont entourées d'un pack ("H *", & # 8230;)? Tous sauf le dernier juste avant le codage Base64, c’est-à-dire. Je pense que cela signifie que le code PHP est en Base64 codant la représentation "hex imprimable" des données (32 octets, chacun un chiffre hexadécimal en ASCII) et non la valeur "brute" (16 octets).

Etant donné que vous ne pouvez pas modifier l'implémentation PHP, vous devez écrire une implémentation HMAC dans Objective C comportant cette même variante non standard.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top