【问题标题】:How to implement AES in crypto++ which is applied multiple times to an input? which AES mode?如何在多次应用于输入的crypto++中实现AES?哪种AES模式?
【发布时间】:2021-06-09 06:00:15
【问题描述】:

对于我的目标应用程序,我想为给定的输入连续多次使用 AES。 在连续加密它 $i$ 次后,如果向后解密 $i$ 次,它应该会产生相同的起始输入。

举个例子code我已经实现了一些可行的解决方案:

//g++ -o aestest aestest.cpp -lcryptopp    
#include <iostream>
#include <iomanip>

#include "cryptopp/modes.h"
#include "cryptopp/aes.h"
#include "cryptopp/filters.h"
#include <cassert>

void dispBA(std::vector<byte> &bav, std::string text =""){
    std::cout << text << " : size "<< bav.size() <<" byte"<< std::endl;
    for( long unsigned int i = 0; i < bav.size(); i++ ) {
         std::cout << std::dec<< (int)((static_cast<byte>(bav[i]))) << ", ";
    }
    std::cout << std::endl << std::endl;
}

void encryptBV(CryptoPP::CBC_Mode_ExternalCipher::Encryption &cbcEncryption, std::vector<byte> &bytesIn, std::vector<byte> &bytesCrypOut, bool disp=false){
    CryptoPP::StreamTransformationFilter stfEncryptor(cbcEncryption, new CryptoPP::ArraySink( &bytesCrypOut[0],bytesCrypOut.size()  ), CryptoPP::StreamTransformationFilter::NO_PADDING );
    stfEncryptor.Put(  &bytesIn[0], bytesIn.size() );
    stfEncryptor.MessageEnd();
    if(disp)dispBA(bytesCrypOut, "Cipher numbers");
}

void decryptBV(CryptoPP::CBC_Mode_ExternalCipher::Decryption &cbcDecryption, std::vector<byte> &bytesCrypIn, std::vector<byte> &bytesDecrOut, bool disp=false){
    CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::ArraySink( &bytesDecrOut[0], bytesDecrOut.size()  ), CryptoPP::StreamTransformationFilter::NO_PADDING  );
    stfDecryptor.Put( &bytesCrypIn[0], bytesCrypIn.size() );
    stfDecryptor.MessageEnd();
    if(disp)dispBA(bytesDecrOut, "Decrypted numbers");
}


int main(int argc, char* argv[]) {

    //Key 32 bytes -> aes256
    //block size always 16
    const int myKeysize = 32;
    byte key[ myKeysize ], iv[ CryptoPP::AES::BLOCKSIZE ];
    memset( key, 0x00, myKeysize ); // no key set yet
    memset( iv, 0x00, CryptoPP::AES::BLOCKSIZE );
    
    //encryption
    std::vector<byte> bytesCryp(myKeysize);
    CryptoPP::AES::Encryption aesEncryption(key, myKeysize);
    CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption( aesEncryption, iv );
    
    //decryption
    std::vector<byte> bytesDecr(myKeysize);   
    CryptoPP::AES::Decryption aesDecryption(key, myKeysize);
    CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption( aesDecryption, iv );
        
    std::vector<byte> bytesIn = {0 ,1, 2, 3, 4, 5 ,6 ,7 ,8 ,9 ,10 ,11, 12, 13 ,14 ,15 ,16, 17, 18 ,19 ,20 ,21 ,22 ,23 ,24 ,25 ,26 ,27 ,28 ,29 ,30,31};
    assert(bytesIn.size()== myKeysize); 
    dispBA(bytesIn, "Starting number");
    
    //-----does work for single en/decryption
    // Create Cipher numbers    
    //encryptBV(cbcEncryption, bytesIn, bytesCryp, true);    
    // Decrypt
    //decryptBV(cbcDecryption, bytesCryp, bytesDecr, true);
    
    int count = 42;
    for(int i=0; i < count; i++){       
        cbcEncryption.SetKeyWithIV(key, myKeysize, iv ); // ++
        encryptBV(cbcEncryption, bytesIn, bytesCryp); 
        cbcEncryption.SetKeyWithIV(key, myKeysize, iv ); // ++
        encryptBV(cbcEncryption, bytesCryp, bytesIn);
    }
    for(int i=0; i<count; i++){ 
        cbcDecryption.SetKeyWithIV(key, myKeysize, iv ); // ++
        decryptBV(cbcDecryption, bytesIn, bytesCryp);   
        cbcDecryption.SetKeyWithIV(key, myKeysize, iv ); // ++
        decryptBV(cbcDecryption, bytesCryp, bytesIn);
    }
    dispBA(bytesIn, "end"); // this does only return the correct value if lines marked with ++ are added
    
    //-----but it does also work if I repeat them without changing the inputs--- ["W2"]
    // Create Cipher numbers    
    //encryptBV(cbcEncryption, bytesIn, bytesCryp, true);    
    //encryptBV(cbcEncryption, bytesIn, bytesCryp, true);   
    // Decrypt
    //decryptBV(cbcDecryption, bytesCryp, bytesDecr, true);
    //decryptBV(cbcDecryption, bytesCryp, bytesDecr, true);


    return 0;
}

但是,目前这仅在我在每条消息后重置密钥(或生成新的 ExternalCipher)时才有效。我虽然密钥仅在单个(128,196,256 位)消息(或在长消息内)的轮次中更改,并且不会继续通过消息。

有没有更好的方法来做到这一点?或者如果我不更改输入,为什么会发生这种情况而不会发生(参见[“W2”])?

