HMAC—PHP算法在Objective-C中的实现

HMAC—PHP算法在Objective-C中的实现,php,objective-c,algorithm,encryption,hmac,Php,Objective C,Algorithm,Encryption,Hmac,我必须在我的iPhone应用程序中实现HMAC MD5。算法的PHP版本(用于验证的服务器端实现)在这里,我不能修改它(它是一个API) 我发现了几个objective-C实现: - (NSString *)HMACMD5WithKey:(NSString *)key andData:(NSString *)data { const char *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding]; const

我必须在我的iPhone应用程序中实现HMAC MD5。算法的PHP版本(用于验证的服务器端实现)在这里,我不能修改它(它是一个API)

我发现了几个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中的两个实现返回相同的结果,因此这里只有一个有用。

首先,您的“ObjC2”使用的是SHA1,而不是MD5(这意味着您可能会出现缓冲区溢出,因为SHA1是20字节,而MD5是16字节)

第二,我认为PHP HMAC实现中存在非标准变体。请注意,除了最后一次调用md5()之外,其他所有调用都是用包(“H*”,…)包装的?除了Base64编码之前的最后一个之外,其他都是。我认为这意味着PHP代码是Base64编码数据的“可打印十六进制”表示(32个字节,每个字节都是ASCII中的十六进制数字),而不是“原始”值(16个字节)


由于您无法更改PHP实现,因此必须在Objective C中编写一个具有相同非标准变体的HMAC实现。

根据我之前的回答,PHP代码实现了HMAC算法的非标准变体。这个目标C代码应该模仿它。我在Mac OS X 10.4.11上对PHP代码进行了两种组合测试:

“短键”
“一些文本”

“这是一个很长的密钥。它的长度超过64字节,这是最重要的部分。”
这是一些很长的文本。它的长度超过64字节,这是重要的部分

-(NSString*)HMACMD5带键:(NSString*)键和数据:(NSString*)数据{
const char*cKey=[key cStringUsingEncoding:NSASCIIStringEncoding];
常量字符*cData=[数据cStringUsingEncoding:NSASCIIStringEncoding];
const unsigned int blockSize=64;
字符ipad[blockSize]、opad[blockSize]、键盘[blockSize];
无符号整数keyLen=strlen(cKey);
CC_MD5_CTX ctxt;
如果(keyLen>块大小){
//CC_MD5(cKey、keyLen、键盘);
CC_MD5_Init(&ctxt);
CC_MD5_更新(&ctxt、cKey、keyLen);
CC_MD5_最终((无符号字符*)键盘和ctxt);
keyLen=CC_MD5_摘要_长度;
}否则{
memcpy(键盘、cKey、keyLen);
}
memset(ipad,0x36,块大小);
内存集(opad,0x5c,块大小);
int i;
对于(i=0;i
没有必要在社区Wiki上回答这个问题。社区维基答案不会赢得任何声誉,通常用于非技术性问题。首先,感谢您的回答!你是对的,ObjC使用SHA1而不是MD5算法。但我的问题仍然是,如何重新实现PHP非标准变体?我可以从strach实现str_pad和^(XOR)函数,但对我来说,pack one仍然不可理解@Fsdn:现在,我没有时间编写ObjC代码来测试我的理论(编码十六进制而不是原始)。也许其他人会尝试一下,或者我以后再拿。(这也是我创建社区维基的原因,我的回答只是给出了一个理论,并不完整。)你能告诉我
[Base64编码]
来自哪里吗?它看起来像来自标准的ios。谢谢:)
- (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;
}
- (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;
}