2017-12-21 49 views
1

HMACSHA1을 손으로 구현하려고합니다. 서비스 제공자 또는 지원 티켓 (SOAP 호출, 따라서 XML 콘텐츠)에 대해 잘못된 HMAC를 계산했는지 확인해야합니다.Manual HMACSHA1 계산이 openssl 결과와 다릅니다.

문제는 HMAC의 NIST 사양을 고수하고 Hands와 OpenSSL HMAC 기능을 사용할 때 다른 결과를 얻는 것입니다.

다음 코드를 인쇄 :

B92674DCBA96F2DA93F7043071B931F5F2583FBD 
4303E965D88D288C9AC594CE6C5E6AFF27D40B2D 

하려면 openssl에 의한 결과는 우리가 우리의 응용 프로그램에서 얻을 동일하지만

- 그래서 나는 내 결과가 잘못되었다고, OpenSSL이 너무 일반적으로 사용되는 기준으로, 가정 - 하지만 내 오류는 어디 있습니까?

#include <stdio.h> 
#include <stdlib.h> 
#include <openssl/sha.h> 
#include <openssl/hmac.h> 
#include <string.h> 

#define byte unsigned char 
#define IPAD 0x36 
#define OPAD 0x5c 
#define DIGESTSIZE 20 



int main() { 
    byte *derivedKey = (byte[DIGESTSIZE]) {0x42,0xA9,0x78,0x90,0xFC,0xE5,0x16,0x8E,0x58,0x12,0x2F,0xF1,0xBA,0x32,0x5F,0x09,0x88,0x94,0x02,0x91}; 
    byte *content =  "<ds:SignedInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\" xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\"><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"><ec:InclusiveNamespaces xmlns:ec=\"http://www.w3.org/2001/10/xml-exc-c14n#\" PrefixList=\"soap\"></ec:InclusiveNamespaces></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#hmac-sha1\"></ds:SignatureMethod><ds:Reference URI=\"#TS-B183A13FEB0189143115136776276601\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"><ec:InclusiveNamespaces xmlns:ec=\"http://www.w3.org/2001/10/xml-exc-c14n#\" PrefixList=\"wsse soap\"></ec:InclusiveNamespaces></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></ds:DigestMethod><ds:DigestValue>rXJdGuDqoRrUJxuGiA1eyAozifk=</ds:DigestValue></ds:Reference></ds:SignedInfo>"; 
    byte *oPadKey =  malloc(DIGESTSIZE); 
    byte *iPadKey =  malloc(DIGESTSIZE); 


    int i; 
    for(i=0;i<DIGESTSIZE;i++){ 
     iPadKey[i]=derivedKey[i]^IPAD; 
     oPadKey[i]=derivedKey[i]^OPAD; 
    } 

    byte *rOpInput=  malloc(strlen(content)+DIGESTSIZE); 

    //concat iPad and content 
    memcpy(rOpInput, iPadKey, DIGESTSIZE); 
    memcpy(rOpInput+DIGESTSIZE,content,strlen(content)); 

    //SHA1 (iPad||content) gives the rightmost 20 bytes of the final SHA1 Input 
    byte *rOp=malloc(DIGESTSIZE); // H(iPad||content) 
    SHA1(rOpInput,strlen(content)+DIGESTSIZE,rOp); 
    free(rOpInput); 

    byte *finalInput = malloc(2*DIGESTSIZE); //oPad||H(iPad||content) 

    //concat oPad and H(ipad||content) 
    memcpy(finalInput, oPadKey,DIGESTSIZE); 
    memcpy(finalInput+DIGESTSIZE,rOp,DIGESTSIZE); 

    free(rOp); 
    free(oPadKey); 
    free(iPadKey); 
    //SHA1(oPad||H(iPad||content)) 

    byte *hmac = malloc(DIGESTSIZE); 
    SHA1(finalInput,40,hmac); 
    free(finalInput); 

    //print calculated HMAC as HEX 
    for(i=0;i<DIGESTSIZE;i++){ 
     printf("%02X", (hmac[i] & 0xFF)); 
    } 
    printf("\n"); 


    //verify with openssl HMAC 
    byte *result = HMAC(EVP_sha1(), derivedKey, DIGESTSIZE, content, strlen(content), NULL, NULL); 
    for(i=0;i<DIGESTSIZE;i++){ 
     printf("%02X", (result[i] & 0xFF)); 
    } 
    printf("\n"); 
    return 0; 
} 

답변

6

버그가 간단한입니다 : 여기 내 코드입니다 http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.198-1.pdf

:

내가 참조 사양입니다. ipadopad은 다이제스트 출력 길이가 아닌 (input) block size 길이 여야합니다. 나는. SHA-1의 경우 20 비트가 아니라 512 비트 (64 바이트) 여야합니다.

#define INPUT_BLOCK_SIZE 64 
byte derivedKey[64] = {0x42,0xA9,0x78,0x90,0xFC,0xE5,0x16,0x8E,0x58,0x12, 
         0x2F,0xF1,0xBA,0x32,0x5F,0x09,0x88,0x94,0x02,0x91}; 
// null-padded on the right 

다음 ipad의 길이, opad 필요 목적지에 대한 INPUT_BLOCK_SIZE DIGESTSIZE 변경.

결과 :

4303E965D88D288C9AC594CE6C5E6AFF27D40B2D 

Wikipedia

K에서 '은 입력 블록에 추가 제로와 오른쪽 K 패딩하여 본래의 키 K (유래의 다른 비밀 키이며 해시 함수의 크기 또는 블록 크기보다 길면 K를 해싱하여)

(강조 광산).


P. SHA1_Init/Update/Final을 사용하는 것이 더 좋을 것입니다. 그런 다음 많은 복사가 건너 뜁니다. ipadopad에 대한 메모리 할당을 먼저 수행하지 않고 ipad을 계산하고 사용 된 후에는 opad를 얻으려면 0x6a으로 xorring하십시오.

+0

아아, 24 바이트 길이이므로 키를 해시 할 필요가 없습니다. – billdoor

+0

그래, 그게 내가 –

+0

을 읽는 방법이다. 자바 프레임 워크 apache cxf/wss4j는 HMAC를 계산하기 전에 hmacsha1에서 20 바이트까지 사용하는 키를 "잘라내"않는다. 단지 마지막 4 바이트를 떨어 뜨렸다. 어쨌든 이것은 틀린가? 원래 키는 24 바이트입니다. – billdoor