Here我发现了不同的操作模式。我猜这些是AES的不同实现。我应该使用某个吗? (编辑:欧洲央行?它不支持 afaik)

【问题讨论】:

  • 在这种情况下“莫迪”是什么意思?
  • @bmm6o 做了一些编辑,参考了cryptopp.com/wiki/Modes_of_Operation AES 使用密钥的方式有不同的类型
  • 我已经从Cryptography 迁移了这个问题,因为它依赖于通读代码。如果在执行期间更改了密钥,则这是特定于代码/库的,而不是 AES 算法定义的详细信息。 Crypto++ 是最常用的库之一,而且维护得很好。如果这是一个不错的选择,我会删除这个问题,因为这是固执己见(Crypto++ 确实有一种非常具体的工作方式)。
  • 顺便说一句,您可能需要重置 IV 而不是 CBC。在某些协议中,IV 取自消息的最后一个密文块,因此将“向量”保持在最后一个设置是有意义的。我不建议堆叠 CBC 加密。如果您只想加密另一个 128 位或 256 位的 AES 密钥,那么 ECB 就足够了。在这种情况下,您不需要静脉注射。如果您使用 AES,通常不需要多次加密密钥,但是您可以在 SIV 模式下使用 AES 或使用特定的 AES 密钥包装机制。
  • @MaartenBodewes SIV 模式?我认为crypto++不支持这一点。我不想以经典的方式使用它。它应该作为对称伪随机数生成器,每个元素都可以作为初始元素。给定两个数字,应该很难确定是否在同一个周期中。给定一个循环的两个随机元素,应该很难确定它们之间的步数。

标签: c++ encryption aes crypto++


【解决方案1】:

crypto++ Modes of Operation 没有列出 ECB 模式,但是! crypto++ 显示了一些 here 用这个我可以做一些小的重写:

//ecb
void encryptBV(CryptoPP::ECB_Mode< CryptoPP::AES >::Encryption &ecbEncryption, std::vector<byte> &bytesIn, std::vector<byte> &bytesCrypOut, bool disp=false){
    CryptoPP::StreamTransformationFilter stfEncryptor(ecbEncryption, new CryptoPP::ArraySink( &bytesCrypOut[0],bytesCrypOut.size()  ), CryptoPP::StreamTransformationFilter::NO_PADDING );
    stfEncryptor.Put(  &bytesIn[0], bytesIn.size() );
    stfEncryptor.MessageEnd();
    if(disp)dispBA(bytesCrypOut, "Cipher number");
}

void decryptBV(CryptoPP::ECB_Mode< CryptoPP::AES >::Decryption &ecbDecryption, std::vector<byte> &bytesCrypIn, std::vector<byte> &bytesDecrOut, bool disp=false){
    CryptoPP::StreamTransformationFilter stfDecryptor(ecbDecryption, new CryptoPP::ArraySink( &bytesDecrOut[0], bytesDecrOut.size()  ), CryptoPP::StreamTransformationFilter::NO_PADDING  );
    stfDecryptor.Put( &bytesCrypIn[0], bytesCrypIn.size() );
    stfDecryptor.MessageEnd();
    if(disp)dispBA(bytesDecrOut, "Decrypted number");
}
int main(int argc, char* argv[]) {

    //Key 32 bytes -> aes256
    //block size always 16
    const int myKeysize = 32;
    byte key[ myKeysize ], iv[ CryptoPP::AES::BLOCKSIZE ];
    memset( key, 0x00, myKeysize ); // no key set yet
    memset( iv, 0x00, CryptoPP::AES::BLOCKSIZE );
    CryptoPP::ECB_Mode< CryptoPP::AES >::Encryption ecbEncryption;
    ecbEncryption.SetKey( key, myKeysize);
    CryptoPP::ECB_Mode< CryptoPP::AES >::Decryption ecbDecryption;
    ecbDecryption.SetKey( key, myKeysize);
    std::vector<byte> bytesCryp(myKeysize);
    std::vector<byte> bytesDecr(myKeysize);

    std::vector<byte> bytesIn = {0 ,1, 2, 3, 4, 5 ,6 ,7 ,8 ,9 ,10 ,11, 12, 13 ,14 ,15 ,16, 17, 18 ,19 ,20 ,21 ,22 ,23 ,24 ,25 ,26 ,27 ,28 ,29 ,30,31};
    dispBA(bytesIn, "Starting number");

    //test single encrypt, decrypt
    encryptBV(ecbEncryption, bytesIn, bytesCryp, true);
    decryptBV(ecbDecryption, bytesCryp, bytesDecr, true);

    int count = 42;
    for(int i=0; i<count; i++){
        encryptBV(ecbEncryption, bytesIn, bytesCryp);
        encryptBV(ecbEncryption, bytesCryp, bytesIn);
    }
    for(int i=0; i<count; i++){
        decryptBV(ecbDecryption, bytesIn, bytesCryp);
        decryptBV(ecbDecryption, bytesCryp, bytesIn);
    }
    dispBA(bytesIn, "end");
}

它的运行速度也更快(大约 60%)。

警告:这对于正常的 AES 使用来说是不安全的。

(如果其他人找到更好的方法我可以更改正确答案)

【讨论】:

  • 我点击链接发现ECB是第一种方法:“ Crypto++提供多种操作模式,包括ECB ...”,它指向您发布的URL cryptopp.com/wiki/ECB_Mode
  • @MaartenBodewes 哎呀,我只检查了宽块密码部分中的列表
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-05
  • 1970-01-01
  • 1970-01-01
  • 2012-12-28
  • 2021-02-14
相关资源
最近更新 更多