我遇到了使用RSA_public_encrypt加密的问题。
我所拥有的:模数(1024位),指数(每次不改变)和明文。
我想要的:使用由模数和指数(以HEX字符串形式传递)的公钥加密纯文本,使用RSA_PKCS1_OAEP_PADDING。
问题是RSA_public_encrypt函数存在访问冲突,我不明白为什么。我在互联网上看到了很多类似的例子,但由于这些评论,它们似乎很好。
这是我的代码:
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;
我做错了什么?请帮帮我。提前谢谢!
答案 0 :(得分:0)
Res未初始化,但您正在写入它。我假设一个错字和那行
Result := '';
真的应该
Res := '';
如果是这样,那么没有足够的空间来保存你的结果,你需要使用类似SetLength到Res的东西来使它足够大以保持结果加上一个空终止符。
SetLength( Res, Length(PlainText) + 1); // or whatever is appropriate
您需要注意AnsiString是引用计数并自动控制,就像普通字符串一样,但PAnsiChar不是,并且被认为是一个预定义的字符串,它不会自动改变其大小(分配的内存)。当您将AnsiString强制转换为PAnsiChar时,编译器会在内部传递指向AnsiString的第一个char的指针,绕过其引用计数和长度字段。它不会将Res更改为AnsiChar数组。因此必须非常谨慎地使用它。
另一种方法是将Res定义为AnsiChar的数组
Res : Array[0..255] of AnsiChar;
例如,明确显示已分配的内存,但设置长度更灵活。
答案 1 :(得分:0)
最后我找到了问题的根源。这是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;