【问题标题】:RAW RSA encryption and decryption with Crypto++使用 Crypto++ 进行 RAW RSA 加密和解密
【发布时间】:2012-04-07 16:17:01
【问题描述】:

我需要在 PC 和支持 RSA 加密和使用 SHA1 签名的设备之间建立安全通信。因为我已经在我的应用程序的其他部分使用了 Crypto++,所以我也想使用 Crypto++。

该设备非常原始,但允许执行我在其上编写的程序。它内置了原始的 RSA 和 SHAa 函数;但是,它可以使用的内存非常少,准确地说是 2K 字节。

我必须对来自 PC 的消息进行加密和签名。然后设备解密并验证消息。然后设备将回复一条加密消息并在其上签名。 PC 将解密该消息并随后对其进行验证。我已经使用内置函数在设备内部使用 SHA1 实现了原始 RSA 加密、签名和验证。消息足够短,可以在一轮中完成。

但是,我不知道如何在不涉及 OAEP 或 PKCS#1 的情况下使用 Crypto++ 使用原始 RSA 加密消息。有人可以向我展示一些示例代码吗?非常感谢!

【问题讨论】:

    标签: rsa crypto++


    【解决方案1】:

    这是我第一次使用 Crypto++ 进行 RSA 加密和解密时编写的演示函数。我写它只是为了了解基础知识。希望对您有所帮助:

    #include <cryptopp/files.h>
    #include <cryptopp/modes.h>
    #include <cryptopp/osrng.h>
    #include <cryptopp/rsa.h>
    #include <cryptopp/sha.h>
    
    using namespace CryptoPP;
    
    void rsa_examples()
    {
        // Keys created here may be used by OpenSSL.
        //
        // openssl pkcs8 -in key.der -inform DER -out key.pem -nocrypt 
        // openssl rsa -in key.pem -check
    
        AutoSeededRandomPool rng;
    
        // Create a private RSA key and write it to a file using DER.
        RSAES_OAEP_SHA_Decryptor priv( rng, 4096 );
        TransparentFilter privFile( new FileSink("rsakey.der") );
        priv.DEREncode( privFile );
        privFile.MessageEnd();
    
        // Create a private RSA key and write it to a string using DER (also write to a file to check it with OpenSSL).
        std::string the_key;
        RSAES_OAEP_SHA_Decryptor pri( rng, 2048 );
        TransparentFilter privSink( new StringSink(the_key) );
        pri.DEREncode( privSink );
        privSink.MessageEnd();
    
        std::ofstream file ( "key.der", std::ios::out | std::ios::binary );
        file.write( the_key.data(), the_key.size() );
        file.close();
    
        // Example Encryption & Decryption
        InvertibleRSAFunction params;
        params.GenerateRandomWithKeySize( rng, 1536 );
    
        std::string plain = "RSA Encryption", cipher, decrypted_data;
    
        RSA::PrivateKey privateKey( params );
        RSA::PublicKey publicKey( params );
    
        RSAES_OAEP_SHA_Encryptor e( publicKey );
        StringSource( plain, true, new PK_EncryptorFilter( rng, e, new StringSink( cipher )));
    
        RSAES_OAEP_SHA_Decryptor d( privateKey );
        StringSource( cipher, true, new PK_DecryptorFilter( rng, d, new StringSink( decrypted_keydata )));
    
        assert( plain == decrypted_data );
    }
    

    【讨论】:

    • 感谢您的代码。我理解你的代码。但是,我的情况有点不同。
    • 该代码执行 RSA 加密和解密。如果这不是你想要的,我就删除它。
    • 抱歉评论是用回车键发布的,但我只是想插入一行。我已进一步阐述了我在该主题中的情况以供批准。我真的很感谢你的帮助。 ^_^
    【解决方案2】:

    我不知道如何使用 Crypto++ 使用原始 RSA 加密消息,而无需 涉及 OAEP 或 PKCS#1。有人可以给我一些示例代码吗?

    当您知道在哪里查找时,这很容易:来自 Crypto++ wiki 的 Raw RSA。下面的代码取自页面。


    加密

    Integer n("0xbeaadb3d839f3b5f"), e("0x11"), d("0x21a5ae37b9959db9");
    
    RSA::PublicKey pubKey;
    pubKey.Initialize(n, e);
    
    ///////////////////////////////////////////////////////////////
    
    Integer m, c;
    string message = "secret";  
    
    cout << "message: " << message << endl;
    
    // Treat the message as a big endian byte array
    m = Integer((const byte *)message.data(), message.size());
    cout << "m: " << hex << m << endl;
    
    // Encrypt
    c = pubKey.ApplyFunction(m);
    cout << "c: " << hex << c << endl;
    

    解密

    Integer n("0xbeaadb3d839f3b5f"), e("0x11"), d("0x21a5ae37b9959db9");
    AutoSeededRandomPool prng;
    
    RSA::PrivateKey privKey;
    privKey.Initialize(n, e, d);
    
    ///////////////////////////////////////////////////////////////
    
    Integer c("0x3f47c32e8e17e291"), r;
    string recovered;
    
    // Decrypt
    r = privKey.CalculateInverse(prng, c);
    cout << "r: " << hex << r << endl;
    
    // Round trip the message
    size_t req = r.MinEncodedSize();
    recovered.resize(req);
    r.Encode((byte *)recovered.data(), recovered.size());
    
    cout << "recovered: " << recovered << endl;
    

    这是一个示例输出:

    $ ./cryptopp-raw-rsa.exe
    message: secret
    m: 736563726574h
    c: 3f47c32e8e17e291h
    r: 736563726574h
    recovered: secret
    

    有一个警告:c = m ^ e mod n,因此对明文大小和密文大小有一些限制。本质上,mc 必须小于n。在此示例中,将字符串 secret 替换为 now is the time for all good men to come to the aid of their country 会失败,因为在转换为 Integer 时它大于 n

    您可以使用MaxPreImage()函数获取最大纯文本大小,使用MaxImage()获取最大密文大小。


    我必须对来自 PC 的消息进行加密和签名。然后设备解密 并验证消息。然后设备将回复一条加密消息 并在上面签名。 PC 将解密该消息并随后对其进行验证。

    从表面上看,这看起来会遭受重放攻击。您可能需要具有保护功能的协议。

    【讨论】:

    • m = Integer((const byte *)message.data(), message.size()); 谁能解释一下大端字节*如何转换为整数?
    • @Laxman - byte*, size 对被包裹在 Store 中,这给了它一个 BufferedTransformation 前端。然后调用Integer::Decode。另见integer.cpp : 3356
    猜你喜欢
    • 2018-06-26
    • 2014-11-10
    • 1970-01-01
    • 1970-01-01
    • 2017-07-02
    • 2013-11-06
    • 1970-01-01
    • 1970-01-01
    • 2019-06-26
    相关资源
    最近更新 更多