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::HexEncoderHexDecoder类,它们都是well documented on CryptoPP wiki

+0

你救了我的命! – Andiana

+0

不客气。请注意,我不知道你是如何生成你的IV的,但要非常小心,不要使用两次相同的IV,否则只要你使用相同的密钥(但不同的数据)加密两次,你暴露你的数据到CTR模式的传统攻击。所以确保你没有两次相同的IV(即使增加后)。所以当你使用例如17作为一个IV加密5块,你不能再使用从17到22的IV的整个范围! – Lery

+2

Crypto ++提供[IncrementCounterByOne](http://www.cryptopp.com/docs/ref/misc_8h.html)用于递增表示为字节数组的计数器。 – jww