2017-12-21 4 views
1

I HMACSHA1 von Hand zu implementieren ist versucht, zu überprüfen, ob unsere Serviceprovider oder wir eine falsche HMAC für einen Support-Ticket (einen SOAP-Aufruf, damit die XML-Inhalte) zu berechnen.Handbuch HMACSHA1 Berechnung unterscheidet mich von OpenSSL Ergebnissen

Das Problem ist, ich bleibe für HMACs auf NIST-Spezifikation und ein anderes Ergebnis von Hand bekommen und wenn Funktionen mit OpenSSL HMAC.

Der folgende Code druckt:

B92674DCBA96F2DA93F7043071B931F5F2583FBD 
4303E965D88D288C9AC594CE6C5E6AFF27D40B2D 

während das Ergebnis von OpenSSL ist die gleichen wir in unserer Anwendung zu bekommen - so nehme ich an, auf der Grundlage, dass OpenSSL so häufig verwendet wird, dass mein Ergebnis nicht stimmt - Aber wo ist mein Fehler?

Dies ist die Spezifikation I zu verweisen:

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

Antwort

6

Der Fehler ist einfach: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.198-1.pdf

hier mein Code. Die ipad und opad müssen (input) block size in der Länge sein, nicht die Länge der Digest-Ausgabe. I.e. sie müssen 512 Bits (64 Bytes) für SHA-1, 20 nicht

D.h. sein

#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 

und dann die DIGESTSIZE zu INPUT_BLOCK_SIZE ändern, wo die Länge der ipad, opad benötigt wird.

Ergebnis:

4303E965D88D288C9AC594CE6C5E6AFF27D40B2D 

Von Wikipedia

K‘ist ein weiterer Geheimschlüssel, von dem Originalschlüssel K abgeleitet (durch K nach rechts mit zusätzlichen Nullen an den Eingangsblock Klotzen Größe der Hash-Funktion, oder durch Hashing K, wenn sie länger als diese Blockgröße ist)

(Schwerpunkt meins).


P.S. Es wäre besser, die SHA1_Init/Update/Final zu verwenden, da dann viele Kopien übersprungen würden. Sie können auch vermeiden, das Zuweisen von Speicher für die ipad und opad separat von ersten ipad Berechnung und nachdem es verwendet wurde, dann xorring anstelle von 0x6a die opad zu bekommen.

+0

Ahh, also muss ich den Schlüssel überhaupt nicht Hash, wie es 24 Byte lang ist? – billdoor

+0

Ja, das ist, wie ich es gelesen –

+0

vor allem: die Java-Framework Apache CXF/WSS4J bedeutet „trimmen“ den Schlüssel für HMACSHA1 vor 20 Byte verwendet, um die HMAC Berechnung - es dropt nur die letzten 4 Bytes. Das ist in jedem Fall falsch, oder? Der ursprüngliche Schlüssel ist 24 Bytes lang – billdoor

Verwandte Themen