簡體   English   中英

嘗試使用Crypto ++ RSA Scheme加密文件時崩潰

[英]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_EncryptorPK_Decryptor密碼系統( Sources (如StringSourceFileSource )和Sinks (如StringSinkFileSink )也可以互換):

////////////////////////////////////////////////
// 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.MessageEndencoder2.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM