模板模式 object 和外部密码 object 有什么区别?

What's the difference between templated mode object and external cipher object?

如标题所示,我正在 cryptopp 库中寻找此声明之间的差异

CBC_Mode<AES>::Decryption 
cbcDecryption.SetKeyWithIV(key, AES::DEFAULT_KEYLENGTH, iv);

这个:

AES::Decryption aesDecryption(key, AES::DEFAULT_KEYLENGTH);
CBC_Mode_ExternalCipher::Decryption cbcDecryption( aesDecryption, iv );

此外,我不明白为什么会这样:

AES::Decryption aesDecryption(key, AES::DEFAULT_KEYLENGTH);
CBC_Mode_ExternalCipher::Decryption cbcDecryption( aesDecryption, iv );

StreamTransformationFilter stfDecryptor(
    cbcDecryption,
    new StringSink( recoveredtext )
);

stfDecryptor.Put( reinterpret_cast<const unsigned char*>( ciphertext.c_str() ), ciphertext.size() );
stfDecryptor.MessageEnd();

使用模板模式时一切正常 我在 运行 时间 :

期间出现此错误
AES128CBC: /usr/local/include/cryptopp/misc.h:304: void CryptoPP::memcpy_s(void*, size_t, const void*, size_t): Assertion `dest != __null' failed.
Aborted (core dumped)

应该不一样吧?

我看过 this 但我不太了解其中的区别,在网上搜索我找不到问题的答案。

What's the difference between templated mode object and external cipher object?

*_ExternalCiphers 的解释在 modes.h, and it shows up on the web in CipherModeDocumentation Class Reference 中给出。不太好找,我也是跟消息源密切合作才知道的。

这是正文:

Each class derived from this one [CipherModeDocumentation] defines two types, Encryption and Decryption, both of which implement the SymmetricCipher interface. For each mode there are two classes, one of which is a template class, and the other one has a name that ends in "_ExternalCipher".

The "external cipher" mode objects hold a reference to the underlying block cipher, instead of holding an instance of it. The reference must be passed in to the constructor. For the "cipher holder" classes, the CIPHER template parameter should be a class derived from BlockCipherDocumentation, for example DES or AES.

所以不同之处在于操作模式如何与密码相关联 - 外部与内部。

外部 - 下面是两个不同的 object。第一个是对称密码,第二个是运算方式:

AES::Encryption aes(key, ...);
CBC_Mode_ExternalCipher::Encryption cbc(aes, ...);

内部 - 下面是单个object。通过模板实例化的操作模式"has a"对称密码:

CBC_Mode<AES>::Encryption enc(key, ...);

all works fine while using the templated mode I have this error during run time...

好的,这是一个不同的问题。让我们看看如何使用它:

$ grep -IR "CBC_Mode_ExternalCipher::Decryption" *
fipstest.cpp:       KnownAnswerTest(CBC_Mode_ExternalCipher::Encryption(encryption, iv).Ref(), ...);
validat1.cpp:       CBC_Mode_ExternalCipher::Decryption modeD(desD, iv);
validat1.cpp:       CBC_Mode_ExternalCipher::Decryption modeD(desD, iv);
validat1.cpp:       CBC_Mode_ExternalCipher::Decryption modeD(desD, iv);
validat1.cpp:       CBC_Mode_ExternalCipher::Decryption modeD(desD, iv);

你可以找到validat1.cpp online, starting around line 1366:

bool ValidateCipherModes()
{
    ...
    DESEncryption desE(key);
    DESDecryption desD(key);

    ...
    CBC_Mode_ExternalCipher::Encryption modeE(desE, iv);
    ...
    CBC_Mode_ExternalCipher::Decryption modeD(desD, iv);
    ...
}

所以通配符是 DESEncryptionDESDecryption。让我们看看:

$ grep -IR DESEncryption *
des.h:typedef DES::Encryption DESEncryption;

所以 AES 应该 cut-in 干净。现在,测试程序:

#include "filters.h"
#include "osrng.h"
#include "modes.h"
#include "files.h"
#include "aes.h"
using namespace CryptoPP;

#include <iostream>
#include <string>
using namespace std;

// g++ -DNDEBUG -g2 -O2 -I. test.cxx ./libcryptopp.a -o test.exe
int main(int argc, char* argv[])
{
  AutoSeededRandomPool prng;
  string plain = "Now is the time for all good men to come to the aide of their country";
  string cipher, recover;

  SecByteBlock key(AES::DEFAULT_KEYLENGTH), iv(AES::BLOCKSIZE);
  prng.GenerateBlock(key, key.size());
  prng.GenerateBlock(iv, iv.size());

  AES::Encryption aes1(key, key.size());
  CBC_Mode_ExternalCipher::Encryption cbc1(aes1, iv);
  StringSource ss1(plain, true, new StreamTransformationFilter(cbc1, new StringSink(cipher)));

  AES::Decryption aes2(key, key.size());
  CBC_Mode_ExternalCipher::Decryption cbc2(aes2, iv);
  StringSource ss2(cipher, true, new StreamTransformationFilter(cbc2, new StringSink(recover)));

  cout << "Plain: " << plain << endl;
  cout << "Recover: " << recover << endl;

  return 0;
}

编译并运行:

$ g++ -DNDEBUG -g2 -O2 -I. test.cxx ./libcryptopp.a -o test.exe
$

$ ./test.exe
Plain: Now is the time for all good men to come to the aide of their country
Recover: Now is the time for all good men to come to the aide of their country

所以一切似乎都按预期工作。


现在,对于这个问题:

AES128CBC: /usr/local/include/cryptopp/misc.h:304: void CryptoPP::memcpy_s(void*, size_t, const void*, size_t):
Assertion `dest != __null' failed.

