Crypto ++ CTR模式手动工具
我想在使用Crypto ++的ECB模式(但仍然)之上手动点击CTR。 的理念是:Crypto ++ CTR模式手动工具
对于单块:只要使用ECB对于多个块,使用CTR算法 (AFAIK):
//We have n block of plain data -> M PlainData M[n]; key; iv; char *CTR; cipher =""; for(i = 0; i<n; i++){ if(i ==0){ CTR = iv; } ei = encryptECB(CTR + i) cipherI = xor(ei, M[i]) cipher += cipherI; }
//我的XOR(),以异或两个char阵列
void xor(char *s1, char* s2, char *& result, int len){
try{
int i;
for (i = 0; i < len; i++){
int u = s1[i]^s2[i];
result[i] = u;
}
result[i] = '\0';
}
catch (...){
cout << "Errp";
}
}
测试1:100%的Crypto ++ CTR
string auto_ctr(char * s1, long size){
CTR_Mode<AES>::Encryption e;
e.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));
string cipherZ;
StringSource s(s1, true,
new StreamTransformationFilter(e,
new StringSink(cipherZ), BlockPaddingSchemeDef::BlockPaddingScheme::NO_PADDING
)
);
return cipherZ;
}
测试2:手动CTR基于ECB
string encrypt(char* s1, int size){
ECB_Mode<AES>::Encryption e;
e.SetKey(key, size);
string cipher;
string s(s1, size);
StringSource ss1(s, true,
new StreamTransformationFilter(e,
new StringSink(cipher), BlockPaddingSchemeDef::BlockPaddingScheme::NO_PADDING
) // StreamTransformationFilter
); // StringSource
return cipher;
}
static string manual_ctr(char *plain, long &size){
int nBlocks = size/BLOCK_SIZE;
char* encryptBefore = new char[BLOCK_SIZE];
char *ci = new char[BLOCK_SIZE] ;
string cipher;
for (int i = 0; i < nBlocks; i++){
//If the first loop, CTR = IV
if (i == 0){
memcpy(encryptBefore, iv, BLOCK_SIZE);
}
encryptBefore[BLOCK_SIZE] = '\0';
memcpy(encryptBefore, encryptBefore + i, BLOCK_SIZE);
char *buffer = new char[BLOCK_SIZE];
memcpy(buffer, &plain[i], BLOCK_SIZE);
buffer[BLOCK_SIZE] = '\0';
//Encrypt the CTR
string e1 = encrypt(encryptBefore, BLOCK_SIZE);
//Xor it with m[i] => c[i]
xor((char*)e1.c_str(), buffer, ci, BLOCK_SIZE);
//Append to the summary cipher
/*for (int j = 0; j < BLOCK_SIZE/2; j++){
SetChar(cipher, ci[j], i*BLOCK_SIZE + j);
}*/
cipher += ci;
//Set the cipher back to iv
//memcpy(encryptBefore, ci, BLOCK_SIZE);
}
return cipher;
}
这是主要用于测试:
void main(){
long size = 0;
char * plain = FileUtil::readAllByte("some1.txt", size);
string auto_result = auto_ctr(plain, size);
string manual_result = manual_ctr(plain, size);
getchar();
}
的auto_result是:
“YZ +eÞsÂÙ \bü'\x1a¨Ü_ÙR•LD€|å«IIE [w®Ÿg\fT½\ Y7 p!\ r^IC†达\位\ X3 \ X 1cZï.s%\ x1ei {ÚMØ...Pä¾õ\ x46 \ r5 \tâýï,,\x16ç'Qiæ²\x15šá^ªê] W ènqdŒ†¾j%8.Ìù\x6Þ>ÔÏ'[c \ x19'
的manual_result是:
“YZ +eÞsÂÙ\bü'\x1a¨Ü_Ù·\x18ýuù\ n \ NL \ X11A \x19À†Žaðƒºñ®GäþŽá•\x11ÇYœf+^Q \ X1A \ x13B³'QQμºëÑÌåM\“\ X12 \x115â\x10¿Ô“> S 0‰= \ X18 * \ X1C:²IF'[email protected]ŠŠ¾mGÂzõžÀ\x1eÏ\SëYU¼í”' >
什么是proble米与我的工具?
因为你的第一个块似乎是工作的罚款,我只在柜台本身的管理搜索的问题,这里是什么,似乎我的意思:
的memcpy(encryptBefore,encryptBefore + 1, BLOCK_SIZE);
在这里,你正试图增加你的IV i
次,我相信,但是这是不是发生什么事,你做的是试图复制到encryptBefore
指针encryptBefore+i
指针跨越BLOCK_SIZE
字节的内容。这完全不是递增IV,但它适用于第一个块,因为那时i=0
。
你想要做的实际上是创建一个使用CryptoPP::Integer
作为IV使用和增加与整数,然后使用从CryptoPP Integer类的Encode(byte *output, size_t outputLen, Signedness sign=UNSIGNED) const
功能将其转换成字节数组,当你需要使用字节,而不是一个大的整数什么整数。 Ps:当进行I/O操作时,我建议你使用十六进制字符串,看一下CryptoPP::HexEncoder
和HexDecoder
类,它们都是well documented on CryptoPP wiki。
你救了我的命! – Andiana
不客气。请注意,我不知道你是如何生成你的IV的,但要非常小心,不要使用两次相同的IV,否则只要你使用相同的密钥(但不同的数据)加密两次,你暴露你的数据到CTR模式的传统攻击。所以确保你没有两次相同的IV(即使增加后)。所以当你使用例如17作为一个IV加密5块,你不能再使用从17到22的IV的整个范围! – Lery
Crypto ++提供[IncrementCounterByOne](http://www.cryptopp.com/docs/ref/misc_8h.html)用于递增表示为字节数组的计数器。 – jww