我有一个要求我们实现S-DES(简化DES)的任务,该算法包括很多位排列,移位以及异或。
显然,实现这一点的最快方法是使用位操作,例如:
char CLS(char key, int shift){
char skey;
skey = (key << shift) | (key >> (8 - shift))
return skey;
}
/* Get 8-bit subkey from 10-bit key */
char permute(short int key){
short int i;
short int k1[] = { BIT_6, BIT_3, BIT_7, BIT_4, BIT_8, BIT_5, BIT_10, BIT_9 }; // SDES spec
char sk1 = '\0';
for(i = 0; i < 8; i++){
sk1 = (sk1 << 1) | (key & k1[i]);
}
}
...
这很简单。但是,如何有效地获取这些位?使用像fread()
这样的东西,我一次只能读取1个字节,并将其提供给SDES算法,但是这大大低估了CPU的使用率,因为我不仅仅是读取和加密1个字节。一次一个字节,我也会一次写1个字节的加密数据到磁盘!当然必须有更好的方法。
我能想到的唯一替代方法是将每个字节视为一个char数组并以这种方式操作这些位,但这不仅会增加内存开销:我仍然会遇到1个字节的问题时间和我不能使用移位操作,而是需要使用临时数组和数组索引。
我希望稍微改善这种行为,但我能想到的只是将更大的块带入内存。例如,我可以使用fread()
将4K数据块读入char数组[4096]然后使用它,而不是从磁盘逐个读取4096个字节。
但是,我不确定这是否是我能做的全部,因为它是一个简单的算法。是否可以进行进一步的改进,或者它是否能达到最佳状态?
如果有人想看看,here是S-DES算法的规范。
答案 0 :(得分:3)
如果要加速算法,可以在字节数组上并行加密,例如使用OpenMP。正如DarkSquirrel42在评论中指出的那样,为了提高速度,您还应该使用查找表将函数替换为permute函数:
#define LUT_SIZE 1024
static char lookup_table[LUT_SIZE];
/* Get 8-bit subkey from 10-bit key */
char permute(short int key)
{
// SDES spec
short int k1[] = { BIT_6, BIT_3, BIT_7, BIT_4, BIT_8, BIT_5, BIT_10, BIT_9 };
char sk1 = '\0';
for (short int i = 0; i < 8; i++) {
sk1 = (sk1 << 1) | (key & k1[i]);
}
return sk1;
}
void init_lut()
{
for (short int i = 0; i < LUT_SIZE; i++) {
lookup_table[i] = permute(i);
}
}
char permute_fast(short int key)
{
if (key < 0 || key >= LUT_SIZE) {
//error handling
return 0;
}
return lookup_table[key];
}