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;
}
Ahh, also muss ich den Schlüssel überhaupt nicht Hash, wie es 24 Byte lang ist? – billdoor
Ja, das ist, wie ich es gelesen –
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