2
votes

I use Delphi XE and Lockbox3.5, I want to encyrpt a string having a public key provided by the payment gateway that requires the operation, the public key is something like : -----BEGIN PUBLIC KEY----- staff here -----END PUBLIC KEY----- I am not able the make RSA codec read this public key, my code is as follows:

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 is linked to CryptoLibrary and cipher is (RSA public key encryption system *),chaining mode is empty, but this code fails with out of memory error. Thanks for any hints..

The following code from the demo does not work neither, can someone provide an example to encrypt a string with RSA and public key? :

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;
2
How often is this function called? The reason I ask is that it creates a TFileStream but does not free it, leading to a memory leak.Dsm
The error occurs the first time the function is called, i added freeing the stream with same error, it raises when calling funcion LoadKeysFromStream of signatory component..Moore

2 Answers

0
votes

the problem might be in free the ms variable - TFileStream - you created:

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;
0
votes

A key file is a text file, containing a sequence of lines. Each line in the file MUST NOT be longer than 72 8-bit bytes excluding line termination characters.

Your hardcoded string has only one line with a length of 358 plus BEGIN /END lines

We can not see the content of C:\PubKey.txt. Looks the file the same?

Add <CR><LF> at the end

sKey := '-----BEGIN PUBLIC KEY-----'#13#10 +
         'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDlAVd8PUhIiuA00vlUZYm0xrk+'#13#10 +
         'UgyZxwWZSrysOJWk0POGJ91hUUqr659mBA7bg0i07Y4T+FYdA4iuvg5bT2aSMAGl'#13#10 +
         'To3GRKvwX8RAnimQQNqkqDk3nf20OiEygwWDQr72fWzKLtuoo7Rd5onrXEp1qM3o'#13#10 +
         'ywRq5Mwk4dHPX1F5EwIDAQAB'#13#10 +
         '-----END PUBLIC KEY-----';

Also read about differences ...

Differences between BEGIN RSA PUBLIC KEY and BEGIN PUBLIC KEY

With the lines

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

you do the Base64_to_stream(skey, ss) with the included lines BEGIN .... and END ....

It should be

-----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-----';

In essence PEM files are just base64 encoded versions of the DER encoded data. In order to distinguish from the outside what kind of data is inside the DER encoded string, a header and footer are present around the data.

If you want to load a key text file with header and footer, you need to find a way to separate the key from the key.txt file. That's not hard.

Anyway, the Base64_to_stream(skey, ss) can only be applied to the key and not also to the surrounding text.