模板化模式对象和外部密码对象有什么区别?
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)
不应该是一样的吗?
我看过这个,但我不太清楚其中的区别,在网上搜索时我找不到问题的答案。
模板模式对象和外部密码对象之间的区别是什么?
*_ExternalCiphers
的解释在modes.h
中给出,并在CipherModeDocumentation Class Reference
中显示在web上。它不容易找到,我之所以知道它,是因为我与消息来源密切合作。
文本如下:
从这个[CipherModeDocumentation]派生的每个类都定义了两种类型,加密和解密,这两种类型都实现了SymmetricCipher接口。对于每种模式,都有两个类,其中一个是模板类,另一个的名称以"_ExternalCipher"结尾。
"外部密码"模式对象包含对底层块密码的引用,而不是它的实例。该引用必须传递给构造函数。对于"密码持有者"类,cipher模板参数应该是从BlockCipherDocumentation派生的类,例如DES或AES。
因此,区别在于操作模式如何与密码相关联——从字面上讲是外部的还是内部的。
外部 -下面是两个不同的对象。第一种是对称密码,第二种是操作模式:
AES::Encryption aes(key, ...);
CBC_Mode_ExternalCipher::Encryption cbc(aes, ...);
内部-下面是单个对象。操作模式"有一个"通过模板实例化的对称密码:
CBC_Mode<AES>::Encryption enc(key, ...);
在使用模板模式时一切都很好我在运行时遇到了这个错误。。。
好吧,这是另一个问题。让我们看看如何使用它:
$ 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);
您可以在线找到validate1.cpp,从第1366:行开始
bool ValidateCipherModes()
{
...
DESEncryption desE(key);
DESDecryption desD(key);
...
CBC_Mode_ExternalCipher::Encryption modeE(desE, iv);
...
CBC_Mode_ExternalCipher::Decryption modeD(desD, iv);
...
}
所以通配符是DESEncryption
和DESDecryption
。让我们看看:
$ 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.
在CBC模式下使用cryptopp库实现的AES128中,您被告知要使用最新的Crypto++库,因为我们清理了其中的一些库。请参阅以下评论:
您应该使用最新版本的Crypto++源。我相信这个问题早就解决了:
void CryptoPP::memcpy_s(void*, size_t, const void*, size_t): Assertion 'dest != __null' failed
。您可以使用git clone https://github.com/weidai11/cryptopp.git
获取最新的来源。
你也接受了Zaph的回答,所以这应该是关于你的解密和断言问题的结束。这向我和Stack Overflow社区表明,您不需要额外的帮助或答案。
可能遇到的问题是,将位于/usr/local
的Crypto++版本与通过带有sudo apt-get install libcrypto++-dev libcrypto++-doc libcrypto++-utils
的发行版安装的版本混合。assert是混合和匹配它们的经典标志,因为发行版提供了库的旧版本。
如果你注意到我使用的命令行,你会看到:
-DNDEBUG -g2 -O2
以确保我使用与构建库相同的选项-I
以确保我在PWD中使用Crypto++标头./libcryptopp.a
确保我链接到PWD中库的静态版本,并避免运行时链接/加载错误的库
您可能在运行时链接到了错误的Crypto++库。我通过精确控制链接的内容来避免它们,而不依赖于运行时链接/加载程序。
您可以自由使用运行时链接/加载程序来执行这些操作,但必须注意确保在运行时获得正确的库。有关此信息,请参见GNUmakefile|编译和链接。我认为你在第二种情况下被称为BAD:
Bad:以下内容会产生问题,因为您根据库的副本进行编译和链接,但在运行时它会链接到发行版的库副本:
$ ls cryptopp test.cxx $ g++ -DNDEBUG -g2 -O2 -I . test.cxx -o test.exe -L ./cryptopp -lcryptopp
如果它没有解决,那么你需要发布一个最小、完整和可验证的例子(MCVE)。很可能是断言在您的数据集下触发。我们最近在VS2013上尝试进行CMAC时发现了一个错误。"断言失败:(input&&length)||!(input|| length)"。我们在报告发布后的几个小时内就签入了修复程序,而这还不到30天。
我还需要查看您的编译和链接命令,以及ldd
的输出,以查看您所链接的内容。
有时,如果您不提供纯文本或密文数据(input0.txt
和output0.txt
),或者您不提供诸如编译和链接命令之类的详细信息,我们就无能为力。
- 什么时候调用组成单元对象的析构函数
- 返回常量对象引用 (getter) 和仅返回字符串有什么区别?
- int数据类型的指针指向的是什么,如果是一个类的私有数据成员,我们创建了该类的两个对象?
- 是什么让放置新调用对象的构造函数?
- 当 std::move 与 C 样式数组或不移动对象时会发生什么
- 在什么情况下,两个堆栈分配的结构对象的 this 点指向同一个地址?
- 这个C++编译器优化(在自身的实例上调用对象自己的构造函数)的名称是什么,它是如何工作的?
- 什么更好?返回对象指针列表?或返回指向对象列表的指针?
- 在什么条件下使用 std::memcpy 在对象之间复制是安全的?
- 处理影响跨不同线程共享对象的定时回调的最佳方法是什么?
- 具有相同特征的两个对象是否只在内存中存储一次?无论定义它们的函数是什么,都是不同的
- 为对象分配整数.输出将是什么?
- 当使用对象名称后带有 [] 的类对象时,您究竟会传入什么.C++
- 什么是"undetectable means",它们如何更改 C/C++ 程序的对象?
- 在C++中,创建'n'数量的对象的推荐方法是什么,其中n是用户定义的。我该怎么做?
- 使用 gtest 框架在单元测试代码中检查目标对象的私有变量的最佳实践是什么?
- 删除对象(具有不同类型)的引用时会发生什么情况?
- 一个对象什么时候可以有非零大小的一个,但不能同时具有一个或多个字节的存储
- 在C++中,对象什么时候真正被销毁?delete(ptr)做什么
- C++在文件中保存类对象和从文件中读取类对象.什么是最好的选择