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;
我在使用 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;