[英]Crash when trying to encrypt a file with Crypto++ RSA Scheme
我在我的程序中成功地使用了這幾行:
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 Pro。
編輯2:我進一步追捕錯誤。
這有效,文件二進制內容正確打印在屏幕上:
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
現在我覺得這很容易解決。
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加密和RSA加密方案 。
以下是使用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,
...
好的,我想我知道你可能遇到問題的地方。 但我需要查看所有代碼,而不僅僅是加密。
我可以通過省略 encoder1.MessageEnd
和encoder2.MessageEnd
來哄騙BER Decode error
。 顯然,我能夠在完全寫入之前閱讀密鑰。 我假設它在離開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;
}
我已經等待加密和安全主題,所以我不知道對RSA方案的消息長度的限制。 https://security.stackexchange.com/questions/44702/whats-the-limit-on-the-size-of-the-data-that-public-key-cryptos-can-handle
因此,解決方案通過實施集成或混合加密方案,如ECIES。
我使用Crypto ++成功完成了這項工作: http : //www.cryptopp.com/wiki/Elliptic_Curve_Integrated_Encryption_Scheme
感謝jww指出正確的決定。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.