2015-07-11 89 views
2

我用下面的代碼進行加密和解密的字符串利用加密++ 5.6.2庫無效的密文進行時,RSA解密

string to_BER(string spriv,bool b)  
{ 
    string HEADER, FOOTER; 

    if(b) 
    { 
     HEADER = "-----BEGIN RSA PRIVATE KEY-----"; 
     FOOTER = "-----END RSA PRIVATE KEY-----"; 
    } 
    else 
    { 
     HEADER = "-----BEGIN PUBLIC KEY-----"; 
     FOOTER = "-----END PUBLIC KEY-----"; 
    } 

     size_t pos1, pos2; 
     pos1 = spriv.find(HEADER); 
     if(pos1 == string::npos) 
      throw std::runtime_error("PEM header not found"); 

     pos2 = spriv.find(FOOTER, pos1+1); 
     if(pos2 == string::npos) 
      throw std::runtime_error("PEM footer not found"); 

     // Start position and length 
     pos1 = pos1 + HEADER.length(); 
     pos2 = pos2 - pos1; 
     string keystr = spriv.substr(pos1, pos2); 

     return keystr; 
} 

string rsa_encrypt(const string &message, const string &public_key) 
{  
    string keystr=to_BER(public_key,false); 

    ByteQueue queue; 
    Base64Decoder decoder; 

    decoder.Attach(new Redirector(queue)); 
    decoder.Put((const byte*)keystr.data(), keystr.length()); 
    decoder.MessageEnd(); 

    RSAES_PKCS1v15_Encryptor e; 
    e.AccessKey().Load(queue); 

    bool key_ok = e.AccessKey().Validate(rng, 3); 
    if(!key_ok) 
    { 
     printf("ERROR IN RSA KEY\n"); 
     return ""; 
    } 

    string encrypted_data; 

    StringSource ss1(message, true, 
     new PK_EncryptorFilter(rng, e, 
      new StringSink(encrypted_data) 
     ) // PK_EncryptorFilter 
    ); // StringSource 

    return encrypted_data; 
} 

string rsa_decrypt(const string &message, const string &private_key,bool b_Base64decode) 
{ 
    string keystr=to_BER(private_key,true); 

    string decoded=message; 

    if(b_Base64decode) 
    { 
     Base64Decoder decoder; 

     decoder.Put((byte*)message.data(), message.size()); 
     decoder.MessageEnd(); 

     word64 size = decoder.MaxRetrievable(); 
     if(size && size <= SIZE_MAX) 
     { 
      decoded.resize(size); 
      decoder.Get((byte*)decoded.data(), decoded.size()); 
     } 
    } 

    RSAES_PKCS1v15_Decryptor pri(rng, 1024); 
    TransparentFilter privSink(new StringSink(keystr)); 
    pri.DEREncode(privSink); 
    privSink.MessageEnd();    

    string decrypted_data; 
    try 
    { 

    StringSource ss(decoded, true, 
      new PK_DecryptorFilter(rng, pri, new StringSink(decrypted_data))); 
    } 
    catch(Exception *e) 
    { 
     printf("ERROR DECRYPTING RSA\n"); 
     return ""; 
    } 

    return decrypted_data; 
} 

然後我用這個代碼:

string enc=rsa_encrypt("hola mundo","-----BEGIN PUBLIC KEY----- MIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgHIiecdmRAaiTrCbbEOLBPh+fxp2KyGWyMTeWIj56NRk1CFLfBDT6vOWDceFpuTcrAFGR4Np4JLsssqM24F7bZCKv6eQCV8Xjv6GJiGofKEkI4b0zwHHEwq63p+9Rb5jYXlPZ7JIud7Yi96CHbg3foLQzZSSS9oFItGOFF0jDM7lAgMBAAE= -----END PUBLIC KEY-----"); 

