我之前在我的程序中成功使用了这几行:
string tmp;
StringSource(msg, true, new PK_EncryptorFilter(*rng, *encryptor, new CryptoPP::HexEncoder(new StringSink(tmp))));
return tmp;
所以你知道Crypto ++对象是很好创建的。
现在我想加密整个二进制文件并将其保存到相邻的文件中:
FileSource(file.c_str(), true, new PK_EncryptorFilter(*rng, *encryptor, new FileSink((file+".xx").c_str(), true)),true);
但最后一行因调试错误而崩溃,说明 abort()已被调用。
解决错误,我试图将FileSource调用的第二个参数更改为false,从而导致以下代码:
FileSource(file.c_str(), false, new PK_EncryptorFilter(*rng, *encryptor, new FileSink((file+".xx").c_str(), true)),true);
然后错误消失了,但目标文件的权重为0字节,没有任何内容被读/写。
我不知道问题的关键是什么,所以,我希望有人可以帮一下。
编辑:我使用的是Visual Studio 2013专业版。
EDIT2:我进一步追捕错误。
这样可以正常打印文件二进制内容:
string s;
FileSource file2("C:\\test.jpg", true, new StringSink(s));
std::cout << s << std::endl;
但这不起作用,并以上述崩溃告终。
string s;
FileSource file2("C:\\test.jpg", true, new PK_EncryptorFilter(*rng, *encryptor, new StringSink (s)));
std::cout << s << std::endl;
这很奇怪,因为我在另一种方法中使用了相同的PK_EncryptorFilter过滤器,正如我在帖子开头所说的那样。
无论如何,我在这里发布了我的全班,以便清楚地了解发生了什么:
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);
}
编辑3:用try..catch()包围代码后出现此错误:
RSA/OAEP-MGF1(SHA-1): message length of 490986 exceeds the maximum of 214 for this public key
现在我认为这很容易解决。
答案 0 :(得分:3)
FileSource(file.c_str(), false,
new PK_EncryptorFilter(*rng, *encryptor,
new FileSink((file+".xx").c_str(), true)
),
true);
这看起来不对。 的指针。另外,还有一个额外的错误,我不习惯看到。类似的东西:new FileSink((file+".xx").c_str()
返回char*
,您需要指向Sink
FileSource fs1(filename, true,
new PK_EncryptorFilter(rng, encryptor,
new FileSink(filename, true)
) // PK_EncryptorFilter
); // StringSource
Crypto ++ wiki上有几个例子。请参阅RSA Cryptography和RSA Encryption Schemes。
以下是使用RSA的Crypto ++ wiki的示例。但是,您可以将代码用于符合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 );
另外,请勿使用匿名声明。某些版本的GCC存在问题。也就是说,使用:
StringSource ss1( plain, true,
...
而不是:
StringSource( plain, true,
...
答案 1 :(得分:0)
好的,我想我知道你可能遇到什么问题。但我需要看到所有您的代码,而不仅仅是加密。
我可以通过省略 BER Decode error
和encoder1.MessageEnd
来哄骗encoder2.MessageEnd
。显然,我能够在完全写入之前阅读密钥。我假设它在离开main
(并且运行析构函数)后完全写入,因为ls
文件大小看起来没问题。
在下面的代码中,邮件在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;
}
答案 2 :(得分:0)
我已经等待加密和安全主题,所以我不知道RSA方案的消息长度有限。 https://security.stackexchange.com/questions/44702/whats-the-limit-on-the-size-of-the-data-that-public-key-cryptos-can-handle
因此,解决方案通过实施集成或混合加密方案,如ECIES。
我使用:http://www.cryptopp.com/wiki/Elliptic_Curve_Integrated_Encryption_Scheme
成功地使用Crypto ++完成了这项工作感谢 jww 指出正确的决定。