[英]Crash when trying to encrypt a file with Crypto++ RSA Scheme
I have successfully used this some lines ago in my program: 我在我的程序中成功地使用了这几行:
string tmp;
StringSource(msg, true, new PK_EncryptorFilter(*rng, *encryptor, new CryptoPP::HexEncoder(new StringSink(tmp))));
return tmp;
So you know that the Crypto++ objects are well created and so. 所以你知道Crypto ++对象是很好的创建的。
Now I want to encrypt a whole binary file and save it to an adjacent file: 现在我想加密整个二进制文件并将其保存到相邻文件:
FileSource(file.c_str(), true, new PK_EncryptorFilter(*rng, *encryptor, new FileSink((file+".xx").c_str(), true)),true);
But this last line crashes with a debug error stating that abort() has been called . 但最后一行崩溃时出现调试错误,表明已调用abort() 。
Hunting down the error, I tried to change the second argument to the FileSource call to false, leading to the following code: 解决错误,我试图将FileSource调用的第二个参数更改为false,从而导致以下代码:
FileSource(file.c_str(), false, new PK_EncryptorFilter(*rng, *encryptor, new FileSink((file+".xx").c_str(), true)),true);
And then the error gone, but the destination file weights 0 bytes, nothing was read/wrote. 然后错误消失了,但目标文件加权0字节,没有读/写。
I do not know what can can the key to the problem, so, I hope someone can help a little bit. 我不知道问题的关键是什么,所以,我希望有人可以帮助一点点。
EDIT: I am using Visual Studio 2013 Pro. 编辑:我正在使用Visual Studio 2013 Pro。
EDIT2: I hunted the error further. 编辑2:我进一步追捕错误。
This works and the file binary content is correctly printed on screen: 这有效,文件二进制内容正确打印在屏幕上:
string s;
FileSource file2("C:\\test.jpg", true, new StringSink(s));
std::cout << s << std::endl;
But this don't work and ends with the mentioned crash. 但这不起作用,并以提到的崩溃结束。
string s;
FileSource file2("C:\\test.jpg", true, new PK_EncryptorFilter(*rng, *encryptor, new StringSink (s)));
std::cout << s << std::endl;
This is so strange since the same PK_EncryptorFilter filter is used in another method without trouble, as I stated at the beginning of the post. 这很奇怪,因为相同的PK_EncryptorFilter过滤器在另一种方法中使用没有问题,正如我在帖子开头所说的那样。
Anyway, I post here my entire class, so as to get a clear idea of what is going on: 无论如何,我在这里发布我的全班,以便清楚地知道发生了什么:
RSASystem::RSASystem()
{
std::string pubkey = "...OMITED...";
rng = new AutoSeededRandomPool;
CryptoPP::HexDecoder decoder;
decoder.Put((byte*)pubkey.c_str(), pubkey.size());
decoder.MessageEnd();
CryptoPP::HexDecoder decoder2;
decoder2.Put((byte*)pubkey.c_str(), pubkey.size());
decoder2.MessageEnd();
verifier = new RSASSA_PKCS1v15_SHA_Verifier;
encryptor = new RSAES_OAEP_SHA_Encryptor;
verifier->AccessKey().Load(decoder);
encryptor->AccessKey().Load(decoder2);
}
string RSASystem::encrypt(string msg)
{
string tmp;
StringSource(msg, true, new PK_EncryptorFilter(*rng, *encryptor, new CryptoPP::HexEncoder(new StringSink(tmp))));
return tmp;
}
void RSASystem::encryptFile(string file)
{
FileSource(file.c_str(), true, new PK_EncryptorFilter(*rng, *encryptor, new FileSink((file+".xx").c_str(), true)),true);
}
EDIT 3: After surrounding the code with try..catch() I got this error: 编辑3:用try..catch()包围代码后,我收到此错误:
RSA/OAEP-MGF1(SHA-1): message length of 490986 exceeds the maximum of 214 for this public key
Which now I think can be easily solved. 现在我觉得这很容易解决。
FileSource(file.c_str(), false,
new PK_EncryptorFilter(*rng, *encryptor,
new FileSink((file+".xx").c_str(), true)
),
true);
This does not look right. 这看起来不对。
. Plus, there's an extra false in there I'm not used to seeing. Something like:
new FileSink((file+".xx").c_str()
returns a
char*
, and you need a pointer to a
Sink
。另外,还有一个额外的假,我不习惯看到。有点像: new FileSink((file+".xx").c_str()
返回一个
char*
,你需要一个指向
Sink
的指针
FileSource fs1(filename, true,
new PK_EncryptorFilter(rng, encryptor,
new FileSink(filename, true)
) // PK_EncryptorFilter
); // StringSource
There's a couple of examples on the Crypto++ wiki. Crypto ++ wiki上有几个例子。 See RSA Cryptography and RSA Encryption Schemes . 请参阅RSA加密和RSA加密方案 。
The following is an example from the Crypto++ wiki using RSA. 以下是使用RSA的Crypto ++ wiki的示例。 But you can use the code for any cryptosystem that adheres to PK_Encryptor
and PK_Decryptor
( Sources
(like StringSource
and FileSource
) and Sinks
(like StringSink
and FileSink
) are also interchangeable): 但您可以将代码用于任何符合PK_Encryptor
和PK_Decryptor
密码系统( Sources
(如StringSource
和FileSource
)和Sinks
(如StringSink
和FileSink
)也可以互换):
////////////////////////////////////////////////
// Generate keys
AutoSeededRandomPool rng;
InvertibleRSAFunction params;
params.GenerateRandomWithKeySize( rng, 1536 );
RSA::PrivateKey privateKey( params );
RSA::PublicKey publicKey( params );
string plain="RSA Encryption", cipher, recovered;
////////////////////////////////////////////////
// Encryption
RSAES_OAEP_SHA_Encryptor e( publicKey );
StringSource ss1( plain, true,
new PK_EncryptorFilter( rng, e,
new StringSink( cipher )
) // PK_EncryptorFilter
); // StringSource
////////////////////////////////////////////////
// Decryption
RSAES_OAEP_SHA_Decryptor d( privateKey );
StringSource ss2( cipher, true,
new PK_DecryptorFilter( rng, d,
new StringSink( recovered )
) // PK_DecryptorFilter
); // StringSource
assert( plain == recovered );
Also, don't use anonymous declarations. 另外,不要使用匿名声明。 Some versions of GCC has problems with them. 某些版本的GCC存在问题。 That is, use: 也就是说,使用:
StringSource ss1( plain, true,
...
rather than: 而不是:
StringSource( plain, true,
...
OK, I think I know where you might be having problems. 好的,我想我知道你可能遇到问题的地方。 But I'd need to see all your code and not just the encryption. 但我需要查看所有代码,而不仅仅是加密。
I could coax a BER Decode error
by omitting encoder1.MessageEnd
and encoder2.MessageEnd
. 我可以通过省略 encoder1.MessageEnd
和encoder2.MessageEnd
来哄骗BER Decode error
。 Apparently, I was able to read the key before it was fully written. 显然,我能够在完全写入之前阅读密钥。 I assume it was fully written after leaving main
(and the destructors ran) because the file sizes looked OK with ls
. 我假设它在离开main
(和析构函数运行)之后完全写入,因为文件大小看起来很好用ls
。
In the code below, the message was encrypted under publicKey1
and then decrypted with privateKey2
to ensure the keys were round-tripping. 在下面的代码中,消息在publicKey1
下加密,然后使用privateKey2
解密,以确保密钥是往返的。
try {
////////////////////////////////////////////////
// Generate keys
AutoSeededRandomPool rng;
InvertibleRSAFunction params;
params.GenerateRandomWithKeySize(rng, 1024);
RSA::PrivateKey privateKey1(params);
RSA::PublicKey publicKey1(privateKey1);
////////////////////////////////////////////////
// Save/Load keys
HexEncoder encoder1(new FileSink("private-key-der.txt", true));
HexEncoder encoder2(new FileSink("public-key-der.txt", true));
privateKey1.Save(encoder1);
publicKey1.Save(encoder2);
// Must have these. Otherwise, the full key (hex encoded)
// is not written until destructors are run
encoder1.MessageEnd();
encoder2.MessageEnd();
FileSource fs1("private-key-der.txt", true, new HexDecoder);
FileSource fs2("public-key-der.txt", true, new HexDecoder);
RSA::PrivateKey privateKey2;
RSA::PublicKey publicKey2;
privateKey2.Load(fs1);
bool valid = privateKey2.Validate(rng, 3);
if(!valid)
throw Exception(Exception::OTHER_ERROR, "Failed to validate key 1");
publicKey2.Load(fs2);
valid = publicKey2.Validate(rng, 3);
if(!valid)
throw Exception(Exception::OTHER_ERROR, "Failed to validate key 2");
////////////////////////////////////////////////
// Scratch
string plain="RSA Encryption", cipher, recovered;
////////////////////////////////////////////////
// Encryption
RSAES_OAEP_SHA_Encryptor encryptor(publicKey1);
StringSource ss1(plain, true,
new PK_EncryptorFilter(rng, encryptor,
new StringSink(cipher)
) // PK_EncryptorFilter
); // StringSource
////////////////////////////////////////////////
// Decryption
RSAES_OAEP_SHA_Decryptor decryptor(privateKey2);
StringSource ss2(cipher, true,
new PK_DecryptorFilter(rng, decryptor,
new StringSink(recovered)
) // PK_DecryptorFilter
); // StringSource
cout << "Recovered plain text: " << recovered << endl;
} catch (const Exception& ex) {
cerr << ex.what() << endl;
}
I had already pending the encryption and security subject so I wasn't aware of the limitation on the length of the message of the RSA scheme. 我已经等待加密和安全主题,所以我不知道对RSA方案的消息长度的限制。 https://security.stackexchange.com/questions/44702/whats-the-limit-on-the-size-of-the-data-that-public-key-cryptos-can-handle https://security.stackexchange.com/questions/44702/whats-the-limit-on-the-size-of-the-data-that-public-key-cryptos-can-handle
So the solution passes by implementing an Integrated or Hybrid Encryption Scheme, like ECIES. 因此,解决方案通过实施集成或混合加密方案,如ECIES。
I've done this successfully with Crypto++ using: http://www.cryptopp.com/wiki/Elliptic_Curve_Integrated_Encryption_Scheme 我使用Crypto ++成功完成了这项工作: http : //www.cryptopp.com/wiki/Elliptic_Curve_Integrated_Encryption_Scheme
Thanks to jww to point to the correct decision. 感谢jww指出正确的决定。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.