我使用以下代码用OpenSSL
加密C ++中的字符串,并且只有当文本达到256
字节时它才能正常工作,它不适用于更大的尺寸:
void encrypt(char* message, int sourceSzie, char* encryptedMessage, int &destSize)
{
char err[130];
RSA *rsa_pubkey = NULL;
FILE *rsa_pub_file = fopen("pubkey_file.bin", "rb");
if(PEM_read_RSAPublicKey(rsa_pub_file, &rsa_pubkey, NULL, NULL) == NULL)
{
printf("Error reading public key \n");
}
if((destSize = RSA_public_encrypt(sourceSzie, (unsigned char*)message, (unsigned char*)encryptedMessage, rsa_pubkey, RSA_PKCS1_OAEP_PADDING)) == -1)
{
ERR_load_crypto_strings();
ERR_error_string(ERR_get_error(), err);
fprintf(stderr, "Error encrypting message: %s\n", err);
}
fclose(rsa_pub_file);
}
char msg[1024];
stcpy(msg, "A test message");
int size;
char encrypted[1024];
encrypt(msg, strlen(msg), encrypted, size);
但是如果字符串的大小超过256,则它不起作用并生成Data too large error
我该怎么做才能使它适用于任何大小的字符串?
答案 0 :(得分:2)
但是如果字符串的大小超过256,则它不起作用并生成数据太大的错误。
正确。 RSA加密定义为c = m ^ e mod n
。消息不能大于模数大小n
。您可以使用RSA_size()
获得模数大小。
更准确地说,限制为modulus size - padding size
,因为邮件是填充的。 OAEP填充大小约为41个字节,因此限制大约为RSA_size(rsa) - 41
。
我省略了PKCS填充,因为它不安全。在来源中,它是#define RSA_PKCS1_PADDING_SIZE 11
。有关平易近人的讨论,请参阅A bad couple of years for the cryptographic token industry。
如何使其适用于任何大小的字符串?
您需要一个任意大的密钥;)但OpenSSL将密钥大小限制为16K位。所以你不能把钥匙任意大。
另外,很难生成那些大键。生成时间随密钥大小而增长,您可能需要花费几天时间生成大密钥。
在您的特定情况下:
char msg[1024];
...
encrypt(rsa, msg, sizeof(msg), ...);
尝试生成一个(1024 + 64)* 8或8704位的密钥。那应该用填充来处理1024字节的缓冲区。
要在这种情况下使用公钥加密,您应该使用AES等对称密码加密字符串。然后,使用公共RSA密钥加密AES密钥。这基本上就是SSL / TLS和其他人的运作方式。
如果您使用混合加密,则应选择EAX
或GCM
等模式;和不 CBC
模式。 EAX
和GCM
是经过身份验证的加密模式,它们提供机密性和真实性。通过经过身份验证的加密,您将提供隐私和能够检测到篡改。
如果您选择将OpenSSL与AES / GCM一起使用,请参阅EVP Authenticated Encryption and Decryption上OpenSSL wiki上如何使用它的示例。
有一些密码系统将服务作为一个包提供。见Shoupe的Elliptic Curve Integrated Encryption Scheme(ECIES);或Abdalla,Bellare和Rogaway的Diffie-Hellman Authenticates Encryption Schemes(DHAES)。不幸的是,OpenSSL也没有提供。
但如果您对ECIES或DHAES感兴趣,请查看Crpyto++。图书馆提供了这两个。有关在Crypto ++中使用它的示例,请参阅Elliptic Curve Integrated Encryption Scheme。
答案 1 :(得分:2)
我在链接https://shanetully.com/2012/06/openssl-rsa-aes-and-c/找到了解决方案。
函数Crypto::aesEncrypt()
和Crypto::aesDecrypt()
能够加密/解密任意大小的字符串。