加密算法中的数据类型问题 [英] Data type problem in encryption algorithm
问题描述
大家好,
我非常需要你的帮助......我正在研究一个IPSec
的实现,几乎完成了,我发现了一个相当可观的问题。我正在发送一个特定的数组+一个HMAC-SHA1函数的密钥。
我用以下内容进行了测试:
void icv_Calculation_test(char p_output [20]){
char msgtest [] ="你什么都不想要?" ;;
char key [] =" Jefe";
uint8_t outputsha [20];
int size_message,size_key;
size_message = strlen(msgtest);
size_key = strlen(key);
hmac_sha(key,size_key,msgtest,size_message,outputsha,
sizeof(outputsha));
strcpy( p_output,outputsha);
返回;
}
我得到了预期的结果,如测试用例#2 RFC 2202:
0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79
然而,在我尝试匹配不同的
HMAC计算(来自发件人)之前,我认为一切正常和接收器)..他们没有匹配,我
然后意识到我每次都在生成不同的HMAC计算时间我
调用函数(来自发件人)。我尝试了其他测试用例来自
RFC 2202,然后我意识到我遇到了以下问题:
例如,当试图获得HMAC时测试用例的结果#1
其中包含:
char msgtest [] =" Hi There";
和键是0x0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B
我不知道如何处理它..我尝试了以下内容:
strtoul()..像这样:
char szInput [] =" 0x0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B" ;;
char * pEnd;
unsigned long ul;
ul = strtoul(szInput,& pEnd,0);
但是RFC 2202的HMAC功能需要键作为字符串..我很小
有点困惑,因为我不知道该怎么办。
底线,我在发送时没有得到预期的HMAC计算
以下函数,但在使用测试用例#2时,全部为
ascii,它工作正常..
下面是代码..它有点长,但我非常需要你的
帮助到这里..告诉我,如果你需要别的东西,为了更清楚..
这里我试图显示数据类型..
..........
typedef struct {
char * message;
char dest_ip [ 20];
char src_ip [20];
int msg_length;
int port;
char * key ;
char算法;
} CONF_PARAMS;
.............
uint8_t payload [sizeof(packet)+ sizeof(authenHeader_ext)];
uint8_t输出[output_size]
............. ..
icv_Calculation(payload,sizeof(payload),cnf,output,output_size);
..............
void icv_Calculation(char * hdrs,int hdrs_len,CONF_PARAMS * cnf,uint8_t
* output,int output_len){
if(b) cnf-> algorithm =='s'')
hmac_ sha(cnf-> key,strlen(cnf-> key),hdrs,hdrs_len,output,
sizeof(output));
}
hdrs是我的十六进制值,HMAC
计算的工作信息。
继承HMAC功能,.h和.c
#ifndef HMACSHA1_H_
#define HMACSHA1_H_
#include " sha1.h"
#ifndef SHA_DIGESTSIZE
#define SHA_DIGESTSIZE 20
#endif
#ifndef SHA_BLOCKSIZE
#define SHA_BLOCKSIZE 64
#endif
void pr_sha(FILE *,unsigned char *,int) ;
void truncate_sha1(char *,char *,int);
void hmac_sha(char *,int,char *,int,char *,int);
#endif / * HMACSHA1_H _ * /
------------------------- ---------
#include< stdio.h>
#include" sha1.h"
#包括hmac-sha1.h
/ *
*来自sha1.h - -----------------------
*
* sha1_context;
* void sha1_starts(sha1_context * ctx);
* void sha1_update(sha1_context * ctx,uint8 * input,uint32 length);
* void sha1_finish(sha1_context * ctx, uint8 digest [20]);
*
* /
/ *打印摘要的功能* /
void pr_sha(FILE * fp,unsigned char * s,int t){
int i;
fprintf(fp," 0x");
for(i = 0;我< t; i ++)
fprintf(fp,"%02x",s [i]);
fprintf(fp," 0");
}
void truncate_sha1(
char * d1,/ *数据被截断* /
char * d2, / *截断数据* /
int len / *以字节为单位的长度* /
){
int i;
for(i = 0; i< len; i ++)
d2 [i] = d1 [i];
}
/ *计算摘要的函数* /
void hmac_sha(
char * k,/ *密钥* /
int lk,/ *密钥长度,以字节为单位* /
char * d,/ * data * /
int ld,/ *数据长度,以字节为单位* /
char * out,/ *输出缓冲区,至少t字节* /
int t
){
sha1_context ictx,octx;
char isha [SHA_DIGESTSIZE],osha [SHA_DIGESTSIZE];
char key [SHA_DIGESTSIZE];
char buf [SHA_BLOCKSIZE];
int i;
if(lk& GT; SHA_BLOCKSIZE){
sha1_context tctx;
sha1_starts(& tctx);
sha1_update(& tctx ,k,lk);
sha1_finish(& tctx,key);
k = key;
lk = SHA_DIGESTSIZE;
}
/ ****内心摘要**** /
sha1_starts(& ictx );
/ *填充内部摘要的关键字* /
for(i = 0; i< lk; ++ i)>
buf [i] = k [i] ^ 0x36;
for(i = lk; i< SHA_BLOCKSIZE; ++ i)buf [i] = 0x36;
sha1_update(& ictx,buf,SHA_BLOCKSIZE);
sha1_update(& ictx,d,ld);
sha1_finish(& ictx,isha);
/ **** Outter Digest **** /
sha1_starts(& octx);
/ *填写外部摘要的关键字* /
for(i = 0; i< lk; ++ i)
buf [i] = k [i] ^ 0x5C;
for(i = lk; i< SHA_BLOCKSIZE; ++ i)
buf [i] = 0x5C;
sha1_update(& octx,buf,SHA_BLOCKSIZE);
sha1_update(& octx,isha,SHA_DIGESTSIZE);
sha1_finish(& octx,osha) ;
/ *截断并打印结果* /
t = t> SHA_DIGESTSIZE? SHA_DIGESTSIZE:t;
truncate_sha1(osha,out,t);
pr_sha(stdout,out,t);
}
------------------------
和这是SHA1函数,对不起,如果这是一个很长的代码,但是我猜的是
问题是函数调用的起源..
/ *
*符合FIPS-180-1标准的SHA-1实施
*
*版权所有(C)2001-2003 Christophe Devine
*
*此程序是免费软件;您可以根据GNO通用公共许可证的条款重新分发和/或修改
*它由
*自由软件基金会发布;许可证的第2版,或者
*(根据您的选择)以后的任何版本。
*
*此程序在希望它有用,
*但没有任何保证;甚至没有暗示的保证
*适销性或特定用途的适用性。有关更多详细信息,请参阅
* GNU通用公共许可证。
*
*您应该已收到GNU通用公共许可证的副本
*以及该计划;如果没有,请写信给自由软件
* Foundation,Inc.,59 Temple Place,Suite 330,Boston,MA
02111-1307 USA
* /
#include< string.h>
#include" sha1.h"
#define GET_UINT32(n,b,i)\
{\
(n)=((uint32)(b)[( i)]<< 24)\
| ((uint32)(b)[(i)+ 1]<< 16)\
| ((uint32)(b)[(i)+ 2]<< 8)\
| ((uint32)(b)[(i)+ 3]); \
}
#define PUT_UINT32(n,b,i)\
{\
(b)[(i)] =(uint8)((n)>> 24); \\ b
(b)[(i)+ 1] =(uint8)((n)>> 16); \\ b
(b)[(i)+ 2] =(uint8)((n)>> 8); \\ b
(b)[(i)+ 3] =(uint8)((n)); \
}
void sha1_starts(sha1_context * ctx)
{
ctx-> ; total [0] = 0;
ctx-> total [1] = 0;
ctx-> state [0] = 0x67452301;
ctx-> state [1] = 0xEFCDAB89;
ctx-> state [2] = 0x98BADCFE;
ctx-> state [3] = 0x10325476;
ctx-> state [4] = 0xC3D2E1F0;
}
void sha1_process( sha1_context * ctx,uint8 data [64])
{
uint32 temp,W [16],A,B,C,D,E;
GET_UINT32(W [0],数据,0);
GET_UINT32(W [1],数据,4);
GET_UINT32(W [2],数据,8);
GET_UINT32(W [3],数据,12);
GET_UINT32(W [4],数据,16);
GET_UINT32(W [5],数据,20);
GET_UINT32(W [6],数据,24);
GET_UINT32(W [7],数据,28);
GET_UINT32(W [8],数据,32);
GET_UINT32(W [9],数据,36);
GET_UINT32(W [10],数据,40);
GET _UINT32(W [11],数据,44);
GET_UINT32(W [12],数据,48);
GET_UINT32(W [13],数据,52 );
GET_UINT32(W [14],数据,56);
GET_UINT32(W [15],数据,60);
#define S(x,n)((x<< n)| ((x& 0xFFFFFFFF)>>(32 - n)))
#define R(t)\
(\
temp = W [(t - 3)& 0x0F] ^ W [(t - 8)& 0x0F] ^ \
W [(t - 14) & 0x0F] ^ W [t& 0x0F],\
(W [t& 0x0F] = S(temp,1))\
)
#define P(a,b,c,d,e,x)\
{\
e + = S(a,5)+ F(b,c,d)+ K + x; b = S(b,30); \
}
A = ctx->州[0];
B = ctx->州[ 1];
C = ctx->州[2];
D = ctx->州[3];
E = ctx-> state [4];
#define F(x,y,z)(z ^(x&(y ^ z)))
#define K 0x5A827999
P(A,B,C,D,E,W [0]);
P(E, A,B,C,D,W [1]);
P(D,E,A,B,C,W [2]);
P( C,D,E,A,B,W [3]);
P(B,C,D,E,A,W [4]);
P(A,B,C,D,E,W [5]);
P(E,A,B,C,D,W [6]);
P(D,E,A,B,C,W [7]);
P(C,D,E,A,B,W [8]);
P(B,C,D,E,A,W [9]);
P(A,B,C,D,E,W [10]);
P(E,A,B,C,D,W [11]);
P(D,E,A,B,C,W [12]);
P(C,D,E,A,B,W [13]);
P(B,C,D,E,A,W [14] );
P(A,B,C,D,E,W [15]);
P(E,A,B,C,D,R( 16));
P(D,E,A,B,C,R(17));
P(C,D,E,A, B,R(18));
P(B,C,D,E,A,R(19));
#undef K
#undef F
#define F(x,y,z)(x ^ y ^ z)
#define K 0x6ED9EBA1
P(A,B,C,D,E,R(20));
P(E,A,B,C,D ,R(21));
P(D,E,A,B,C,R(22));
P(C,D,E,A ,B,R(23));
P(B,C,D,E,A,R(24));
P(A,B,C ,D,E,R(25));
P(E,A,B,C,D,R(26));
P(D,E ,A,B,C,R(27));
P(C,D,E,A,B,R(28));
P(B ,C,D,E,A,R(29));
P(A,B,C,D,E,R(30));
P (E,A,B,C,D,R(31));
P(D,E,A,B,C,R(32));
P(C,D,E,A,B,R(33));
P(B,C,D,E,A,R(34));
P(A,B,C,D,E,R(35));
P(E,A,B,C,D,R(36));
P(D,E,A,B,C,R(37));
P(C,D,E,A,B,R(38));
P(B,C,D,E,A,R(39));
#undef K
#undef F
#define F(x,y,z)((x& y)| (z&(x | y)))
#define K 0x8F1BBCDC
P(A,B,C,D,E,R(40) ));
P(E,A,B,C,D,R(41));
P(D,E,A,B,C,R (42));
P(C,D,E,A,B,R(43));
P(B,C,D,E,A ,R(44));
P(A,B,C,D,E,R(45));
P(E,A,B,C ,D,R(46));
P(D,E,A,B,C,R(47));
P(C,D,E ,A,B,R(48));
P(B,C,D,E,A,R(49));
P(A,B ,C,D,E,R(50));
P(E,A,B,C,D,R(51));
P(D ,E,A,B,C,R(52));
P(C,D,E,A,B,R(53));
P (B,C,D,E,A,R(54));
P(A,B,C,D,E,R(55));
P(E,A,B,C,D,R(56));
P(D,E,A,B,C,R(57));
P(C,D,E,A,B,R(58));
P(B,C,D,E,A,R(59));
#undef K
#undef F
#define F(x,y,z)(x ^ y ^ z)
#define K 0xCA62C1D6
P(A,B,C,D,E,R(60));
P(E,A,B,C,D,R(61));
P(D,E,A,B,C,R(62));
P(C,D,E,A,B,R(63));
P(B,C,D,E,A,R(64));
P(A,B,C,D,E,R(65));
P(E,A,B,C,D,R(66));
P(D,E,A,B,C,R(67));
P(C,D,E,A,B,R(68));
P(B,C,D,E,A,R(69));
P(A,B,C,D,E,R(70) );
P(E,A,B,C,D,R(71));
P(D,E,A,B,C,R( 72));
P(C,D,E,A,B,R(73));
P(B,C,D,E,A, R(74));
P(A,B,C,D,E,R(75));
P(E,A,B,C, D,R(76));
P(D,E,A,B,C,R(77));
P(C,D,E, A,B,R(78));
P(B,C,D,E,A,R(79));
#undef K
#undef F
ctx-> state [0] + = A;
ctx-> state [ 1] + = B;
ctx->州[2] + = C;
ctx->州[3] + = D;
ctx-> state [4] + = E;
}
void sha1_update(sha1_context * ct x,uint8 *输入,uint32长度)
{
uint32 left,fill;
if(!长度)返回;
left = ctx-> total [0]& 0x3F;
fill = 64 - left;
ctx-> total [0] + = length;
ctx- > total [0]& = 0xFFFFFFFF;
if(ctx-> total [0]< length)
ctx-> total [1] ++;
if(left&& length> = fill)
{
memcpy( (void *)(ctx-> buffer + left),
(void *)input,fill);
sha1_process(ctx,ctx-> buffer);
长度 - =填充;
输入+ =填充;
left = 0;
}
while(长度> = 64)
{
sha1_process(ctx,输入);
长度 - = 64;
输入+ = 64;
}
如果(长度)
{
memcpy((void *)(ctx-> buffer + left),
(void *)输入,长度);
}
}
静态uint8 sha1_padding [64] =
{
0x80,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
void sha1_finish(sha1_context * ctx,uint8 digest [20])
{
uint32 last,padn;
uint32高,低;
uint8 msglen [8];
high =(ctx-> total [0]>> 29)
| (ctx->总计[1] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
PUT_UINT32(高,msglen,0);
PUT_UINT32(低,msglen,4);
last = ctx-> total [ 0]& 0x3F;
padn =(last< 56)? (56 - last):( 120 - last);
sha1_update(ctx,sha1_padding,padn);
sha1_update(ctx,msglen,8);
PUT_UINT32(ctx-> state [0],digest,0);
PUT_UINT32(ctx-> state [1],digest,4 );
PUT_UINT32(ctx-> state [2],digest,8);
PUT_UINT32(ctx-> state [3],digest,12);
PUT_UINT32(ctx-> state [4],digest,16);
}
FBM
Fernando Barsoba写道:大家好,
我非常需要你们的帮助...我是从事IPSec实施,几乎完成后,我发现了一个相当大的问题。我正在发送一个特定的数组+一个HMAC-SHA1函数的密钥。
我做了以下测试:
void icv_Calculation_test(char p_output [20]){
char msgtest [] ="你想做什么?" ;;
char key [] =" Jefe" ;;
uint8_t outputsha [20];
int size_message, size_key;
size_message = strlen(msgtest);
size_key = strlen(key);
hmac_sha(key,size_key,msgtest,size_message,outputsha,
sizeof(outputsha));
strcpy(p_output,outputsha);
返回;
}
我得到了预期的结果,如RFC 2202中的测试用例#2:
0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79
然而,我认为一切正常,直到我尝试匹配不同的HMAC计算(来自发送者和接收者)......他们并不匹配,我
然后意识到我每次调用函数(发件人)时都会生成不同的HMAC计算。我尝试了来自RFC 2202的其他测试用例,然后我意识到我遇到了以下问题:
例如,当试图获得测试用例#1的HMAC结果时其中包括:
char msgtest [] =" Hi There" ;;
,密钥是0x0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B
我不知道怎么处理用它..我尝试了以下内容:
strtoul()..像这样:
< snip>
忘了strtoul(),这太久了。您需要将此
十六进制字符串转换为实际的字节序列。看看你是否有一个库
函数来执行此操作。
如果没有,这是一个示例实现,我在几秒钟内掀起了
(所以不要相信它,不要指望它快速):
#include< stdlib.h>
#include< string.h>
/ *将单个十六进制数字''c''转换为相应的
整数,如果''c''不是十六进制数字,则为-1。 * /
int hexdigit_to_int(char c){
if(c> =''0''&& c< ='''9'')返回c - ''0'';
开关(c){
case''a'':case''A'':返回10;
case''b'':case''B'':返回11;
case''c'':case''C'':返回12;
case''d'':case''D'':返回13;
case''e'':case''E'':返回14;
case''f'':case''F'':返回15;
默认值:{
返回-1;
}
}
}
/ *将字节序列的十六进制表示转换为
字节序列。 * /
/ *如果
成功则返回malloc() - 分配的strlen(十六进制)/ 2字节块,否则返回空指针。 * /
unsigned char * hexstr_to_bytes(const char * hex){
size_t l = strlen(hex);
size_t n = 0;
unsigned char * result;
if(l%2!= 0)返回NULL;
result = malloc(l / 2);
if(!result)返回NULL;
while(n< l){
int d1 = hexdigit_to_int(hex [n])* 16;
int d2 = hexdigit_to_int(hex [n + 1]);
if(d1 == -1 || d2 == -1){
免费(结果);
返回NULL;
}
结果[n / 2] = d1 + d2;
n + = 2;
}
返回结果;
}
请记住,输入字符串不能以0x开头,你要求
必须释放()结果并且*不是*一个以null结尾的字符串但是
a一个长度的字节序列你必须跟踪自己,所以没有
在它上面调用strlen()。
S.
Skarmander写道:Fernando Barsoba写道: 大家好,
我非常需要你的帮助...我正在研究IPSec
void icv_Calculation_test(char p_output [20]){
char msgtest [] =你想要什么?;
char key [] =" Jefe";
uint8_t outputsha [20];
int size_message,size_key;
size_message = strlen(msgtest);
size_key = strlen(key );
hmac_sha(key,size_key,msgtest,size_message,outputsha,
sizeof(outputsha));
strcpy(p_output,outputsha);
return;
}
我得到了预期的结果,如RFC 2202中的测试用例#2:
0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79
然而,在我尝试匹配之前,我认为一切正常不同的HMAC计算(来自发送者和接收者)..他们没有匹配,然后我意识到我每次都会生成不同的HMAC计算
我调用了函数(来自发送者)。我从RFC 2202尝试了其他测试用例,然后我意识到我遇到了以下问题:
例如,当试图获得测试用例#1的HMAC结果时其中包括:
char msgtest [] =" Hi There" ;;
,密钥是0x0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B
我不知道如何处理用它..我尝试了以下内容:
strtoul()..像这样:
< snip>
忘了strtoul(),这太久了。您需要将此
十六进制字符串转换为实际的字节序列。看看你是否在某个地方有一个库
功能。
如果没有,这是一个示例实现我在几秒钟内掀起
(所以不要''相信它,不要指望它快速):
#include< stdlib.h>
#include< string.h>
非常感谢,我会试试这个......但是,我有什么问题背后的概念是什么?我的意思是,为什么当我尝试获取消息摘要
a特定的''字符串''消息和特定的''字符串''键时,函数
有效(消息摘要)总是一样的),当我尝试使用相同的字符串键,但是不同的''字符串''消息时,我不会尝试
?
这些消息之间的区别仅在于后者的十六进制
内容对我来说很重要..我的意思是,而不是:
char msgtest [] ="你什么都不想要什么?" ;;
char key [] =" Jefe";
我有一个char *,其十六进制内容对我来说很重要..
谢谢,
FBM
Fernando Barsoba写道:Skarmander写道:
Fernando Barsoba写道:
大家好,
我非常需要你的帮助......我正在开发一个IPSec
实现,几乎完成后,我发现了相当多的问题。我正在发送一个特定的数组+一个HMAC-SHA1功能键。我用以下方法进行了测试:
void icv_Calculation_test(char p_output [20]){
char msgtest [] =你想要什么?;
char key [] =" Jefe";
uint8_t outputsha [20];
int size_message,size_key;
size_message = strlen(msgtest);
size_key = strlen(key );
hmac_sha(key,size_key,msgtest,size_message,outputsha,
sizeof(outputsha));
strcpy(p_output,outputsha);
return;
}
我得到了预期的结果,如RFC 2202中的测试用例#2:
0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79
< snip>例如,当试图获得测试用例#1的HMAC结果时,其中包含:
char msgtest [] =" Hi There" ;;
,密钥为0x0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B
< snip>我的意思是,为什么当我尝试获取特定字符串消息和特定字符串键的消息摘要时,该功能
有效(消息摘要始终相同),以及它不是当我尝试使用相同的字符串键,而是一个不同的''字符串''消息时?这些消息之间唯一的区别是,对于后者,hex内容对我来说很重要。我的意思是,而不是:
char msgtest [] = 你想要什么,什么都不需要?;
char key [] =" Jefe" ;;
我有一个char *,其十六进制内容对我来说很重要..
SHA函数(显然)需要一个字节序列的键。
正如它所发生的那样,Jefe是一个字节序列:假设你的系统
使用与ASCII兼容的字符集,序列可以用十六进制表示为
为0x4A65666500。
>
这就是为什么将字符串传递给函数just are:字符串是
已经是一个字节序列。在第二个例子中(key = 0x0b0b0b ...)
你要传递一个实际的字节序列,表示为一串
十六进制数字,而不是字符串0x0b0b0b ......,这是
完全不同的东西。
S.
Hi all,
I very much need your help here guys.. I''m working on a IPSec
implementation, and when almost finished, I found a considerable
problem. I''m sending a particular array + a key to a HMAC-SHA1 function.
I did the tests with the following:
void icv_Calculation_test(char p_output[20]) {
char msgtest[]="what do ya want for nothing?";
char key[]="Jefe";
uint8_t outputsha[20];
int size_message, size_key;
size_message = strlen(msgtest);
size_key = strlen(key);
hmac_sha(key, size_key, msgtest, size_message, outputsha,
sizeof(outputsha));
strcpy(p_output, outputsha);
return;
}
And I got the expected result, as in test case #2 from RFC 2202:
0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79
However, I thought everything was ok until I tried to match different
HMAC calculations (from sender and receiver).. they didn''t match and I
then realized I was generating different HMAC calculations every time I
called the function (from sender). I tried then other test cases from
RFC 2202, and then I realized I had problems with the following:
For instance, when trying to obtain the HMAC result for test case #1
which has:
char msgtest[]="Hi There";
and the key is 0x0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B
I''m not sure how to deal with it.. I tried the following:
strtoul().. like this:
char szInput[]="0x0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B";
char * pEnd;
unsigned long ul;
ul = strtoul (szInput,&pEnd,0);
But the HMAC functions from RFC 2202 need keys as strings.. I''m a little
bit confused because I don''t know what to do with it.
Bottom line, I''m not getting the expected HMAC calculation when sending
to the function the following, but when using test case #2, which is all
ascii, it works fine..
Below is the code.. It''s a little bit long, but I very much need your
help here.. Tell me if you need something else for this to be more clear..
Here i''m trying to show the data types..
..........
typedef struct {
char * message;
char dest_ip[20];
char src_ip[20];
int msg_length;
int port;
char * key;
char algorithm;
} CONF_PARAMS;
.............
uint8_t payload[sizeof(packet) + sizeof(authenHeader_ext)];
uint8_t output[output_size]
...............
icv_Calculation(payload, sizeof(payload), cnf, output, output_size);
..............
void icv_Calculation(char *hdrs, int hdrs_len, CONF_PARAMS *cnf, uint8_t
*output, int output_len) {
if (cnf->algorithm == ''s'' )
hmac_sha(cnf->key, strlen(cnf->key), hdrs, hdrs_len, output,
sizeof(output));
}
hdrs is where I have my hex values, the message over which the HMAC
calculation works.
Heres the HMAC function, .h and .c
#ifndef HMACSHA1_H_
#define HMACSHA1_H_
#include "sha1.h"
#ifndef SHA_DIGESTSIZE
#define SHA_DIGESTSIZE 20
#endif
#ifndef SHA_BLOCKSIZE
#define SHA_BLOCKSIZE 64
#endif
void pr_sha(FILE*, unsigned char*, int);
void truncate_sha1 (char*, char*, int);
void hmac_sha (char*, int, char*, int, char*, int);
#endif /*HMACSHA1_H_*/
----------------------------------
#include <stdio.h>
#include "sha1.h"
#include "hmac-sha1.h"
/*
* From sha1.h ------------------------
*
* sha1_context;
* void sha1_starts( sha1_context *ctx );
* void sha1_update( sha1_context *ctx, uint8 *input, uint32 length );
* void sha1_finish( sha1_context *ctx, uint8 digest[20] );
*
*/
/* Function to print the digest */
void pr_sha(FILE* fp, unsigned char* s, int t) {
int i;
fprintf(fp, "0x");
for (i = 0 ; i < t ; i++)
fprintf(fp, "%02x", s[i]);
fprintf(fp, "0");
}
void truncate_sha1 (
char* d1, /* data to be truncated */
char* d2, /* truncated data */
int len /* length in bytes to keep */
) {
int i;
for (i=0; i < len; i++)
d2[i] = d1[i];
}
/* Function to compute the digest */
void hmac_sha (
char* k, /* secret key */
int lk, /* length of the key in bytes */
char* d, /* data */
int ld, /* length of data in bytes */
char* out, /* output buffer, at least "t" bytes */
int t
) {
sha1_context ictx, octx;
char isha[SHA_DIGESTSIZE], osha[SHA_DIGESTSIZE];
char key[SHA_DIGESTSIZE];
char buf[SHA_BLOCKSIZE];
int i;
if (lk > SHA_BLOCKSIZE) {
sha1_context tctx;
sha1_starts(&tctx);
sha1_update(&tctx, k, lk);
sha1_finish(&tctx, key);
k = key;
lk = SHA_DIGESTSIZE;
}
/**** Inner Digest ****/
sha1_starts(&ictx);
/* Pad the key for inner digest */
for (i = 0 ; i < lk ; ++i)
buf[i] = k[i] ^ 0x36;
for (i = lk ; i < SHA_BLOCKSIZE ; ++i) buf[i] = 0x36;
sha1_update(&ictx, buf, SHA_BLOCKSIZE);
sha1_update(&ictx, d, ld);
sha1_finish(&ictx, isha);
/**** Outter Digest ****/
sha1_starts(&octx);
/* Pad the key for outter digest */
for (i = 0 ; i < lk ; ++i)
buf[i] = k[i] ^ 0x5C;
for (i = lk ; i < SHA_BLOCKSIZE ; ++i)
buf[i] = 0x5C;
sha1_update(&octx, buf, SHA_BLOCKSIZE);
sha1_update(&octx, isha, SHA_DIGESTSIZE);
sha1_finish(&octx, osha);
/* truncate and print the results */
t = t > SHA_DIGESTSIZE ? SHA_DIGESTSIZE : t;
truncate_sha1(osha, out, t);
pr_sha(stdout, out, t);
}
------------------------
And here''s the SHA1 function, sorry if this is a long code, but the
problem I guess is in the origin of the function calls..
/*
* FIPS-180-1 compliant SHA-1 implementation
*
* Copyright (C) 2001-2003 Christophe Devine
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
*/
#include <string.h>
#include "sha1.h"
#define GET_UINT32(n,b,i) \
{ \
(n) = ( (uint32) (b)[(i) ] << 24 ) \
| ( (uint32) (b)[(i) + 1] << 16 ) \
| ( (uint32) (b)[(i) + 2] << 8 ) \
| ( (uint32) (b)[(i) + 3] ); \
}
#define PUT_UINT32(n,b,i) \
{ \
(b)[(i) ] = (uint8) ( (n) >> 24 ); \
(b)[(i) + 1] = (uint8) ( (n) >> 16 ); \
(b)[(i) + 2] = (uint8) ( (n) >> 8 ); \
(b)[(i) + 3] = (uint8) ( (n) ); \
}
void sha1_starts( sha1_context *ctx )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0;
}
void sha1_process( sha1_context *ctx, uint8 data[64] )
{
uint32 temp, W[16], A, B, C, D, E;
GET_UINT32( W[0], data, 0 );
GET_UINT32( W[1], data, 4 );
GET_UINT32( W[2], data, 8 );
GET_UINT32( W[3], data, 12 );
GET_UINT32( W[4], data, 16 );
GET_UINT32( W[5], data, 20 );
GET_UINT32( W[6], data, 24 );
GET_UINT32( W[7], data, 28 );
GET_UINT32( W[8], data, 32 );
GET_UINT32( W[9], data, 36 );
GET_UINT32( W[10], data, 40 );
GET_UINT32( W[11], data, 44 );
GET_UINT32( W[12], data, 48 );
GET_UINT32( W[13], data, 52 );
GET_UINT32( W[14], data, 56 );
GET_UINT32( W[15], data, 60 );
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
#define R(t) \
( \
temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \
W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \
( W[t & 0x0F] = S(temp,1) ) \
)
#define P(a,b,c,d,e,x) \
{ \
e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
#define F(x,y,z) (z ^ (x & (y ^ z)))
#define K 0x5A827999
P( A, B, C, D, E, W[0] );
P( E, A, B, C, D, W[1] );
P( D, E, A, B, C, W[2] );
P( C, D, E, A, B, W[3] );
P( B, C, D, E, A, W[4] );
P( A, B, C, D, E, W[5] );
P( E, A, B, C, D, W[6] );
P( D, E, A, B, C, W[7] );
P( C, D, E, A, B, W[8] );
P( B, C, D, E, A, W[9] );
P( A, B, C, D, E, W[10] );
P( E, A, B, C, D, W[11] );
P( D, E, A, B, C, W[12] );
P( C, D, E, A, B, W[13] );
P( B, C, D, E, A, W[14] );
P( A, B, C, D, E, W[15] );
P( E, A, B, C, D, R(16) );
P( D, E, A, B, C, R(17) );
P( C, D, E, A, B, R(18) );
P( B, C, D, E, A, R(19) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0x6ED9EBA1
P( A, B, C, D, E, R(20) );
P( E, A, B, C, D, R(21) );
P( D, E, A, B, C, R(22) );
P( C, D, E, A, B, R(23) );
P( B, C, D, E, A, R(24) );
P( A, B, C, D, E, R(25) );
P( E, A, B, C, D, R(26) );
P( D, E, A, B, C, R(27) );
P( C, D, E, A, B, R(28) );
P( B, C, D, E, A, R(29) );
P( A, B, C, D, E, R(30) );
P( E, A, B, C, D, R(31) );
P( D, E, A, B, C, R(32) );
P( C, D, E, A, B, R(33) );
P( B, C, D, E, A, R(34) );
P( A, B, C, D, E, R(35) );
P( E, A, B, C, D, R(36) );
P( D, E, A, B, C, R(37) );
P( C, D, E, A, B, R(38) );
P( B, C, D, E, A, R(39) );
#undef K
#undef F
#define F(x,y,z) ((x & y) | (z & (x | y)))
#define K 0x8F1BBCDC
P( A, B, C, D, E, R(40) );
P( E, A, B, C, D, R(41) );
P( D, E, A, B, C, R(42) );
P( C, D, E, A, B, R(43) );
P( B, C, D, E, A, R(44) );
P( A, B, C, D, E, R(45) );
P( E, A, B, C, D, R(46) );
P( D, E, A, B, C, R(47) );
P( C, D, E, A, B, R(48) );
P( B, C, D, E, A, R(49) );
P( A, B, C, D, E, R(50) );
P( E, A, B, C, D, R(51) );
P( D, E, A, B, C, R(52) );
P( C, D, E, A, B, R(53) );
P( B, C, D, E, A, R(54) );
P( A, B, C, D, E, R(55) );
P( E, A, B, C, D, R(56) );
P( D, E, A, B, C, R(57) );
P( C, D, E, A, B, R(58) );
P( B, C, D, E, A, R(59) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0xCA62C1D6
P( A, B, C, D, E, R(60) );
P( E, A, B, C, D, R(61) );
P( D, E, A, B, C, R(62) );
P( C, D, E, A, B, R(63) );
P( B, C, D, E, A, R(64) );
P( A, B, C, D, E, R(65) );
P( E, A, B, C, D, R(66) );
P( D, E, A, B, C, R(67) );
P( C, D, E, A, B, R(68) );
P( B, C, D, E, A, R(69) );
P( A, B, C, D, E, R(70) );
P( E, A, B, C, D, R(71) );
P( D, E, A, B, C, R(72) );
P( C, D, E, A, B, R(73) );
P( B, C, D, E, A, R(74) );
P( A, B, C, D, E, R(75) );
P( E, A, B, C, D, R(76) );
P( D, E, A, B, C, R(77) );
P( C, D, E, A, B, R(78) );
P( B, C, D, E, A, R(79) );
#undef K
#undef F
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
}
void sha1_update( sha1_context *ctx, uint8 *input, uint32 length )
{
uint32 left, fill;
if( ! length ) return;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += length;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < length )
ctx->total[1]++;
if( left && length >= fill )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, fill );
sha1_process( ctx, ctx->buffer );
length -= fill;
input += fill;
left = 0;
}
while( length >= 64 )
{
sha1_process( ctx, input );
length -= 64;
input += 64;
}
if( length )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, length );
}
}
static uint8 sha1_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
void sha1_finish( sha1_context *ctx, uint8 digest[20] )
{
uint32 last, padn;
uint32 high, low;
uint8 msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT32( high, msglen, 0 );
PUT_UINT32( low, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
sha1_update( ctx, sha1_padding, padn );
sha1_update( ctx, msglen, 8 );
PUT_UINT32( ctx->state[0], digest, 0 );
PUT_UINT32( ctx->state[1], digest, 4 );
PUT_UINT32( ctx->state[2], digest, 8 );
PUT_UINT32( ctx->state[3], digest, 12 );
PUT_UINT32( ctx->state[4], digest, 16 );
}
FBM
Fernando Barsoba wrote:Hi all,
I very much need your help here guys.. I''m working on a IPSec
implementation, and when almost finished, I found a considerable
problem. I''m sending a particular array + a key to a HMAC-SHA1 function.
I did the tests with the following:
void icv_Calculation_test(char p_output[20]) {
char msgtest[]="what do ya want for nothing?";
char key[]="Jefe";
uint8_t outputsha[20];
int size_message, size_key;
size_message = strlen(msgtest);
size_key = strlen(key);
hmac_sha(key, size_key, msgtest, size_message, outputsha,
sizeof(outputsha));
strcpy(p_output, outputsha);
return;
}
And I got the expected result, as in test case #2 from RFC 2202:
0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79
However, I thought everything was ok until I tried to match different
HMAC calculations (from sender and receiver).. they didn''t match and I
then realized I was generating different HMAC calculations every time I
called the function (from sender). I tried then other test cases from
RFC 2202, and then I realized I had problems with the following:
For instance, when trying to obtain the HMAC result for test case #1
which has:
char msgtest[]="Hi There";
and the key is 0x0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B
I''m not sure how to deal with it.. I tried the following:
strtoul().. like this:
<snip>
Forget strtoul(), this is too long for a long. You need to convert this
hexstring to an actual sequence of bytes. See if you have a library
function somewhere to do this.
If not, here''s an example implementation I whipped up in a few seconds
(so don''t trust it, and don''t count on it being fast):
#include <stdlib.h>
#include <string.h>
/* Convert the single hexadecimal digit ''c'' to the corresponding
integer, or -1 if ''c'' is not a hex digit. */
int hexdigit_to_int(char c) {
if (c >= ''0'' && c <= ''9'') return c - ''0'';
switch (c) {
case ''a'': case ''A'': return 10;
case ''b'': case ''B'': return 11;
case ''c'': case ''C'': return 12;
case ''d'': case ''D'': return 13;
case ''e'': case ''E'': return 14;
case ''f'': case ''F'': return 15;
default: {
return -1;
}
}
}
/* Convert the hexadecimal representation of a sequence of bytes to
the sequence of bytes. */
/* Returns a malloc()-allocated block of strlen(hex) / 2 bytes if
successful or a null pointer otherwise. */
unsigned char* hexstr_to_bytes(const char* hex) {
size_t l = strlen(hex);
size_t n = 0;
unsigned char* result;
if (l % 2 != 0) return NULL;
result = malloc(l / 2);
if (!result) return NULL;
while (n < l) {
int d1 = hexdigit_to_int(hex[n]) * 16;
int d2 = hexdigit_to_int(hex[n + 1]);
if (d1 == -1 || d2 == -1) {
free(result);
return NULL;
}
result[n / 2] = d1 + d2;
n += 2;
}
return result;
}
Keep in mind that the input string must not begin with "0x", that you
must free() the result and that it is *not* a null-terminated string but
a sequence of bytes of a length you must keep track of yourself, so no
calling strlen() on it.
S.
Skarmander wrote:Fernando Barsoba wrote:Hi all,
I very much need your help here guys.. I''m working on a IPSec
implementation, and when almost finished, I found a considerable
problem. I''m sending a particular array + a key to a HMAC-SHA1
function. I did the tests with the following:
void icv_Calculation_test(char p_output[20]) {
char msgtest[]="what do ya want for nothing?";
char key[]="Jefe";
uint8_t outputsha[20];
int size_message, size_key;
size_message = strlen(msgtest);
size_key = strlen(key);
hmac_sha(key, size_key, msgtest, size_message, outputsha,
sizeof(outputsha));
strcpy(p_output, outputsha);
return;
}
And I got the expected result, as in test case #2 from RFC 2202:
0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79
However, I thought everything was ok until I tried to match different
HMAC calculations (from sender and receiver).. they didn''t match and I
then realized I was generating different HMAC calculations every time
I called the function (from sender). I tried then other test cases
from RFC 2202, and then I realized I had problems with the following:
For instance, when trying to obtain the HMAC result for test case #1
which has:
char msgtest[]="Hi There";
and the key is 0x0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B
I''m not sure how to deal with it.. I tried the following:
strtoul().. like this:
<snip>
Forget strtoul(), this is too long for a long. You need to convert this
hexstring to an actual sequence of bytes. See if you have a library
function somewhere to do this.
If not, here''s an example implementation I whipped up in a few seconds
(so don''t trust it, and don''t count on it being fast):
#include <stdlib.h>
#include <string.h>
Thanks a lot, I''ll try this.. however, what is the concept behind the
problem I''m having? I mean, why when I try to obtain a message digest of
a particular ''string'' message and particular ''string'' key the function
works (message digest is always the same), and it doesn''t when I try the
same with identical string key, but a different ''string'' message? The
only difference between those messages is that with the latter the hex
content is what is important to me.. I mean, instead of having:
char msgtest[]="what do ya want for nothing?";
char key[]="Jefe";
I have a char * whose hex content is what matters to me..
thanks,
FBM
Fernando Barsoba wrote:Skarmander wrote:Fernando Barsoba wrote:Hi all,
I very much need your help here guys.. I''m working on a IPSec
implementation, and when almost finished, I found a considerable
problem. I''m sending a particular array + a key to a HMAC-SHA1
function. I did the tests with the following:
void icv_Calculation_test(char p_output[20]) {
char msgtest[]="what do ya want for nothing?";
char key[]="Jefe";
uint8_t outputsha[20];
int size_message, size_key;
size_message = strlen(msgtest);
size_key = strlen(key);
hmac_sha(key, size_key, msgtest, size_message, outputsha,
sizeof(outputsha));
strcpy(p_output, outputsha);
return;
}
And I got the expected result, as in test case #2 from RFC 2202:
0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79
<snip> For instance, when trying to obtain the HMAC result for test case #1
which has:
char msgtest[]="Hi There";
and the key is 0x0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B<snip> I mean, why when I try to obtain a message digest of
a particular ''string'' message and particular ''string'' key the function
works (message digest is always the same), and it doesn''t when I try the
same with identical string key, but a different ''string'' message? The
only difference between those messages is that with the latter the hex
content is what is important to me.. I mean, instead of having:
char msgtest[]="what do ya want for nothing?";
char key[]="Jefe";
I have a char * whose hex content is what matters to me..
The SHA function (apparently) expects a key that is a sequence of bytes.
As it so happens, "Jefe" is a sequence of bytes: assuming your system
uses an ASCII-compatible character set, the sequence can be represented
in hexadecimal as 0x4A65666500.
This is why passing a string to the function "just works": a string is
already a sequence of bytes. In the second example (key = 0x0b0b0b...)
you want to pass an actual byte sequence represented as a string of
hexadecimal digits, not the string "0x0b0b0b...", which is something
completely different.
S.
这篇关于加密算法中的数据类型问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!