我正在尝试手工实现HMACSHA1,以检查我们的服务提供者或者我们为支持票( SOAP调用,因此是xml内容)计算了错误的HMAC。
问题是,我坚持HMACs的NIST规范,在使用openssl函数时手工获得不同的结果。
以下代码打印:
B92674DCBA96F2DA93F7043071B931F5F2583FBD
4303E965D88D288C9AC594CE6C5E6AFF27D40B2D虽然openssl的结果与我们在应用程序中得到的结果相同--因此我假设,基于openssl是如此常用的,我的结果是错误的--但是我的错误在哪里呢?
这是我所指的规范:http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.198-1.pdf
这是我的代码:
#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;
}发布于 2017-12-21 16:54:37
窃听器很简单。ipad和opad的长度需要是(输入)块大小,而不是摘要输出的长度。也就是说,对于SHA-1,它们必须是512位(64字节),而不是20位。
也就是说。
#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然后将DIGESTSIZE更改为INPUT_BLOCK_SIZE,以便在需要ipad长度的地方使用opad。
结果:
4303E965D88D288C9AC594CE6C5E6AFF27D40B2D来自维基百科
K‘是从原始键K派生出来的另一个秘密密钥(在哈希函数__的哈希输入块大小中向右填充K和额外的零,或者如果K大于该块大小,则通过散列K)
(偏压雷).
最好使用SHA1_Init/Update/Final,,因为这样就会跳过大量的复制。您还可以避免分别为ipad和opad分配内存,方法是先计算ipad,然后在使用了ipad之后,由0x6a进行定位以获得opad。
发布于 2019-10-29 16:23:45
请把这个转过来。您可以轻松地计算散列。
发布于 2019-10-29 16:28:36
#define IPAD 0x36
#define OPAD 0x5c
#define DIGESTSIZE 20
#define INPUT_BLOCK_SIZE 64
#define byte unsigned char
static byte mykey[64];
int main () {
int i;
byte mykey[INPUT_BLOCK_SIZE] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F };
byte content[] = {0x53, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x6D, 0x65, 0x73,
0x73, 0x61, 0x67, 0x65, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x6B, 0x65, 0x79, 0x6C, 0x65, 0x6E, 0x3D, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x6C, 0x65, 0x6E };
byte k0_ipad_text[sizeof(content) + INPUT_BLOCK_SIZE];
byte hmac[DIGESTSIZE];
byte k0_opad_hash[INPUT_BLOCK_SIZE + DIGESTSIZE];
/*
* K0 is mykey as size is 0x40 = 64 bytes
*/
byte *oPadKey = malloc(INPUT_BLOCK_SIZE);
byte *iPadKey = malloc(INPUT_BLOCK_SIZE);
memset(oPadKey, 0, INPUT_BLOCK_SIZE);
memset(iPadKey, 0, INPUT_BLOCK_SIZE);
for(i=0;i<INPUT_BLOCK_SIZE;i++){
iPadKey[i]=mykey[i]^IPAD;
oPadKey[i]=mykey[i]^OPAD;
}
printf("\n iPad key = ");
for(i=0;i<INPUT_BLOCK_SIZE;i++){
printf("%02x ", iPadKey[i]);
}
printf("\n oPad key = ");
for(i=0;i<INPUT_BLOCK_SIZE;i++){
printf("%02x ", oPadKey[i]);
}
//Key^ipad)||text)
memcpy(k0_ipad_text, iPadKey, INPUT_BLOCK_SIZE);
memcpy(k0_ipad_text + INPUT_BLOCK_SIZE, content, sizeof(content));
SHA1(k0_ipad_text, INPUT_BLOCK_SIZE + sizeof(content), hmac);
#if 0
printf("\n hmac = ");
for(i=0;i<DIGESTSIZE;i++){
printf("%02x ", hmac[i]);
}
#endif
memcpy(k0_opad_hash, oPadKey, INPUT_BLOCK_SIZE);
memcpy(k0_opad_hash + INPUT_BLOCK_SIZE, hmac, DIGESTSIZE);
SHA1(k0_opad_hash, INPUT_BLOCK_SIZE + DIGESTSIZE, hmac);
printf("\n hmac \n");
for(i=0;i<DIGESTSIZE;i++){
printf("%02x", hmac[i]);
}
printf("\n");
//verify with openssl HMAC
byte *result = HMAC(EVP_sha1(), mykey, INPUT_BLOCK_SIZE, content, sizeof(content), NULL, NULL);
for(i=0;i<DIGESTSIZE;i++){
printf("%02X", (result[i] & 0xFF ));
}
printf("\n");
return 0;
}https://stackoverflow.com/questions/47929005
复制相似问题