AES / CBC加密和解密之间的速度差异?

时间:2013-11-23 16:01:51

标签: c++ cryptography aes benchmarking crypto++

理论上,我想知道在下列条件下,AES / CBC解密与AES / CBC加密相比要慢得多:

  • 32字节(256位)的加密密钥;
  • 16字节(128位)的块大小。

我问的原因是我想知道我所拥有的实现的解密速度是否异常缓慢。我已经对不同大小的随机内存块做了一些测试。结果如下:

64B:

enter image description here

64KB:

enter image description here

10MB - 520MB:

enter image description here

所有数据都存储在我系统的内部存储器中。应用程序生成要自行加密的数据。在测试PC上禁用虚拟内存,这样就不会有任何I / O调用。

分析表时,加密和解密之间的区别是否意味着我的实现异常缓慢?我做错了什么?

更新

  • 此测试在另一台电脑上执行;
  • 此测试使用随机数据执行;
  • Crypto ++用于AES / CBC加密和解密。

解密实现如下:

CryptoPP::AES::Decryption aesDecryption(aesKey, ENCRYPTION_KEY_SIZE_AES);
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, aesIv);

CryptoPP::ArraySink * decSink = new CryptoPP::ArraySink(data, dataSizeMax);
CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, decSink);
stfDecryptor.Put(reinterpret_cast<const unsigned char*>(ciphertext), cipherSize);
stfDecryptor.MessageEnd();

*dataOutputSize = decSink->TotalPutLength(); 

更新2:

  • 添加了64字节块的结果

3 个答案:

答案 0 :(得分:2)

作为对称加密,加密和解密应为fairly close in speed。不确定您的实施,但there are ways to optimize if you're concerned about how the algorithm was used。在实验中,AES is not the fastest and CBC会增加安全性,但会降低安全性。这是一个比较,因为你问的是密钥和块大小:

enter image description here

答案 1 :(得分:1)

  

分析表时,加密和解密之间的区别是否意味着我的实现异常缓慢?我做错了什么?

三四件事突然袭来。我有点同意@JamesKPolk - 数字看起来很像。首先,加密库通常用CTR模式标记,而不是CBC模式。另请参阅SUPERCOP benchmarks。任何你必须使用每字节周期数(cpb)来规范机器间的测量单位。在没有上下文的情况下说“9 MB / s”就没有任何意义。

其次,我们需要了解机器及其CPU频率。看起来您正在以9 MB / s的速度推送数据进行加密,并以6.5 MB / s的速度进行解密。现代iCore机器,如Core-i5 running at 2.7 GHz,将推动CBC模式数据大约2.5或3.0 cpb,大约980 MB / s或1 GB / s。即使我的旧Core2 Duo running at 2.0 GHz移动数据的速度也比您显示的速度快。 Core 2以14.5 cpb或130 MB / s的速度移动数据。

第三,废弃此代码。还有很大的改进空间,因此在这方面不值得批评;建议的代码如下。值得一提的是,您正在创建许多对象,例如ArraySourceStreamTransformationFilter。过滤器添加了填充,这会扰乱AES加密和解密基准并使结果发生偏差。您只需要一个加密对象,然后您只需拨打ProcessBlockProcessString

CryptoPP::AES::Decryption aesDecryption(aesKey, ENCRYPTION_KEY_SIZE_AES);
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, aesIv);
...

第四,Crypto ++ wiki有Benchmarks article,代码如下。这是一个新的部分,在您提出问题时无法使用。以下是如何进行测试。

AutoSeededRandomPool prng;
SecByteBlock key(16);
prng.GenerateBlock(key, key.size());

CTR_Mode<AES>::Encryption cipher;
cipher.SetKeyWithIV(key, key.size(), key);

const int BUF_SIZE = RoundUpToMultipleOf(2048U,
    dynamic_cast<StreamTransformation&>(cipher).OptimalBlockSize());

AlignedSecByteBlock buf(BUF_SIZE);
prng.GenerateBlock(buf, buf.size());

const double runTimeInSeconds = 3.0;
const double cpuFreq = 2.7 * 1000 * 1000 * 1000;
double elapsedTimeInSeconds;
unsigned long i=0, blocks=1;

ThreadUserTimer timer;
timer.StartTimer();

do
{
    blocks *= 2;
    for (; i<blocks; i++)
        cipher.ProcessString(buf, BUF_SIZE);
    elapsedTimeInSeconds = timer.ElapsedTimeAsDouble();
}
while (elapsedTimeInSeconds < runTimeInSeconds);

const double bytes = static_cast<double>(BUF_SIZE) * blocks;
const double ghz = cpuFreq / 1000 / 1000 / 1000;
const double mbs = bytes / 1024 / 1024 / elapsedTimeInSeconds;
const double cpb = elapsedTimeInSeconds * cpuFreq / bytes;

std::cout << cipher.AlgorithmName() << " benchmarks..." << std::endl;
std::cout << "  " << ghz << " GHz cpu frequency"  << std::endl;
std::cout << "  " << cpb << " cycles per byte (cpb)" << std::endl;
std::cout << "  " << mbs << " MiB per second (MiB)" << std::endl;

在2.7 GHz的Core-i5 6400上运行代码会导致:

$ ./bench.exe
AES/CTR benchmarks...
  2.7 GHz cpu frequency
  0.58228 cycles per byte (cpb)
  4422.13 MiB per second (MiB)

第五,当我修改上面显示的基准程序以操作64字节块时:

const int BUF_SIZE = 64;
unsigned int blocks = 0;
...

do
{
    blocks++;
    cipher.ProcessString(buf, BUF_SIZE);
    elapsedTimeInSeconds = timer.ElapsedTimeAsDouble();
}
while (elapsedTimeInSeconds < runTimeInSeconds);

对于64字节块的2.7 GHz,Core-i5 6400我看到3.4 cpb或760 MB / s。该库对小缓冲区有效,但大多数(所有?)库都有。

$ ./bench.exe
AES/CTR benchmarks...
  2.7 GHz cpu frequency
  3.39823 cycles per byte (cpb)
  757.723 MiB per second (MiB)

第六,您需要让处理器退出节能模式或低能耗状态,以获得最佳/最一致的结果。该库使用governor.sh在Linux上执行此操作。它位于TestScript/目录中。

第七,当我用:

切换到CTR模式解密时
CTR_Mode<AES>::Decryption cipher;
cipher.SetKeyWithIV(key, key.size(), key);

然后我看到批量解密的速率相同:

$ ./bench.exe
AES/CTR benchmarks...
  2.7 GHz cpu frequency
  0.579923 cycles per byte (cpb)
  4440.11 MiB per second (MiB)

Eigth,这是一系列不同机器上的基准数字集合。在调整测试时,它应该提供一个粗略的目标。

我的Beaglebone开发板运行速度为980 MHz,速度是您报告速度的两倍。 Beaglebone以20 MB / s的速度实现了40 cpb的无聊,因为它是星际C / C ++;而且没有针对A-32进行优化。

我的要点是:

  • CTR模式批量加密和解密在现代机器上大致相同
  • 点击率模式键设置不一样,现代机器上的解密需要更长时间
  • 小块尺寸比大块尺寸更贵

这是我期待看到的一切。

我认为您的下一步是使用Crypto ++ wiki上的the sample program收集一些数据,然后评估结果。

答案 2 :(得分:-2)

理论上,AES解密速度慢30%。这是Rijndael系统的一般属性。

来源:http://www4.ncsu.edu/~hartwig/Teaching/437/aes.pdf