LockBox 3 使用 public 证书加密 RSA
LockBox 3 encrypt RSA with public certyficate
在 Delphi 10.4 中,我尝试使用来自证书 (*.cer) 的 public 密钥,使用 RSA 加密字符串。
问题是,我不知道如何将此证书传递给 RSA 函数。
我觉得 LockBox 3 有自己的格式来存储 public 和文件中的私钥。
我是这样写的:
type
TGen = class(TObject)
private
keyRSA: TBytes;
fileKey: TBytes;
cryptoLib: TCryptographicLibrary;
procedure readKeyWithoutHeader();
public
constructor Create();
destructor Destroy(); override;
function getRSA(const inputS: string): string;
end;
constructor TGen.Create();
var
path: string;
tmp: TFileStream;
begin
inherited;
cryptoLib := TCryptographicLibrary.Create(nil);
tmp := TFileStream.Create(path, fmOpenRead);
tmp.Position := 0;
SetLength(fileKey, tmp.Size);
plik.Read(fileKey, tmp.Size);
tmp.Free();
readKeyWithoutHeader();
end;
function TGen.getRSA(const inputS: string): string;
var
key: TSymetricKey;
rsa: TCodec;
t: TStream;
begin
try
t := TMemoryStream.Create();
Base64_to_stream(keyRSA, t);
t.Position := 0;
rsa := TCodec.Create(nil);
rsa.Reset();
rsa.CryptoLibrary := cryptoLib;
rsa.StreamCipherId := uTPLb_Constants.RSA_ProgId;
//rsa.ChainModeId := uTPLb_Constants.ECB_ProgId;
//rsa.AsymetricKeySizeInBits := 2048;
key := rsa.Asymetric_Engine.CreateFromStream(t, [partPublic]);
rsa.InitFromKey(key);
rsa.EncryptString(inputS, Result, TEncoding.UTF8);
finally
rsa.Burn();
FreeAndNil(rsa);
FreeAndNil(t);
end;
end;
procedure TGen.readKeyWithoutHeader();
var
pozStart: integer;
pozKoniec: integer;
i: integer;
poz: integer;
begin
pozStart := 0;
pozKoniec := 0;
SetLength(kluczRSA, Length(plikKlucza));
//znajdź koniec --- begin * ---
//wyszukaj pierwszej #13#10, ale nowa linia może mieć tylko #13 lub #10
for i := 0 to Length(plikKlucza) - 1 do
begin
if plikKlucza[i] in [13, 10] then pozStart := i
else if pozStart > 0 then break;
end;
//teraz znajdź początek --- end * ----
//przygotwany klucz może mieć jedną dodatkową linię, inne pliki obecnie nie są wspierane
for i := Length(plikKlucza) - 4 downto 0 do
begin
if plikKlucza[i] in [13, 10] then pozKoniec := i
else if pozKoniec > 0 then break;
end;
if (pozStart = 0) or (pozKoniec = 0) then
raise Exception.Create('Błędny plik z kluczem - nie zawiera nagłówków');
if pozStart >= pozKoniec then
raise Exception.Create('Błąd przy pobieraniu wartości klucza - nie rozpoznano nagłówków');
//teraz usuń wszystkie nowe linie, to co jest zakodowane w base64 między nagłówkami ma zostać
poz := 0;
for i := pozStart to pozKoniec do
begin
if not (plikKlucza[i] in [13, 10]) then
begin
kluczRSA[poz] := plikKlucza[i];
Inc(poz);
end;
end;
SetLength(kluczRSA, poz);
end;
但我收到错误:流读取错误。
我使用 openssl 从 public 证书中提取 public 密钥:
openssl x509 -pubkey -noout -in cert.cer > pubkey.pem
输出为:
-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr5qMxLWtgkId2oRUfnPf
6MX+UouBQKOzyfG0J9LW9yya8Nr+ilPTSPp+hSBL/TD1ijUZ2RClyegnrojOKHS7
kp1ZFDQJwmKSW660NKeLbyu2fbcJFBuDmSVK8XwRsUaIpf4eixqx5wAZg8q64kJ9
R9e07WPqrC2+8p2F/7zlKsZ263CWZ/xE0M6I4RiKSA24iaiGVrppnIrX1oX2v/dq
UNaQL3uIgH1WWtf4apnDA7MVei2Iz2NjFzLJ569wxzO92XBUrcEkqA7Xx0or6xij
h0oFKxsygNqHzK3qf56McRi/xy1VFrGQsiZL1u4+cdIAu5/tWaecLFl0UOBBbYxz
9QIDAQAB
-----END PUBLIC KEY-----
因为这个证书是 public,并且可以从网站上广泛访问,所以我粘贴在这里以显示示例:
-----BEGIN CERTIFICATE----- MIIFGTCCBAGgAwIBAgITYwABPJqEcB3zrmJ2agABAAE8mjANBgkqhkiG9w0BAQwF
ADBdMRIwEAYKCZImiZPyLGQBGRYCcGwxEzARBgoJkiaJk/IsZAEZFgNnb3YxEjAQ
BgoJkiaJk/IsZAEZFgJtZjEeMBwGA1UEAxMVUmVzb3J0IEZpbmFuc293IEkxIENB
MB4XDTIwMDcyMzExMjgyM1oXDTIyMDcyMzExMjgyM1owgZExCzAJBgNVBAYTAlBM
MRQwEgYDVQQIEwttYXpvd2llY2tpZTERMA8GA1UEBxMIV2Fyc3phd2ExHzAdBgNV
BAoMFk1pbmlzdGVyc3R3byBGaW5hbnPDs3cxHDAaBgNVBAsTE0FwbGlrYWNqZSBL
cnl0eWN6bmUxGjAYBgNVBAMTEWV0dy10c3QubWYuZ292LnBsMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr5qMxLWtgkId2oRUfnPf6MX+UouBQKOzyfG0
J9LW9yya8Nr+ilPTSPp+hSBL/TD1ijUZ2RClyegnrojOKHS7kp1ZFDQJwmKSW660
NKeLbyu2fbcJFBuDmSVK8XwRsUaIpf4eixqx5wAZg8q64kJ9R9e07WPqrC2+8p2F
/7zlKsZ263CWZ/xE0M6I4RiKSA24iaiGVrppnIrX1oX2v/dqUNaQL3uIgH1WWtf4
apnDA7MVei2Iz2NjFzLJ569wxzO92XBUrcEkqA7Xx0or6xijh0oFKxsygNqHzK3q
f56McRi/xy1VFrGQsiZL1u4+cdIAu5/tWaecLFl0UOBBbYxz9QIDAQABo4IBmzCC
AZcwDgYDVR0PAQH/BAQDAgWgMD4GCSsGAQQBgjcVBwQxMC8GJysGAQQBgjcVCIS3
mFWE7NgBhrmTDYO18X6DrtM2gUKEotdOhMuPDgIBZAIBDDAdBgNVHQ4EFgQUnFcp
uSFJZYUBUkIplCvJERbNN98wHwYDVR0jBBgwFoAUfR+t1nzLSol4VWy6EPLtM9Yx
us0wRgYDVR0fBD8wPTA7oDmgN4Y1aHR0cDovL3BraS5tZi5nb3YucGwvY2RwL3Jl
c29ydF9maW5hbnNvd19pMV9jYSgxKS5jcmwwdQYIKwYBBQUHAQEEaTBnMD4GCCsG
AQUFBzAChjJodHRwOi8vcGtpLm1mLmdvdi5wbC9haWEvcmVzb3J0X2ZpbmFuc293
X2kxX2NhLmNydDAlBggrBgEFBQcwAYYZaHR0cDovL3BraS5tZi5nb3YucGwvb2Nz
cDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwJwYJKwYBBAGCNxUKBBow
GDAKBggrBgEFBQcDATAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQwFAAOCAQEAHatd
TuoQDgaydiNDZFPvbvnqO0wmD/sH54LkXnf49hXHcGQRjhBc7xsSDbKzxHEORJ08
wNWWJa0H8cbKCLytBq49FQnENYoi5sgMetM5XGqGSYHwFLTFyAf8A9af8rpqfAEY
HwmL6iIjz6NmSD52i3owOaMCop4pyC+UU5CZDqBrYd10JY4bWRm5NPdjIga0+mDm
hQYEkoW/AEQQam+VmyLsJFGtBl/kr5+EFIUFw8X2tFAubNTuxQsveLo91Q0lHtSt
BMBJ7MYnJeFCGDeuPM65nJtCxexDfWfWSTZvGrdJSUooD5iFSZodCkReP7ZLiQmB
dPB1oIhW3y/VUem3+A==
-----END CERTIFICATE-----
错误“错误读取流”在函数中:
function TRSAKeyPair.LoadHugeCardinal_IfNotAlready(
StoreStream: TStream; var Number: IHugeCardinalWrap): boolean;
// virtual method.
var
L: cardinal;
ValueStream: TMemoryStream;
begin
result := not assigned( Number);
if not result then exit; // Only load if we are not already loaded.
StoreStream.ReadBuffer( L, SizeOf( L)); // <-- L have very big value for example 882233221
ValueStream := TMemoryStream.Create;
try
ValueStream.Size := L;
if L > 0 then
StoreStream.ReadBuffer( ValueStream.Memory^, L); // <--- error throw
ValueStream.Position := 0;
Number := NewWrap( THugeCardinal.CreateFromStreamIn(
L*8, LittleEndien, ValueStream, FPool))
finally
ValueStream.Free
end;
if Number.isZero then
Number := nil
end;
现在这段代码告诉我你不知道你在做什么:
tmp := TStringList.Create();
tmp.LoadFromFile(path, TEncoding.UTF8);
tmp.Delete(0);
tmp.Delete(tmp.Count - 1);
cert := TEncoding.UTF8.GetBytes(stringReplace(tmp.Text, sLineBreak, '', [rfReplaceAll]));
- 您想读取 ASCII 文本文件。如果它包含 UTF-8,那么它根本就无效。将其用作文本编码会漏掉任何一点。
- 你删除了第一行和最后一行,因为你甚至没有检查就希望它们是
-----BEGIN something-----
和 -----END something-----
。但这些行的存在并不是为了好玩:它们清楚地标记了数据应该从哪里开始和应该从哪里结束,而在这些标记行之前和之后 可能会出现其他文本 。一个文件可能包含多个密钥,您可以自行决定选择哪个。
- 您确定删除了所有换行符吗?你真的检查过
cert
的内容吗?
- 您忽略了在 ASCII 上下文中二进制数据很可能是 Base64 编码的。一切几乎都只由拉丁字母和阿拉伯数字组成,这难道不让你的脑袋打上问号吗?但是您将它们视为字节(或 UTF-8)?
- 为什么不看 LockBox's own example?它在常量上使用自己的
Base64_to_stream()
,其内容看起来与您的 public 键的数据非常相似。但是实例化 TStringStream
可能会再次操纵解码为字节的内容,因为现在您出于未知原因再次将其视为文本。
查看您的文本文件并按原样阅读,以行分隔。从你想要的那些行中,删除任何空格(即换行符、空格等),因为 Base64 不知道这些 - 换行符在那里使其与电子邮件兼容。看看你现在得到了什么 - 它必须是一个长 String
,必须全部在 ['A'.. 'Z', 'a'.. 'z', '0'.. '9', '+', '/']
中,没有别的。现在将此 Base64 转换为原始字节,最好使用 TMemoryStream.Create()
.
的实例
并通过查看它在代码中的哪个点发生以及在 LockBox 的代码中的哪个点引发来调试“流读取错误”。然后再试一次,这次更仔细地查看异常发生的时间或访问 Stream 的时间点。以及那个位置的 Stream 包含什么。
我找到了更好的解决方案。刚刚从 TP LockBox 2 或 3 辞职,我已经从 https://github.com/lminuti/Delphi-OpenSSL 下载了包装器,我正在使用 OpenSSL 在 RSA 或 AES 中进行加密。
function TGeneratorSzyfrow.zaszyfrujRSA(const wejscie: TBytes): string;
var
rsa: TRSAUtil;
certyfikat: TX509Cerificate;
bufWejscie: TMemoryStream;
bufWyjscie: TMemoryStream;
bajty: TBytes;
begin
rsa := TRSAUtil.Create();
certyfikat := TX509Cerificate.Create();
bufWejscie := TMemoryStream.Create();
bufWyjscie := TMemoryStream.Create();
try
certyfikat.LoadFromFile(sciezkaDoPlikuRSA);
rsa.PublicKey.LoadFromCertificate(certyfikat);
bufWejscie.write(wejscie, Length(wejscie));
bufWejscie.Position := 0;
rsa.PublicEncrypt(bufWejscie, bufWyjscie, rpPKCS);
setLength(bajty, bufWyjscie.Size);
bufWyjscie.Position := 0;
bufWyjscie.Read(bajty, bufWyjscie.Size);
Result := kodujBase64(bajty);
finally
FreeAndNil(rsa);
FreeAndNil(certyfikat);
FreeAndNil(bufWejscie);
FreeAndNil(bufWyjscie);
end;
end;
在 Delphi 10.4 中,我尝试使用来自证书 (*.cer) 的 public 密钥,使用 RSA 加密字符串。 问题是,我不知道如何将此证书传递给 RSA 函数。 我觉得 LockBox 3 有自己的格式来存储 public 和文件中的私钥。
我是这样写的:
type
TGen = class(TObject)
private
keyRSA: TBytes;
fileKey: TBytes;
cryptoLib: TCryptographicLibrary;
procedure readKeyWithoutHeader();
public
constructor Create();
destructor Destroy(); override;
function getRSA(const inputS: string): string;
end;
constructor TGen.Create();
var
path: string;
tmp: TFileStream;
begin
inherited;
cryptoLib := TCryptographicLibrary.Create(nil);
tmp := TFileStream.Create(path, fmOpenRead);
tmp.Position := 0;
SetLength(fileKey, tmp.Size);
plik.Read(fileKey, tmp.Size);
tmp.Free();
readKeyWithoutHeader();
end;
function TGen.getRSA(const inputS: string): string;
var
key: TSymetricKey;
rsa: TCodec;
t: TStream;
begin
try
t := TMemoryStream.Create();
Base64_to_stream(keyRSA, t);
t.Position := 0;
rsa := TCodec.Create(nil);
rsa.Reset();
rsa.CryptoLibrary := cryptoLib;
rsa.StreamCipherId := uTPLb_Constants.RSA_ProgId;
//rsa.ChainModeId := uTPLb_Constants.ECB_ProgId;
//rsa.AsymetricKeySizeInBits := 2048;
key := rsa.Asymetric_Engine.CreateFromStream(t, [partPublic]);
rsa.InitFromKey(key);
rsa.EncryptString(inputS, Result, TEncoding.UTF8);
finally
rsa.Burn();
FreeAndNil(rsa);
FreeAndNil(t);
end;
end;
procedure TGen.readKeyWithoutHeader();
var
pozStart: integer;
pozKoniec: integer;
i: integer;
poz: integer;
begin
pozStart := 0;
pozKoniec := 0;
SetLength(kluczRSA, Length(plikKlucza));
//znajdź koniec --- begin * ---
//wyszukaj pierwszej #13#10, ale nowa linia może mieć tylko #13 lub #10
for i := 0 to Length(plikKlucza) - 1 do
begin
if plikKlucza[i] in [13, 10] then pozStart := i
else if pozStart > 0 then break;
end;
//teraz znajdź początek --- end * ----
//przygotwany klucz może mieć jedną dodatkową linię, inne pliki obecnie nie są wspierane
for i := Length(plikKlucza) - 4 downto 0 do
begin
if plikKlucza[i] in [13, 10] then pozKoniec := i
else if pozKoniec > 0 then break;
end;
if (pozStart = 0) or (pozKoniec = 0) then
raise Exception.Create('Błędny plik z kluczem - nie zawiera nagłówków');
if pozStart >= pozKoniec then
raise Exception.Create('Błąd przy pobieraniu wartości klucza - nie rozpoznano nagłówków');
//teraz usuń wszystkie nowe linie, to co jest zakodowane w base64 między nagłówkami ma zostać
poz := 0;
for i := pozStart to pozKoniec do
begin
if not (plikKlucza[i] in [13, 10]) then
begin
kluczRSA[poz] := plikKlucza[i];
Inc(poz);
end;
end;
SetLength(kluczRSA, poz);
end;
但我收到错误:流读取错误。
我使用 openssl 从 public 证书中提取 public 密钥:
openssl x509 -pubkey -noout -in cert.cer > pubkey.pem
输出为:
-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr5qMxLWtgkId2oRUfnPf 6MX+UouBQKOzyfG0J9LW9yya8Nr+ilPTSPp+hSBL/TD1ijUZ2RClyegnrojOKHS7 kp1ZFDQJwmKSW660NKeLbyu2fbcJFBuDmSVK8XwRsUaIpf4eixqx5wAZg8q64kJ9 R9e07WPqrC2+8p2F/7zlKsZ263CWZ/xE0M6I4RiKSA24iaiGVrppnIrX1oX2v/dq UNaQL3uIgH1WWtf4apnDA7MVei2Iz2NjFzLJ569wxzO92XBUrcEkqA7Xx0or6xij h0oFKxsygNqHzK3qf56McRi/xy1VFrGQsiZL1u4+cdIAu5/tWaecLFl0UOBBbYxz 9QIDAQAB -----END PUBLIC KEY-----
因为这个证书是 public,并且可以从网站上广泛访问,所以我粘贴在这里以显示示例:
-----BEGIN CERTIFICATE----- MIIFGTCCBAGgAwIBAgITYwABPJqEcB3zrmJ2agABAAE8mjANBgkqhkiG9w0BAQwF ADBdMRIwEAYKCZImiZPyLGQBGRYCcGwxEzARBgoJkiaJk/IsZAEZFgNnb3YxEjAQ BgoJkiaJk/IsZAEZFgJtZjEeMBwGA1UEAxMVUmVzb3J0IEZpbmFuc293IEkxIENB MB4XDTIwMDcyMzExMjgyM1oXDTIyMDcyMzExMjgyM1owgZExCzAJBgNVBAYTAlBM MRQwEgYDVQQIEwttYXpvd2llY2tpZTERMA8GA1UEBxMIV2Fyc3phd2ExHzAdBgNV BAoMFk1pbmlzdGVyc3R3byBGaW5hbnPDs3cxHDAaBgNVBAsTE0FwbGlrYWNqZSBL cnl0eWN6bmUxGjAYBgNVBAMTEWV0dy10c3QubWYuZ292LnBsMIIBIjANBgkqhkiG 9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr5qMxLWtgkId2oRUfnPf6MX+UouBQKOzyfG0 J9LW9yya8Nr+ilPTSPp+hSBL/TD1ijUZ2RClyegnrojOKHS7kp1ZFDQJwmKSW660 NKeLbyu2fbcJFBuDmSVK8XwRsUaIpf4eixqx5wAZg8q64kJ9R9e07WPqrC2+8p2F /7zlKsZ263CWZ/xE0M6I4RiKSA24iaiGVrppnIrX1oX2v/dqUNaQL3uIgH1WWtf4 apnDA7MVei2Iz2NjFzLJ569wxzO92XBUrcEkqA7Xx0or6xijh0oFKxsygNqHzK3q f56McRi/xy1VFrGQsiZL1u4+cdIAu5/tWaecLFl0UOBBbYxz9QIDAQABo4IBmzCC AZcwDgYDVR0PAQH/BAQDAgWgMD4GCSsGAQQBgjcVBwQxMC8GJysGAQQBgjcVCIS3 mFWE7NgBhrmTDYO18X6DrtM2gUKEotdOhMuPDgIBZAIBDDAdBgNVHQ4EFgQUnFcp uSFJZYUBUkIplCvJERbNN98wHwYDVR0jBBgwFoAUfR+t1nzLSol4VWy6EPLtM9Yx us0wRgYDVR0fBD8wPTA7oDmgN4Y1aHR0cDovL3BraS5tZi5nb3YucGwvY2RwL3Jl c29ydF9maW5hbnNvd19pMV9jYSgxKS5jcmwwdQYIKwYBBQUHAQEEaTBnMD4GCCsG AQUFBzAChjJodHRwOi8vcGtpLm1mLmdvdi5wbC9haWEvcmVzb3J0X2ZpbmFuc293 X2kxX2NhLmNydDAlBggrBgEFBQcwAYYZaHR0cDovL3BraS5tZi5nb3YucGwvb2Nz cDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwJwYJKwYBBAGCNxUKBBow GDAKBggrBgEFBQcDATAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQwFAAOCAQEAHatd TuoQDgaydiNDZFPvbvnqO0wmD/sH54LkXnf49hXHcGQRjhBc7xsSDbKzxHEORJ08 wNWWJa0H8cbKCLytBq49FQnENYoi5sgMetM5XGqGSYHwFLTFyAf8A9af8rpqfAEY HwmL6iIjz6NmSD52i3owOaMCop4pyC+UU5CZDqBrYd10JY4bWRm5NPdjIga0+mDm hQYEkoW/AEQQam+VmyLsJFGtBl/kr5+EFIUFw8X2tFAubNTuxQsveLo91Q0lHtSt BMBJ7MYnJeFCGDeuPM65nJtCxexDfWfWSTZvGrdJSUooD5iFSZodCkReP7ZLiQmB dPB1oIhW3y/VUem3+A== -----END CERTIFICATE-----
错误“错误读取流”在函数中:
function TRSAKeyPair.LoadHugeCardinal_IfNotAlready(
StoreStream: TStream; var Number: IHugeCardinalWrap): boolean;
// virtual method.
var
L: cardinal;
ValueStream: TMemoryStream;
begin
result := not assigned( Number);
if not result then exit; // Only load if we are not already loaded.
StoreStream.ReadBuffer( L, SizeOf( L)); // <-- L have very big value for example 882233221
ValueStream := TMemoryStream.Create;
try
ValueStream.Size := L;
if L > 0 then
StoreStream.ReadBuffer( ValueStream.Memory^, L); // <--- error throw
ValueStream.Position := 0;
Number := NewWrap( THugeCardinal.CreateFromStreamIn(
L*8, LittleEndien, ValueStream, FPool))
finally
ValueStream.Free
end;
if Number.isZero then
Number := nil
end;
现在这段代码告诉我你不知道你在做什么:
tmp := TStringList.Create(); tmp.LoadFromFile(path, TEncoding.UTF8); tmp.Delete(0); tmp.Delete(tmp.Count - 1); cert := TEncoding.UTF8.GetBytes(stringReplace(tmp.Text, sLineBreak, '', [rfReplaceAll]));
- 您想读取 ASCII 文本文件。如果它包含 UTF-8,那么它根本就无效。将其用作文本编码会漏掉任何一点。
- 你删除了第一行和最后一行,因为你甚至没有检查就希望它们是
-----BEGIN something-----
和-----END something-----
。但这些行的存在并不是为了好玩:它们清楚地标记了数据应该从哪里开始和应该从哪里结束,而在这些标记行之前和之后 可能会出现其他文本 。一个文件可能包含多个密钥,您可以自行决定选择哪个。 - 您确定删除了所有换行符吗?你真的检查过
cert
的内容吗? - 您忽略了在 ASCII 上下文中二进制数据很可能是 Base64 编码的。一切几乎都只由拉丁字母和阿拉伯数字组成,这难道不让你的脑袋打上问号吗?但是您将它们视为字节(或 UTF-8)?
- 为什么不看 LockBox's own example?它在常量上使用自己的
Base64_to_stream()
,其内容看起来与您的 public 键的数据非常相似。但是实例化TStringStream
可能会再次操纵解码为字节的内容,因为现在您出于未知原因再次将其视为文本。
查看您的文本文件并按原样阅读,以行分隔。从你想要的那些行中,删除任何空格(即换行符、空格等),因为 Base64 不知道这些 - 换行符在那里使其与电子邮件兼容。看看你现在得到了什么 - 它必须是一个长 String
,必须全部在 ['A'.. 'Z', 'a'.. 'z', '0'.. '9', '+', '/']
中,没有别的。现在将此 Base64 转换为原始字节,最好使用 TMemoryStream.Create()
.
并通过查看它在代码中的哪个点发生以及在 LockBox 的代码中的哪个点引发来调试“流读取错误”。然后再试一次,这次更仔细地查看异常发生的时间或访问 Stream 的时间点。以及那个位置的 Stream 包含什么。
我找到了更好的解决方案。刚刚从 TP LockBox 2 或 3 辞职,我已经从 https://github.com/lminuti/Delphi-OpenSSL 下载了包装器,我正在使用 OpenSSL 在 RSA 或 AES 中进行加密。
function TGeneratorSzyfrow.zaszyfrujRSA(const wejscie: TBytes): string;
var
rsa: TRSAUtil;
certyfikat: TX509Cerificate;
bufWejscie: TMemoryStream;
bufWyjscie: TMemoryStream;
bajty: TBytes;
begin
rsa := TRSAUtil.Create();
certyfikat := TX509Cerificate.Create();
bufWejscie := TMemoryStream.Create();
bufWyjscie := TMemoryStream.Create();
try
certyfikat.LoadFromFile(sciezkaDoPlikuRSA);
rsa.PublicKey.LoadFromCertificate(certyfikat);
bufWejscie.write(wejscie, Length(wejscie));
bufWejscie.Position := 0;
rsa.PublicEncrypt(bufWejscie, bufWyjscie, rpPKCS);
setLength(bajty, bufWyjscie.Size);
bufWyjscie.Position := 0;
bufWyjscie.Read(bajty, bufWyjscie.Size);
Result := kodujBase64(bajty);
finally
FreeAndNil(rsa);
FreeAndNil(certyfikat);
FreeAndNil(bufWejscie);
FreeAndNil(bufWyjscie);
end;
end;