Page 1 of 1
How to store keys in a TScMemoryStorage;?
Posted: Thu 29 Oct 2020 15:05
by docH
This post
Code: Select all
https://forums.devart.com/viewtopic.php?f=27&t=39126&p=139889&hilit=TScMemoryStorage#p139889
and this one
Code: Select all
https://forums.devart.com/viewtopic.php?f=27&t=34258&p=118717&hilit=TScMemoryStorage#p118717
hinted that it is possible to hold the private and public keys hard coded into the code of a Delphi program (maybe as constants) and somehow '
load' them into a TScMemoryStorage at run time.
It showed the following code snippet to load from a string into a TscKey object
Code: Select all
Key := TScKey.Create(ScMemoryStorage.Keys);
SStream:=TStringStream.Create(Private_Key);
Key.ImportFrom(SStream);
but did not show what to do with the key object afterwards.
Given code like the following, can anyone please show me
exactly what the code would be to get the public and private keys held as constants to be stored in TScMemoryStorage at run time in such a way that the TScSSHClient can access them using the names '
ThePublicKey' and '
ThePrivateKey'. as assigned to its HostKeyName and PrivateKeyName properties.
Code: Select all
Const
PUBLIC_KEY = 'ABCDEF'; //hard coded public key
PRIVATE_KEY = 'HIJKLM'; //hard coded private key
var
SSHClient : TScSSHClient;
MemoryStorage : TScMemoryStorage;
Key: TscKey;
Private_Key: String;
SStream: TStringStream;
begin
...
SSHClient.KeyStorage := MemoryStorage ;
SSHClient.HostKeyName := 'ThePublicKey'; //name given to public key
SSHClient.PrivateKeyName := 'ThePrivateKey'; //name given to private key
...
end
Re: How to store keys in a TScMemoryStorage;?
Posted: Thu 29 Oct 2020 18:07
by ViktorV
To accomplish your task, you can use the following code:
Code: Select all
Const
PUBLIC_KEY = 'ABCDEF'; //hard coded public key
PRIVATE_KEY = 'HIJKLM'; //hard coded private key
var
SSHClient : TScSSHClient;
MemoryStorage : TScMemoryStorage;
Key: TscKey;
Private_Key: String;
SStream: TStringStream;
begin
...
MemoryStorage := ScMemoryStorage.Create(nil);
Key := TScKey.Create(MemoryStorage.Keys);
SStream:=TStringStream.Create(PUBLIC_KEY);
Key.ImportFrom(SStream);
Key.KeyName := 'ThePublicKey';
Key := TScKey.Create(MemoryStorage.Keys);
SStream:=TStringStream.Create(PRIVATE_KEY);
Key.ImportFrom(SStream);
Key.KeyName := 'ThePrivateKey';
...
SSHClient.KeyStorage := MemoryStorage ;
SSHClient.HostKeyName := 'ThePublicKey'; //name given to public key
SSHClient.PrivateKeyName := 'ThePrivateKey'; //name given to private key
...
end
Re: How to store keys in a TScMemoryStorage;?
Posted: Thu 29 Oct 2020 18:35
by docH
Thanks VictorV for getting back so quickly, I'll try out that code in the morning.
So I only have to set values in a Key object and that also stores them in a Storage object?
Can it be done in two separate stages (for clarity) eg
do this bit first to get it into a key
Code: Select all
SStream:=TStringStream.Create(PRIVATE_KEY);
Key.ImportFrom(SStream);
Key.KeyName := 'ThePrivateKey';
and them put the Key into the MemoryStorage as a separate operation?
Re: How to store keys in a TScMemoryStorage;?
Posted: Thu 29 Oct 2020 22:00
by docH
This seems to be the way, and maybe a bit clearer to understand by doing each operation separately instead of creating a TStringStream at the same time as assigning a value to it and creating a TscKey as a child object of a TScMemoryStorage.
Code: Select all
Const
PUBLIC_KEY = 'ABCDEF'; //hard coded public key
var
MemoryStorage : TScMemoryStorage;
Key: TscKey;
SStream: TStringStream;
begin
...
MemoryStorage := ScMemoryStorage.Create(nil); //make a memory storage object
SStream := TStringStream.Create(nil); //make a string stream
Key:= TScKey.Create(nil); //make a key object
SStream.Position := 0; //set Stream start position
SStream.WriteString(PUBLIC_KEY); //put the key text into the stream
Key.ImportFrom(SStream); //fill the key with the contents of the stream i.e. the key text
Key.KeyName := 'ThePublicKey'; //give the key a name that can be used by a TScSSHClient
MemoryStorage.Keys.Add(key); //store the key in the memory storage object
...
if this is not correct then please tell me
Re: How to store keys in a TScMemoryStorage;?
Posted: Sat 31 Oct 2020 09:24
by ViktorV
Since the line Key := TScKey.Create(MemoryStorage.Keys); is specified before importing the key, the key will be created automatically in the MemoryStorage component. Your code will have the same effect though.
Re: How to store keys in a TScMemoryStorage;?
Posted: Sat 31 Oct 2020 13:15
by docH
I'm afraid neither method of using a TScMemoryStorage worked. Both gave a 'Key not verified' error.
I could connect OK via SSH using a TScFileStorage, with password authentication and just a public key ie no private key.
using these connections and a public key stored in the TScFileStorage
Code: Select all
TMyConnection -> TMyQuery -> TDataSource TMtSSHIOHandler ->TSSHClient -> TScFileStorage
^
|
TDBGrid
However, if at design time, I connected the TScSSHClient to a TScMemory storage instead of a TScFileStorage, put the same public key (correctly constructed using line feeds) into a constant and used the same key name I got a 'Key not verified' error when I added the following code before opening the query.
Code: Select all
procedure TForm1.BtnOpenQueryClick(Sender: TObject);
var
Key: TscKey; //to hold the key}
SStream: TStringStream; // to enable us to transfer a string constant initialization a key
begin
// set up the public key in the TScMemoryStorage
Key := TScKey.Create(LV_ScMemoryStorage.Keys);
SStream:=TStringStream.Create(JHM_LIVE_PUBLIC_KEY);
{debug} SStream.SaveToFile('testfile.txt'); //to check we are using the right key
try
Key.ImportFrom(SStream); //fill the key with the contents of the stream i.e. the key text
Key.KeyName := LIVE_PUBLIC_KEY_NAME; //same key name as was used in the TScFileStorage version
finally
SStream.Free;
Key.Free;
end;
LV_MyQuery.Open;
end;
Re: How to store keys in a TScMemoryStorage;?
Posted: Mon 02 Nov 2020 14:25
by ViktorV
The TScMemoryStorage component is designed to store certificates and keys only in the RAM of the device. Therefore, in runtime, certificates and keys are stored in the local memory of the running application, and in designtime, they are stored only while working in the property editor TScMemoryStorage and as soon as you close it they are automatically deleted. Therefore, to work with the keys in your application, you should run the keys in the runtime each time into the TScMemoryStorage component, even the ones that you downloaded in the design.
When the TScKey.Free method is called, the information about the key is cleared and you should get the "Object not found" error; the TScKey.Ready property will be set to False.
To resolve the issue, try to avoid calling the TScKey.Free method; the key will be automatically deleted when TScMemoryStorarge is released.
If this doesn't help, please create and send us an example demonstrating the incorrect behavior, along with all necessary files, through the contact form:
https://www.devart.com/company/contactform.html