string aaa=rsa_decrypt(
      /*"YTbXg1K4OlXGY6eaLuVTFZrN4qi1zg83h0PjeLd9F3Ge3gKUHsJpoE3iLv1+Gj/PepM8ehiilb5kphxCdcELjaYH9wwYHMpUZUQSRLQUTnofOboI6nfHaKnnNV28QMguM39q1hm7X1wNc69D8R+CkWLka2rQof+BXt+41ivnMj8=",*/ 
      enc 
      ,"-----BEGIN RSA PRIVATE KEY----- MIICWwIBAAKBgHIiecdmRAaiTrCbbEOLBPh+fxp2KyGWyMTeWIj56NRk1CFLfBDT6vOWDceFpuTcrAFGR4Np4JLsssqM24F7bZCKv6eQCV8Xjv6GJiGofKEkI4b0zwHHEwq63p+9Rb5jYXlPZ7JIud7Yi96CHbg3foLQzZSSS9oFItGOFF0jDM7lAgMBAAECgYBxFL9bVHNprz4PtK3bbc2K9qmv6gxpxx88Dp/hdtm8NfoG0uclNRHALZeRa1Yjwo+Y46zPAwPCDkpGbLC+5S9zfBjtrx/+8zjTyMVb2CcGLfR0H2E/hcCjADXNxs+fmpB3+jyPhgH5ANaTmAXqGXOP56I0Fqo8xCfU/zQELCtzMQJBAN2Kq+9bQW3nKAAJEZqWQlAEjuBQfe1lrvLxc/AgVl9XLWrHre7HSlkyqcFemvqhzlZy1wz0Nv5VpOIGcAKefEMCQQCD4xSbkF1kzZyj8k6P3iUW6ezaK4krOZnpq/wDyOtj0DBAtLt3apyv3BUbe7AH1e8llJ5a8UYVHlsOdRUio+m3AkAB0LYR8wR5OxCn12sughavAyqMifxOKqwhT3sst4cdpuA3ZMV3FGj2jCS58eWBMjw3lx9N+t5MfTUpqPXX/6ZzAkBx9eTXqv3YXYZtb7GMxQI9c3Jy7k1/aS1iaXbA+nrTa5BWSRT30cqEduJSNiVcD/KuAWZ35KWPGATMUEUsAoCvAkEAuVg0OA6L3xJphKEbVYXvTwXrXcoVjjLDnNYjUJuNWrFFjBuNE4whWvdg76Panw3vMhgFc6yVr+VE5XOc7rXPvA== -----END RSA PRIVATE KEY-----" 
      ,false 
      ); 

問題是rsa_decrypt失敗並帶有try/catch代碼未捕獲的「無效密文」異常。該程序崩潰。 我想知道我的代碼有什麼問題,即使密文錯誤,我如何避免程序崩潰。 我找到了類似的線程(crypto++ RSA and "invalid ciphertext"),但沒有一個解決方案對我有效:在字符串末尾沒有看到任何0的問題,我檢查鍵是否有效,我知道私有和公共密鑰來自同一個密鑰對,並且與其他RSA庫一起工作。

這行是它崩潰:

​​
+0

