c++ - 模板化模式对象和外部密码对象有什么区别?

标签 c++ cryptography cryptoapi crypto++

如标题所示,我正在寻找 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 中给出。 ,它显示在网络上的 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.

因此,区别在于操作模式与密码的关联方式 - 字面上是外部与内部。

外部 - 下面是两个不同的对象。第一个是对称密码,第二个是操作方式:

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

内部 - 下面是单个对象。操作模式“有一个”通过模板实例化的对称密码:

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 ,从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 应该干净利落地切入。现在,测试程序:

#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 ,您被告知使用最新的 Crypto++ 库,因为我们清理了其中的一些库。请参阅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++ header
  • ./libcryptopp.a 确保链接到 PWD 中库的静态版本,并避免运行时链接/加载错误的库

您可能在运行时链接了错误的 Crypto++ 库。我通过精确控制链接的内容来避免它们,而不是依赖于运行时链接/加载器。


您可以自由地使用运行时链接/加载器来执行这些操作,但必须注意确保您在运行时获得正确的库。为此,请参阅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

如果没有解决,那么您需要发布Minimal, Complete, and Verifiable example (MCVE) 。很可能在您的数据集下触发断言。我们最近有一个在Trying to do CMAC on VS2013 and found this error. "Assertion failed: (input && length) || !(input || length)" 。我们在收到报告后的几个小时内 checkin 了修复程序,距此还不到 30 天。

我还需要查看您的编译和链接命令以及 ldd 的输出,以了解您链接的内容。

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

关于c++ - 模板化模式对象和外部密码对象有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36247336/

相关文章:

java - 加密字节后从 Cipher 获取更新的 IV

java - 如何在Java中使用BouncyCaSTLe正确编码DH参数?

linux - 如何从缓冲区填充分散列表

c++ - float << 通过设置整数部分和浮点部分的精度来操作

C++ 返回但未存储的值会发生什么?

c++ - 无法从 C++ 中的类中访问私有(private)成员?

javascript - TweetNaCl.js 最小公钥签名示例

php - php 中的 RSA 令人困惑

winapi - 验证可执行文件的 Authenticode 签名时内存泄漏?

c++ - 可以从硬编码整数常量中删除 "LL"并替换为 "static_cast<uint64_t>(...)"吗?