【问题标题】:Encrypt/decrypt single octet with no padding using RSA_public_encrypt使用 RSA_public_encrypt 加密/解密没有填充的单个八位字节
【发布时间】:2015-05-30 17:06:44
【问题描述】:

我正在尝试使用 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;
 }

【问题讨论】:

  • 你得到什么结果?怎么错了? “结果不是 1”并没有真正解释它。
  • 我认为有更简单的方法可以用值 1 来做你想做的事情。为什么不简单地将它声明为 unsigned char message_decimal[] = 0x01;?或致电BN_set_word(bn, 0x01)?还是使用BN_value_one?有关相关功能,请参见 bn_set_word 手册页。甚至unsigned char message[RSA_size(rsa)]; memset(message,RSA_size(rsa),0x00); message[RSA_size(rsa)-1]=0x01;(使用C99编译)。
  • 我想了解如何将十进制数传递给 RSA_public_encrypt()。当然我可以只传递一个数组,但这不是重点。我想了解格式。

标签: c encryption openssl cryptography rsa


【解决方案1】:

据记载:

BN_bn2bin() 将 a 的绝对值转换为大端形式并将其存储在 to 中。 to 必须指向BN_num_bytes(a) 字节的内存

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

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

混淆可能来自BN_bn2bin 将值存储为最短的Big Endian 编码(以字节为单位)这一事实。对于值 1,当然是一个字节,而不是 RSA_size(rsa) 字节。


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

【讨论】:

  • 在 C 中,当你用比数组长度少的初始化器来初始化一个数组时,数组的其余部分被设置为 0。所以说“好吧,不管 LENGTH 是什么”是错误的" 字节数。
  • 啊,所以它包含010000.....。对。不过,RSA_size 可能会溢出数组,如果不是因为数组过大的话。但是您可能对那句话是正确的。我将删除评论,但要注意诸如此类的缓冲区 fubar。心血不是从蓝天上掉下来的。
  • 没错。我应该为密码调用 RSA_size(rsa) 字节。我将在代码中更改它。但是,在这种情况下,RSA_size(rsa) 是 256,所以没问题。
  • 根据 Openssl 文档,RSA_public_encrypt 的第一个参数 flen 必须满足:对于基于 PKCS #1 v1.5 的填充模式,flen 必须小于 RSA_size(rsa) - 11,小于RSA_size(rsa) - RSA_PKCS1_OAEP_PADDING 为 41,RSA_NO_PADDING 为 RSA_size(rsa)。所以我不能只将 1 传递给 flen;然后加密失败。
  • 但是你的回答是一个很好的提示;我想我现在知道它为什么失败了:在使用 BN_bn2bin() 转换后,我应该将消息视为一个大端整数,存储在 RSA_size(rsa) 字节中!对于一个字节的整数,我可以颠倒字节顺序,但实际上我必须将所有字节向右移动......所以这就是大小写相关行为的来源!非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-23
  • 1970-01-01
  • 1970-01-01
  • 2017-07-16
  • 2017-09-23
  • 2012-12-14
相关资源
最近更新 更多