與'to_BER'函數相關的是社區爲PEM提供的一個庫補丁。它不是圖書館的一部分;您必須使用Crypto ++源代碼將其放入,然後編譯該庫。請參閱Crypto ++ wiki上的[PEM Pack](http://www.cryptopp.com/wiki/PEM_Pack)。 – jww

回答

1

的問題是,rsa_decrypt失敗,出現 「無效密文」 異常

您創建一個私鑰,然後將其編碼爲keystr

RSAES_PKCS1v15_Decryptor pri(rng, 1024); 
TransparentFilter privSink(new StringSink(keystr)); 
pri.DEREncode(privSink); 

相反,你應該使用private_key(而不是新的鍵),這樣做你的加密所做的:

string keystr=to_BER(private_key,true); 

ByteQueue queue; 
Base64Decoder decoder; 

decoder.Attach(new Redirector(queue)); 
decoder.Put((const byte*)keystr.data(), keystr.length()); 
decoder.MessageEnd(); 

RSAES_PKCS1v15_Decryptor d; 
d.AccessKey().Load(queue); 

...這是不是抓住了...

在try/catch塊包裹一切,而不僅僅是PK_DecryptorFilter電話。


你可以看到類似的公鑰和私鑰之間的差異(或lackof):

try { 

    string s1("-----BEGIN PUBLIC KEY-----\n" 
       "MIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgHIiecdmRAai" 
       "TrCbbEOLBPh+fxp2KyGWyMTeWIj56NRk1CFLfBDT6vOWDceF" 
       "puTcrAFGR4Np4JLsssqM24F7bZCKv6eQCV8Xjv6GJiGofKEk" 
       "I4b0zwHHEwq63p+9Rb5jYXlPZ7JIud7Yi96CHbg3foLQzZSS" 
       "S9oFItGOFF0jDM7lAgMBAAE=" 
       "\n-----END PUBLIC KEY-----"); 
    string s2("-----BEGIN RSA PRIVATE KEY-----\n" 
       "MIICWwIBAAKBgHIiecdmRAaiTrCbbEOLBPh+fxp2KyGWyMTeWIj" 
       "56NRk1CFLfBDT6vOWDceFpuTcrAFGR4Np4JLsssqM24F7bZCKv6" 
       "eQCV8Xjv6GJiGofKEkI4b0zwHHEwq63p+9Rb5jYXlPZ7JIud7Yi" 
       "96CHbg3foLQzZSSS9oFItGOFF0jDM7lAgMBAAECgYBxFL9bVHNp" 
       "rz4PtK3bbc2K9qmv6gxpxx88Dp/hdtm8NfoG0uclNRHALZeRa1Y" 
       "jwo+Y46zPAwPCDkpGbLC+5S9zfBjtrx/+8zjTyMVb2CcGLfR0H2" 
       "E/hcCjADXNxs+fmpB3+jyPhgH5ANaTmAXqGXOP56I0Fqo8xCfU/" 
       "zQELCtzMQJBAN2Kq+9bQW3nKAAJEZqWQlAEjuBQfe1lrvLxc/Ag" 
       "Vl9XLWrHre7HSlkyqcFemvqhzlZy1wz0Nv5VpOIGcAKefEMCQQC" 
       "D4xSbkF1kzZyj8k6P3iUW6ezaK4krOZnpq/wDyOtj0DBAtLt3ap" 
       "yv3BUbe7AH1e8llJ5a8UYVHlsOdRUio+m3AkAB0LYR8wR5OxCn1" 
       "2sughavAyqMifxOKqwhT3sst4cdpuA3ZMV3FGj2jCS58eWBMjw3" 
       "lx9N+t5MfTUpqPXX/6ZzAkBx9eTXqv3YXYZtb7GMxQI9c3Jy7k1" 
       "/aS1iaXbA+nrTa5BWSRT30cqEduJSNiVcD/KuAWZ35KWPGATMUE" 
       "UsAoCvAkEAuVg0OA6L3xJphKEbVYXvTwXrXcoVjjLDnNYjUJuNW" 
       "rFFjBuNE4whWvdg76Panw3vMhgFc6yVr+VE5XOc7rXPvA==" 
       "\n-----END RSA PRIVATE KEY-----"); 

    ArraySource as1(s1, true), as2(s2, true); 

    RSA::PublicKey k1; 
    RSA::PrivateKey k2; 

    PEM_Load(as1, k1); 
    PEM_Load(as2, k2); 

    AutoSeededRandomPool prng; 
    k1.ThrowIfInvalid(prng, 3); 
    k2.ThrowIfInvalid(prng, 3); 

    Integer i1 = k1.GetModulus() - k2.GetModulus(); 
    Integer i2 = k1.GetPublicExponent() - k2.GetPublicExponent(); 

    cout << i1 << " " << i2 << endl; 

} catch (const Exception& ex) { 
    cerr << ex.what() << endl; 
} 

相關,封裝邊界(-----BEGIN PUBLIC KEY----------END PUBLIC KEY-----)應該對他們的自己的路線。而不是空格,你應該使用一個新行(\n)。因此,像:

string enc=rsa_encrypt(
    "hola mundo", 
    "-----BEGIN PUBLIC KEY-----\nMIGeMA0G...gMBAAE=\n-----END PUBLIC KEY-----" 
    ); 

和:

string aaa=rsa_decrypt(
    enc, 
    "-----BEGIN RSA PRIVATE KEY-----\nMIICWwIB...7rXPvA==\n-----END RSA PRIVATE KEY-----", 
    false 
    ); 

相關,你應該使用RSAES_OAEP_SHA_EncryptorRSAES_OAEP_SHA_Decryptor。可在A bad couple of years for the cryptographic token industry處獲得可用的治療。

+0

它工作,如果我使用PEM_LOAD,如果我使用d.AccessKey()。加載(隊列)它失敗,無論我如何寫密鑰字符串。 BERDecodeErr異常(或類似的東西)。關於catch,如果我使用一個指針(Exception * e),它不會捕獲異常,但是如果我使用Exception&e,它就會起作用。 – juanjo75es

+0

我使用RSAES_PKCS1v15_Decryptor,因爲編碼是由另一個只支持PKCS1 – juanjo75es

+0

的軟件完成*「它可以工作,如果我使用PEM_LOAD ...」* - 如果你不介意,然後堅持[PEM Pack](http:///www.cryptopp.com/wiki/PEM_Pack)。我寫了它,所以它會被支持。我打算建議將它添加到庫的未來版本中。 (目前的時間並不正確,因爲我們正在處理其他事情)。 – jww