【问题标题】:Issue with streaming private key using SSH.NET使用 SSH.NET 流式传输私钥的问题
【发布时间】:2017-05-22 22:57:47
【问题描述】:

我正在使用 Renci.SshNet 库,并使用用户名和私钥让它工作。当从文件或文件流中读取私钥时,我可以让私钥正常打开,但在内存流期间会失败。

这行得通:

var pk = new PrivateKeyFile(@"C:\myfile.ppk");

这行得通:

var f = new FileStream(@"C:\myfile.ppk", FileMode.Open, FileAccess.Read);
var pk = new PrivateKeyFile(f);

这些失败并显示“无效的私钥”。

var s = new MemoryStream(Encoding.UTF8.GetBytes(variablename));
//No carriage returns
var s = new MemoryStream(Encoding.UTF8.GetBytes(@"-----BEGIN RSA PRIVATE KEY----- <snip>"));
//Include carriage returns
var s = new MemoryStream(Encoding.UTF8.GetBytes(@"-----BEGIN RSA PRIVATE KEY----- <snip>"));

我什至尝试了在 SO 上找到的流位置:

private Stream GenerateStreamFromString(string s)
{
    MemoryStream stream = new MemoryStream();
    StreamWriter writer = new StreamWriter(stream);
    writer.Write(s);
    writer.Flush();
    stream.Position = 0;
    return stream;
}

我一开始以为 Renci 库在 Stream 上有一个错误,但显然文件流有效。我计划将字符串格式的密钥托管在一个 azure 存储表中,但我对其他想法持开放态度。

【问题讨论】:

    标签: c# azure ssh ssh.net


    【解决方案1】:

    以上答案对我有帮助。我遇到了完全相同的问题,直接从文件中读取工作但无法让内存流工作。它每次都会给出错误“无效的私钥”。

    我将文件读入内存流的方式是这样的:

    byte[] bytes = ReadSSHKeyFromDatabase();
    MemoryStream ms = new MemoryStream();
    ms.Read(bytes, 0, bytes.Length);
    Renci.SshNet.PrivateKeyFile pkf = new Renci.SshNet.PrivateKeyFile(ms, Password);
    

    但是我通过将其更改为:

    byte[] bytes = ReadSSHKeyFromDatabase();
    MemoryStream ms = new MemoryStream(bytes);
    Renci.SshNet.PrivateKeyFile pkf = new Renci.SshNet.PrivateKeyFile(ms, Password);
    

    【讨论】:

      【解决方案2】:

      根据您的描述,我使用PuTTYgen通过SSH生成了我的私钥文件,并通过参考tutorial将我的密钥转换为OpenSSH格式。根据你提供的关于使用MemoryStream的代码,我可以让它按我的预期工作,你可以参考它:

      var f = new MemoryStream(Encoding.UTF8.GetBytes(@"-----BEGIN RSA PRIVATE KEY-----
      ...
      -----END RSA PRIVATE KEY-----");
      var pk = new PrivateKeyFile(f, "{password}");
      

      注意:我认为传递给Encoding.UTF8.GetBytes 的私钥的字符串内容格式不正确。为了隔离这个原因,您可以尝试将加载的MemoryStream 保存到文件中,如下代码,并将其与C:\myfile.ppk 进行比较。

      memoryStream.CopyTo(fileStream);
      

      我计划在一个 azure 存储表中以字符串格式托管密钥,但我对其他想法持开放态度

      据我所知,对于托管在 Azure Web App 上的 Web 应用程序,您可以利用 app settings 来存储键值对,这些键值对可以在运行时自动加载并覆盖 web.config 文件中的现有 appsettings。

      此外,您可以利用Azure Blob storage 将您的私钥文件存储为私有并按如下方式检索它:

      using(var ms=new MemoryStream())
      {
         cloudBlockBlob.DownloadToStream(ms);
         var pk = new PrivateKeyFile(ms, "{password}"); 
      }
      

      注意:您可以按照此tutorial 中的“加密 blob 数据”部分在客户端和服务器端加密您的 blob 数据。

      此外,您可以利用Azure Key Vault 来存储您的私钥。更多细节,你可以参考这个官方document开始使用Azure Key Vault。

      【讨论】:

      • 我想我被这个蒙蔽了,你的基本调试东西帮了大忙——我的脑袋深陷在这个问题上,以至于忘记了基本的调试细节。出于某种原因,从 Notepad++ 到 Azure 表的复制/粘贴在其中插入了一些错误字符——不知道。在“/”字符周围放置空格,可能是某种类型的天蓝色转义。我将字符串从 azure 复制回 Visual Studio 和 bam!但更重要的是,我认为你是对的,我更喜欢你的解决方案,将整个文件存储在 BLOB 中并从那里流式传输,而不用担心格式。谢谢你的想法,我同意了。
      猜你喜欢
      • 2016-01-20
      • 1970-01-01
      • 2016-07-22
      • 1970-01-01
      • 2019-05-19
      • 2011-07-06
      • 2020-10-11
      • 1970-01-01
      • 2016-03-24
      相关资源
      最近更新 更多