Read private key from string (not file)

Advertisement

matrixiux
Joined:
Posts:
6

Read private key from string (not file)

We are storing our Private SSH Key in Azure Key Vault.
We retrieve it as a string, where string the whole key.
WinSCP COM library only allows adding SshPrivateKeyPath in the SessionOptions.

Now we don't want to write out the key in a text file, as that would beat the purpose of storing the key in to Azure Key Vault, for security reasons.

Is there a hidden way to load the key as a string or similar, and not a a physical file?

Azure Key Vault is client's requirement.

Reply with quote

Advertisement

matrixiux

Do you know if that's on the road map, or would be considered? We already have existing services running WinSCP in the code, but this feature made us re-develop for an alternative library.

Reply with quote

martin
Site Admin
martin avatar

Re: Read private key from string (not file)

It's not on the road map, as it's not frequently requested, sorry.

Reply with quote

bobbabooie
Joined:
Posts:
1
Location:
North Pole

Re: Read private key from string (not file)

@martin: I'd upvote this. It's arguable that it may be more secure to pass the key as a string of text rather than having it persisted to a file. In our case we're using SSIS to call winscp.com and we have secure variables in SSIS. If I have to persist it to a file, then that creates more "surface area" that we have to manage securely (make sure it gets deleted, make sure the file as proper permissions and/or in a location that's not accessible to those that shouldn't have read access, etc). I'm not an expert but it might be something to look at.. sort of treat it like a password parameter, since that's how things are going these days (key-based auth).

Reply with quote

Advertisement

randallg
Donor
Joined:
Posts:
5

Re: Read private key from string (not file)

I just voted for this change. I also donated so that is 4 more votes for!
In our case we store the file in the .NET assembly as a resource, but I would like to avoid having to write it to disk every time.
void open()
{
   string keyfile = Path.GetTempPath() + Guid.NewGuid().ToString() + ".ppk";
   using (var keystream = Assembly.GetExecutingAssembly().GetManifestResourceStream(StockwatchPpkResource)) {
      Util.SlopFile(keyfile, new StreamReader(keystream));
   }
   session = new Session();
   session.DisableVersionCheck = true;
   SessionOptions sessionOptions = new SessionOptions {
      Protocol = Protocol.Sftp,
      ... other stuff
      SshPrivateKeyPath = keyfile,
   };
   session.Open(sessionOptions);
   File.Delete(keyfile);
}

Reply with quote

Advertisement

martin
Site Admin
martin avatar

Re: Read private key from string (not file)

@randallg: I'm sending you an email with a development version of WinSCP to the address you have used to register on this forum.

Reply with quote

AKG
Guest

Re: Read private key from string (not file)

Hi, I have tried passing the ssh key as a string but always getting error: Unable to use key file "in-memory" (not a recognised key file format).

I have tried many combinations, tried converting it in Hex string, prefixed with @, but every time getting the same error. While through file it is working fine.

Could you please help me with an example, like what part of ppk file and in which format we need to pass for this feature?

Thanks in advance.

Reply with quote

Advertisement

randallg
Donor
Joined:
Posts:
5

Re: Read private key from string (not file)

@AKG: In my case the key file is stored as a resource in my .NET assembly.
I know nothing of the format of the ppk file, it is plain text generated for you and looks like this:
PuTTY-User-Key-File-2: ssh-rsa
Encryption: none
Comment: rsa-key-20200928
Public-Lines: 6
AAAAB3NzaC1yc2EAAAABJQAAAQEAtLcfmQXeqb3Bk5dNoKAQ1gvZScMnrbGkRvsJ
...  more lines like the above

I access in code like this:
void open()
{
   if (session != null) return;
   string key;
   using (Stream keystream = Assembly.GetExecutingAssembly().GetManifestResourceStream(StockwatchPpkResource)) {
      key = new StreamReader(keystream).ReadToEnd();
   }
   session = new Session {
      DisableVersionCheck = true
   };
   SessionOptions sessionOptions = new SessionOptions {
      Protocol = Protocol.Sftp,
      HostName = StockwatchHost,
      UserName = StockwatchUser,
      SshHostKeyFingerprint = StockwatchSshHostKeyFingerprint,
      SshPrivateKey = key
   };
   session.Open(sessionOptions);
}

Reply with quote

martin
Site Admin
martin avatar
Joined:
Posts:
41,285
Location:
Prague, Czechia

Re: Read private key from string (not file)

@AKG: No @ prefixing. No hex encoding. That's needed in scripting only. In .NET assembly, just pass the contents of your key file to SessionOptions.SshPrivateKey as it is, as @randallg has shown. No special encoding.

If this works:
sessionOptions.SshPrivateKeyPath = @"C:\path\key.ppk"
Then this does the same:
sessionOptions.SshPrivateKey = File.ReadAllText(@"C:\path\key.ppk")

Reply with quote

olinton
Guest

PPKs stored in Azure Key Vault

I've referred to this forum and this post multiple times recently in support of an Azure function I've been working on and just wanted to add a resource which I found helpful for storing .ppk's in an Azure Key Vault. From what I understand, manually adding the plaintext value of the .ppk to the key vault messes the formatting so it has to be done programmatically which I did using Azure CLI, as follows:
Set-AzKeyVaultSecret -VaultName my-key-vault-name -Name SshPrivateKey -SecretValue (ConvertTo-SecureString (Get-Content ./SshPrivateKey.ppk -Raw) -force -AsPlainText)

I adapted that snippet from the reference below in, adding my .ppk file with the name SshPrivateKey and access it using standard Key Vault libraries:

static string GetSecretFromKeyVault(string secretName)
{
    var keyVaultUrl = "https://mykeyvault.vault.azure.net/";
    var client = new SecretClient(new Uri(keyVaultUrl), new DefaultAzureCredential());
    KeyVaultSecret secret = client.GetSecret(secretName);
    return secret.Value;
}
...
string SshPrivateKey = GetSecretFromKeyVault("SshPrivateKey");
...
 
SessionOptions sessionOptions = new SessionOptions
{
    ...
    SshPrivateKey = SshPrivateKey,
    ...
};

Hopefully that's helpful for anyone else that needs to figure this out in the future.
Ref: Storing SSH & PGP Keys in Azure Key Vault – BrownBot

Reply with quote

Advertisement

You can post new topics in this forum