执行RSA解密时无效的密文

时间:2015-07-11 17:31:13

标签: c++ crypto++

我使用以下代码加密和解密使用Crypto ++ 5.6.2库的字符串

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库一起使用。

这是它崩溃的路线:

StringSource ss( decoded, true,
                new PK_DecryptorFilter( rng, pri, new StringSink( decrypted_data )));

1 个答案:

答案 0 :(得分: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来电。

您可以通过以下方式查看公钥和私钥之间的区别(或缺少):

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_DecryptorA bad couple of years for the cryptographic token industry提供了一种无法治疗的治疗方法。