You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无需ssh-keygen,C#应用生成SSH.NET兼容密钥及格式转换方案

C#中生成兼容SSH.NET的ECDSA384密钥对及公钥格式转换

1. 当前实现方式是否合理?

  • 整体方向合理:用BouncyCastle在应用内生成ECDSA384密钥对,解决了用户无ssh-keygen权限的问题,且ECDSA384是SSH.NET明确支持的公钥算法。
  • 需注意私钥格式兼容性:SSH.NET对PKCS#8格式的PEM私钥支持更稳定,生成时要确保输出PKCS#8格式(而非传统PKCS#1)。可通过BouncyCastle的Pkcs8Generator类生成该格式私钥,避免因格式不兼容导致SSH.NET无法加载。
  • 额外注意:生成密钥时必须指定标准椭圆曲线secp384r1(对应nistp384),这是SSH协议中ECDSA384的规范曲线,确保与服务端兼容。

2. 如何将OpenSSL PEM格式公钥转换为OpenSSH格式?

由于无法使用ssh-keygen,可通过手动解析PEM并构造OpenSSH格式公钥,核心实现如下:

核心原理

OpenSSH的ECDSA公钥结构为:

[算法标识长度(4字节大端)][算法标识字符串][公钥数据长度(4字节大端)][公钥数据]

其中:

  • 算法标识固定为ecdsa-sha2-nistp384
  • 公钥数据是未压缩EC点:前缀0x04 + 384位X坐标字节 + 384位Y坐标字节

C#实现代码(基于BouncyCastle)

using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using System;
using System.IO;
using System.Text;

public static string ConvertEcdsaPemToOpenSsh(string pemPublicKey)
{
    // 清理PEM格式的头尾和换行符
    var cleanedPem = pemPublicKey
        .Replace("-----BEGIN PUBLIC KEY-----", "")
        .Replace("-----END PUBLIC KEY-----", "")
        .Replace("\r", "")
        .Replace("\n", "");
    
    // Base64解码得到DER格式字节
    var derBytes = Convert.FromBase64String(cleanedPem);
    
    // 解析DER格式的EC公钥
    var asn1Seq = Asn1Sequence.GetInstance(derBytes);
    var pubKeyInfo = SubjectPublicKeyInfo.GetInstance(asn1Seq);
    var ecPubKey = (ECPublicKeyParameters)PublicKeyFactory.CreateKey(pubKeyInfo);
    
    // 获取未压缩的公钥点字节(0x04 + X坐标 + Y坐标)
    var pubKeyBytes = ecPubKey.Q.GetEncoded(false);
    
    // 构造OpenSSH公钥的字节流
    var algorithmBytes = Encoding.UTF8.GetBytes("ecdsa-sha2-nistp384");
    using var ms = new MemoryStream();
    
    // 写入算法标识的长度和内容
    WriteBigEndianInt(ms, algorithmBytes.Length);
    ms.Write(algorithmBytes, 0, algorithmBytes.Length);
    
    // 写入公钥数据的长度和内容
    WriteBigEndianInt(ms, pubKeyBytes.Length);
    ms.Write(pubKeyBytes, 0, pubKeyBytes.Length);
    
    // 编码为Base64并拼接前缀
    var openSshBase64 = Convert.ToBase64String(ms.ToArray());
    return $"ecdsa-sha2-nistp384 {openSshBase64}"; // 可追加用户标识,如 " user@example.com"
}

// 写入大端格式的4字节整数
private static void WriteBigEndianInt(Stream stream, int value)
{
    var bytes = BitConverter.GetBytes(value);
    if (BitConverter.IsLittleEndian)
        Array.Reverse(bytes);
    stream.Write(bytes, 0, bytes.Length);
}

验证方式

生成的OpenSSH格式公钥可直接添加到SSH服务端的authorized_keys文件中,测试是否能通过SSH.NET使用对应私钥完成认证。


内容的提问来源于stack exchange,提问作者Thomas853

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 14:12:59