c - 使用 RSA_public_encrypt 加密/解密没有填充的单个八位字节

标签 c encryption openssl cryptography rsa

我正在尝试使用 RSA_public_encrypt 加密十进制数字 1,不带填充。当然这次加密的结果应该又是1。但实际上是

密码:

5228673350895653896383201058815462877426144378065091716669226352446563314310753759122681282019606231774744798481087922688401463790373072832646006963123849664906627085625735903412727878929921552918090336305565457632762612646244666075746315455854479912774071351362988587769873374454538153517081634942043196173525640004822126101409481060928041484882764412543090155480476597339865942466034635200613687987398189458867055031285752787781897557950334515480742629110423562374837915117562936777536259795189526199285672603820591631423849227226304977053415509662563290672486408474162339095049681422645956742727171481170704

我做错了什么?

我知道 OpenSSL 中有高级例程,而且使用不带填充的 RSA 是不安全的。这只是一个实验。

我也知道 OpenSSL 使用 Big Endian 格式。所以我也尝试将输入字节的顺序更改为加密 - 然后 1 被加密为 1。但是在实现解密时,考虑到加密和解密中的反向字节顺序,一些数字,如 2,被加密 -正确解密而其他人不是......很奇怪!

这是我的加密代码:

#include <stdio.h>
#include "rsa.h"
#include "pem.h"

#define LENGTH 1000

int main(void)
{
    //Variables for message and cipher
    //BIGNUM format
    BIGNUM message_bignum, cipher_bignum;
    BIGNUM *ptr_message_bignum=&message_bignum;
    BIGNUM *ptr_cipher_bignum=&cipher_bignum;
    //Formatted as decimal string 
    unsigned char message_decimal[]="1";
    //binary format for input to RSA encryption
    unsigned char message[LENGTH]={0},cipher[LENGTH]={0};

    //Initialise RSA structure
    RSA *rsa=RSA_new();

    //Get public key
    BIO *publickey_handle=BIO_new_file("rsa_publickey.txt","rb");
    if(publickey_handle==NULL)
    {
        fprintf(stderr,"Could not open key file!\n");
        return -1;
    }
    PEM_read_bio_RSA_PUBKEY(publickey_handle,&rsa,NULL,NULL);
    if(BIO_free(publickey_handle)==0)
    {
        fprintf(stderr,"Error closing key file!\n");
        return -1;
    }

    //Convert message to BIGNUM format
    BN_init(ptr_message_bignum);
    BN_dec2bn(&ptr_message_bignum,(const char *)message_decimal);
    //Convert message as BIGNUM to binary format
    BN_bn2bin(ptr_message_bignum,message);

    //Encrypt message in binary format
    if(RSA_public_encrypt(RSA_size(rsa),(const unsigned char*)message,cipher,rsa,RSA_NO_PADDING)==-1)
    {
        fprintf(stderr,"Error during encryption!\n");
        return -1;
    }

    //Convert cipher to BIGNUM format
    BN_init(ptr_cipher_bignum);
    BN_bin2bn((const unsigned char*)cipher,RSA_size(rsa),ptr_cipher_bignum);
    //Convert cipher from BIGNUM format to decimal format and print it to stdout
    printf("Cipher:\n%s",BN_bn2dec(ptr_cipher_bignum));

    printf("\nDone!\n");

    return 0;
 }

最佳答案

如文档所示:

BN_bn2bin() converts the absolute value of a into big-endian form and stores it at to. to must point to BN_num_bytes(a) bytes of memory.

但事实并非如此。由于 message[LENGTH]={0},它首先包含一个 00。然后它包含 LENGTH 字节数中的任何内容。

RSA_public_encrypt 中,您使用 RSA_size(rsa) 作为第一个参数,flenflen 然而应该是 BN_num_bytes(&ptr_message_bignum) 的结果,即 1 个字节。另一方面,输出位置 cipher 必须能够存储 RSA_size(rsa) 字节。

可能造成混淆的原因是 BN_bn2bin 会将值存储为最短的 Big Endian 编码(以字节为单位)。对于值 1,它当然是一个字节,而不是 RSA_size(rsa) 字节。


编辑:我找到了 RSA_padding_add_none可以调整大小的方法。

关于c - 使用 RSA_public_encrypt 加密/解密没有填充的单个八位字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30548966/

相关文章:

c - XML 解析启动处理程序中的指针值已更改

ms-access - 连接到加密/密码保护数据库的代码

.net - x509 C# 示例?

c - 在 C 中将 int 转换为 float 时的奇怪行为

c++ - 用STL对象的 vector 序列化结构的 vector

javascript - 使用 Android 从 JavaScript 代码进行 AES 加密

openssl/valgrind

openssl - 为什么openssl在OCSP协议(protocol)中发送CA证书

c - 读取文本文件,将每个字符小写并将其存储在数组中

java - AES用openssl命令行工具加密,用Java解密