实施侧信道定时攻击



我正在从事一个在HMAC上用C实现侧信道定时攻击的项目。我通过计算十六进制编码标签并通过利用strcmp的时序优化逐字节暴力破解来实现这一点。因此,对于测试标签中的每个数字,我都会计算每个十六进制字符验证所需的时间。我采用对应于计算的最高时间量的十六进制字符,并推断它是标签中正确的字符,然后转到下一个字节。然而,strcmp的时间是非常不可预测的。虽然很容易看出比较两个相等的字符串和两个完全不同的字符串之间的时间差异,但我很难找到花费最多时间计算我的测试字符串的字符,而我正在比较的所有其他字符串都非常相似(仅相差 1 个字节(。

下面的 changeByte 方法采用 customTag,它是在该时间点之前计算的标记,并尝试查找与索引对应的正确字节。 changeByte 称为 n 次,其中 n=标签的长度。 hexTag 是一个全局变量,是正确的标记。 timeCompleted 存储计算 testTag 在字符位置的每个十六进制字符处花费的平均时间。任何帮助将不胜感激,感谢您的时间。

// Checks if the index of the given byte is correct or not
void changeByte(unsigned char *k, unsigned char * m, unsigned char * algorithm, unsigned char * customTag, int index)
{
long iterations=50000;
// used for every byte sequence to test the timing
unsigned char * tempTag = (unsigned char *)(malloc(sizeof (unsigned char)*(strlen(customTag)+1 ) ));
sprintf(tempTag, "%s", customTag);
int timeIndex=0;
// stores the time completed for every respective ascii char
double * timeCompleted = (double *)(malloc (sizeof (double) * 16));
// iterates through hex char 0-9, a-f
for (int i=48; i<=102;i++){
if (i >= 58 && i <=96)continue;
double total=0;
for (long j=0; j<iterations; j++){
// calculates the time it takes to complete for every char in that position
tempTag[index]=(unsigned char)i;
struct rusage usage;
struct timeval start, end;
getrusage(RUSAGE_SELF, &usage);
start=usage.ru_stime;
for (int k=0; k<50000; k++)externalStrcmp(tempTag, hexTag); // this is just calling strcmp in another file
getrusage (RUSAGE_SELF, &usage);
end=usage.ru_stime;
}
double startTime=((double)start.tv_sec + (double)start.tv_usec)/10000;
double endTime=((double)end.tv_sec+(double)end.tv_usec)/10000;
total+=endTime-startTime;
}
double val=total/iterations;
timeCompleted[timeIndex]=val;
timeIndex++;                
}
// sets next char equal to the hex char corresponding to the index
customTag[index]=getCorrectChar (timeCompleted);
free(timeCompleted);
free(tempTag);

}

// finds the highest time. The hex char corresponding with the highest time it took the
// verify function to complete is the correct one
unsigned char getCorrectChar(double * timeCompleted)
{
double high =-1;
int index=0;
for (int i=0; i<16; i++){
if (timeCompleted[i]>high){
high=timeCompleted[i];
index=i;
}
}
return (index+48)<=57 ?(unsigned char) (index+48) : (unsigned char)(index+87);
}

我不确定这是否是主要问题,但是您直接将秒添加到微秒,就好像 1us == 1s 一样。当开始时间和结束时间的秒数不同时,它会给出错误的结果。 usec 和 sec 之间的比例因子为 1 000 000 (thx zaph(。所以这应该更好:

double startTime=(double)start.tv_sec + (double)start.tv_usec/1000000;
double endTime=(double)end.tv_sec + (double)end.tv_usec/1000000;

最新更新