使用公钥进行RSA加密和LockBox3

3

我使用 Delphi XE 和 Lockbox3.5,想要使用由支付网关提供的公钥对字符串进行加密,该网关需要进行此操作。公钥长这样: -----BEGIN PUBLIC KEY----- 这里是一些数据 -----END PUBLIC KEY----- 我无法让 RSA 编解码器读取这个公钥,我的代码如下:

var
 Ciphertext: string;
 ms: TStream;
begin
 ms := TFileStream.Create('C:\PubKey.txt', fmOpenRead);
 ms.Seek(0, soFromBeginning);
 cdcRSA.StreamCipherId := RSA_ProgId;
 cdcRSA.ChainModeId := RSA_ProgId;
 Signatory1.LoadKeysFromStream(ms, [partPublic]);
 cdcRSA.EncryptAnsiString('WORDSOMEWORDSOME', Ciphertext);
 Memo1.Lines.Add(Ciphertext);
end;

Codec cdcRA与CryptoLibrary相关联,cipher(RSA公钥加密系统*)使用空链接模式,但该代码在内存不足时会失败。

感谢任何提示。

下面的示例代码也无法正常工作,有人能提供一个使用RSA和公钥加密字符串的示例吗?

procedure TForm1.btnRSAClick(Sender: TObject);
var
 sKey, Ciphertext: string;
 ss: TStringStream;
 Key: TSymetricKey;
begin
 sKey := '-----BEGIN PUBLIC KEY-----' +
         'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDlAVd8PUhIiuA00vlUZYm0xrk+' +
         'UgyZxwWZSrysOJWk0POGJ91hUUqr659mBA7bg0i07Y4T+FYdA4iuvg5bT2aSMAGl' +
         'To3GRKvwX8RAnimQQNqkqDk3nf20OiEygwWDQr72fWzKLtuoo7Rd5onrXEp1qM3o' +
         'ywRq5Mwk4dHPX1F5EwIDAQAB' +
         '-----END PUBLIC KEY-----';

 ss := TStringStream.Create(sKey);  ss.Seek(0,soFromBeginning);
 Base64_to_stream(skey, ss);
 cdcRSA.Reset;
 cdcRSA.StreamCipherId := 'native.RSA';
 cdcRSA.ChainModeId:= 'native.CBC';
 cdcRSA.AsymetricKeySizeInBits := 1024;
 key := cdcRSA.Asymetric_Engine.CreateFromStream(ss, [partPublic]); // error out of memory
 cdcRSA.InitFromKey(key);  
 cdcRSA.EncryptString('WORDSOMEWORDSOME', Ciphertext, TEncoding.UTF8);
 Memo1.Lines.Add(Ciphertext);
end;

1
这个函数被调用的频率有多高?我问这个问题是因为它创建了一个TFileStream但没有释放它,导致内存泄漏。 - Dsm
该错误发生在第一次调用函数时,我添加了释放具有相同错误的流,当调用签名组件的LoadKeysFromStream函数时会引发该错误。 - Moore
@Moore,你解决了这个问题吗?我也遇到了同样的问题,即内存不足。 - Dave Nottage
2个回答

0
一个密钥文件是一个包含一系列行的文本文件。文件中的每一行长度不得超过72个8位字节(行终止符除外)
您的硬编码字符串仅有一行,长度为358加上BEGIN / END行 我们无法查看C:\PubKey.txt的内容。文件是否相同?
在末尾添加<CR><LF>
sKey := '-----BEGIN PUBLIC KEY-----'#13#10 +
         'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDlAVd8PUhIiuA00vlUZYm0xrk+'#13#10 +
         'UgyZxwWZSrysOJWk0POGJ91hUUqr659mBA7bg0i07Y4T+FYdA4iuvg5bT2aSMAGl'#13#10 +
         'To3GRKvwX8RAnimQQNqkqDk3nf20OiEygwWDQr72fWzKLtuoo7Rd5onrXEp1qM3o'#13#10 +
         'ywRq5Mwk4dHPX1F5EwIDAQAB'#13#10 +
         '-----END PUBLIC KEY-----';

还可以了解一下以下内容的区别:

BEGIN RSA PUBLIC KEY 与 BEGIN PUBLIC KEY 的区别

涉及到这两个标签的代码如下:

ss := TStringStream.Create(sKey);  ss.Seek(0,soFromBeginning);
 Base64_to_stream(skey, ss);

你需要使用包含以下代码的 Base64_to_stream(skey, ss) 进行操作:BEGIN ....END ....

这样就可以了。

-----BEGIN PUBLIC KEY-----
BASE64 ENCODED DATA
-----END PUBLIC KEY-----

sKeyBEG := '-----BEGIN PUBLIC KEY-----'#13#10;

sKey := 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDlAVd8PUhIiuA00vlUZYm0xrk+' +
        'UgyZxwWZSrysOJWk0POGJ91hUUqr659mBA7bg0i07Y4T+FYdA4iuvg5bT2aSMAGl' +
        'To3GRKvwX8RAnimQQNqkqDk3nf20OiEygwWDQr72fWzKLtuoo7Rd5onrXEp1qM3o' +
        'ywRq5Mwk4dHPX1F5EwIDAQAB';

sKeyEND := #13#10'-----END PUBLIC KEY-----';

实质上,PEM文件只是DER编码数据的Base64编码版本。为了区分DER编码字符串中包含的数据类型,在数据周围加上了头和尾

如果您想要加载带有头和尾的密钥文本文件,则需要找到一种将密钥与key.txt文件分开的方法。这并不难。

无论如何,Base64_to_stream(skey, ss)仅适用于密钥而不是周围的文本。


即使只使用sKey部分,仍然会导致内存不足错误。 - Dave Nottage

0

问题可能出在您创建的 TFileStream 中释放 ms 变量上:

var
 Ciphertext: string;
 ms: TStream;
begin
 ms := TFileStream.Create('C:\PubKey.txt', fmOpenRead);
 try
   ms.Seek(0, soFromBeginning);
   cdcRSA.StreamCipherId := RSA_ProgId;
   cdcRSA.ChainModeId := RSA_ProgId;
   Signatory1.LoadKeysFromStream(ms, [partPublic]);
 finally
   ms.Free;
 end;
 cdcRSA.EncryptAnsiString('WORDSOMEWORDSOME', Ciphertext);
 Memo1.Lines.Add(Ciphertext);
end;

错误在这一行: Signatory1.LoadKeysFromStream(ms, [partPublic]); 即使释放了流,错误仍然存在。 - Moore

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接