0

我正在尝试使用 Crypto++ 在 ECB 模式(但仍然)之上手动制作 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:基于 ECB 的手动 CTR

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 是:

"Yž+eÞsÂÙ\bü´\x1a¨Ü_ÙR•L¸Ð€¦å«ÎÍÊ[w®Ÿg\fT½\ý7!p\r^ÍdžúP\bîT\x3\x1cZï.s%\x1ei{ÚMˆØ… Pä¾õ\x46\r5\tâýï‚ú\x16ç'Qiæ²\x15š€á^ªê]W ÊNqdŒ¥ ^†¾j%8.Ìù\x6Þ›ÔÏ'[c\x19"

manual_result 是:

"Yž+eÞsÂÙ\bü´\x1a¨Ü_Ù·\x18ýuù\n\nl\x11Á\x19À†Žaðƒºñ®GäþŽá•\x11ÇYœf+^Q\x1a\x13B³'QQµºëÑÌåM\"\x12\x115â\x10¿Ô„›s °‰=\x18*\x1c:²IF'n@ŠŠ¾mGÂzõžÀ\x1eÏ\SëYU¼í'" >

我的工具有什么问题?

4

1 回答 1

1

由于您的第一个块似乎工作正常,我只搜索了柜台本身管理中的问题,这似乎是我的错误:

memcpy(encryptBefore, encryptBefore + i, BLOCK_SIZE);

我想,在这里你试图增加你的 IVi时间,但这不是发生的事情,你所做的是试图将跨越字节encryptBefore的指针的内容复制到你的指针中。这根本不会增加 IV,但它适用于第一个块,因为 then 。encryptBefore+iBLOCK_SIZEi=0

您要做的实际上是创建一个大整数CryptoPP::Integer,用作 IV 并递增该整数,然后Encode(byte *output, size_t outputLen, Signedness sign=UNSIGNED) const在需要使用字节而不是整数时使用 CryptoPP Integer 类中的函数将其转换为字节数组。

Ps:在执行 i/o 操作时,我建议你使用十六进制字符串,看看CryptoPP::HexEncoderHexDecoder类,它们都在 CryptoPP wiki 上有很好的记录

于 2016-12-01T13:25:57.083 回答