AES128 in CBC mode implementation using cryptopp library, you were told to use the latest Crypto++ library because we cleaned up a few of them. See this comment中:

You should use the latest version of the Crypto++ sources. I believe this issue was cleared some time ago: void CryptoPP::memcpy_s(void*, size_t, const void*, size_t): Assertion 'dest != __null' failed. You can get the latest sources with a git clone https://github.com/weidai11/cryptopp.git.

你也接受了Zaph's answer,所以你的解密和断言问题应该到此为止了。这向我和 Stack Overflow 社区表明您不需要额外的帮助或答案。

可能 运行 遇到的问题是将位于 /usr/local 的 Crypto++ 版本与您通过发行版安装的版本与 sudo apt-get install libcrypto++-dev libcrypto++-doc libcrypto++-utils。断言是混合和匹配它们的经典标志,因为发行版提供了旧版本的库。

如果你注意到我使用的命令行,你会看到:

  • -DNDEBUG -g2 -O2 以确保我使用与构建库相同的选项
  • -I 以确保我在 PWD
  • 中使用 Crypto++ headers
  • ./libcryptopp.a确保我link到PWD里的静态库,避免运行时间linking/loading用错库

您可能 运行 时间 link 使用了错误的 Crypto++ 库。我通过精确控制 linked 的内容来避免它们,而不是根据 运行 时间 link/loader.


您可以自由使用 运行 时间 link/loader 来做这些事情,但必须注意确保您在 运行 时间获得正确的库。为此,请参阅 GNUmakefile | Compiling and Linking。我认为您属于第二种情况,称为 BAD:

Bad: the following will create problems because you compile and link against your copy of the library, but at runtime it links to the distro's copy of the library:

$ ls
cryptopp        test.cxx

$ g++ -DNDEBUG -g2 -O2 -I . test.cxx -o test.exe -L ./cryptopp -lcryptopp

如果没有解决,那么你需要post一个Minimal, Complete, and Verifiable example (MCVE). It could well be that an assert fires under your data set. We had one recently at Trying to do CMAC on VS2013 and found this error. "Assertion failed: (input && length) || !(input || length)"。我们 checked-in 在不到 30 天前的报告后数小时内修复了问题。

我还需要查看您的编译和 link 命令,以及 ldd 的输出以了解您的 link 反对意见。

有时,如果您不提供明文或密文数据(input0.txtoutput0.txt),或者您不提供编译和编译等详细信息,我们将无能为力link命令。