RSA_public_encrypt 的 OpenSSL 问题

OpenSSL issue with RSA_public_encrypt

我在使用 RSA_public_encrypt 加密时遇到问题。

我有:模数(1024 位)、指数(每次都不变)和纯文本。

我想要的:使用 public 由模数和指数(作为十六进制字符串传递)和 RSA_PKCS1_OAEP_PADDING 组成的密钥加密纯文本。

问题是 RSA_public_encrypt 函数出现访问冲突,我不明白为什么。我在 Internet 上看到过很多类似的示例,但由于评论,它们似乎还不错。

这是我的代码:

procedure RSAPublicEncrypt(const PlainText, Modulus, Exponent: AnsiString);
  var
    PublicKey: pRSA;
    Output: Integer;
    BN_Modulus, BN_Exponent: pBIGNUM;
    Res: AnsiString;
  begin
    Result := '';
    try
      PublicKey := RSA_new(); //Creating new key

      PublicKey^.n := BN_new; //Creating new modulus
      Output := BN_hex2bn(PublicKey^.n, PAnsiChar(Modulus)); //Convert modulut from hex to BIGNUM

      PublicKey^.e := BN_new; //same to the exponent
      BN_hex2bn(PublicKey^.e, PAnsiChar(Exponent));

      //Trying to encrypt. Here I get the AV
      Output := RSA_public_encrypt(Length(PlainText), PAnsiChar(PlainText), PAnsiChar(Res), PublicKey, RSA_PKCS1_OAEP_PADDING);
    finally
      BN_clear_free(PublicKey^.e);
      BN_clear_free(PublicKey^.n);
      RSA_free(PublicKey);
    end;
  end;

我做错了什么?请帮帮我。提前致谢!

Res 未初始化,但您正在写入它。我假设有一个错字,那一行

Result := '';

真的应该

Res := '';

如果是这样,则没有足够的空间来保存您的结果,您需要使用 SetLength to Res 之类的方法使其足够大以保存结果加上一个空终止符。

SetLength( Res, Length(PlainText) + 1); // or whatever is appropriate 

您需要注意 AnsiString 是引用计数的,并且像普通字符串一样自动控制,但 PAnsiChar 不是,并且被视为不会自动更改其大小(分配的内存)的预定义字符串。当您将 AnsiString 转换为 PAnsiChar 时,编译器在内部将指针传递给 AnsiString 的第一个字符,绕过其引用计数和长度字段。它不会将 Res 更改为 AnsiChar 数组。所以一定要小心使用。

另一种方法是将 Res 定义为 AnsiChar

的数组
Res : Array[0..255] of AnsiChar;

例如,它明确显示分配的内存,但设置长度更灵活。

终于找到问题的根源了。这是RSA结构的错误实现。它缺少一个指针:

RSA = record
    pad: integer;
    version: integer;
    meth: pRSA_METHOD;
    engine: pointer; //<-- this one was missing
    n: pBIGNUM;
    e: pBIGNUM;
    d: pBIGNUM;
    p: pBIGNUM;
    q: pBIGNUM;
    dmp1: pBIGNUM;
    dmq1: pBIGNUM;
    iqmp: pBIGNUM;
    ex_data: CRYPTO_EX_DATA;
    references: integer;
    flags: integer;
    _method_mod_n: pBN_MONT_CTX;
    _method_mod_p: pBN_MONT_CTX;
    _method_mod_q: pBN_MONT_CTX;
    bignum_data: ^byte;
    blinding: ^BN_BLINDING;
end;