5

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

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

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

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

4

2 回答 2

4

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

当您知道在哪里查找时,这很容易:来自 Crypto++ wiki 的原始 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,因此对明文大小和密文大小有一些限制。本质上,m并且c必须小于n。在此示例中,将字符串替换为secretnow is the time for all good men to come to the aid of their country失败,因为它比n转换为Integer.

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


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

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

于 2013-10-04T02:15:17.920 回答
2

这是我第一次使用 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 );
}
于 2012-03-23T03:01:31.713 回答