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

Windows环境下C# Web应用生成OpenSSH格式SSH密钥对的方案咨询

嘿,我来给你梳理几个可行的方案,不用折腾Cygwin也能在Windows服务器的C# Web应用里生成OpenSSH格式的密钥对:

方案1:用.NET自带API手动生成(无需第三方依赖)

OpenSSH的密钥格式本质是对RSA/ED25519等算法生成的密钥做了特定编码,你可以直接用.NET框架自带的加密类来生成密钥,再手动转换为OpenSSH格式。

举个RSA密钥对生成的示例:

using System;
using System.Security.Cryptography;
using System.Text;

public static class SshKeyGenerator
{
    public static (string PublicKey, string PrivateKey) GenerateRsaKeyPair(int keySize = 2048)
    {
        using var rsa = RSA.Create(keySize);
        
        // 生成OpenSSH格式公钥
        var publicParams = rsa.ExportParameters(false);
        var publicKeyBytes = new byte[11 + Encoding.ASCII.GetByteCount("ssh-rsa") + publicParams.Exponent.Length + publicParams.Modulus.Length];
        var index = 0;
        
        // 写入"ssh-rsa"标识的长度和内容
        var sshRsaBytes = Encoding.ASCII.GetBytes("ssh-rsa");
        WriteBigEndianInt(sshRsaBytes.Length, publicKeyBytes, ref index);
        Array.Copy(sshRsaBytes, 0, publicKeyBytes, index, sshRsaBytes.Length);
        index += sshRsaBytes.Length;
        
        // 写入指数的长度和内容
        WriteBigEndianInt(publicParams.Exponent.Length, publicKeyBytes, ref index);
        Array.Copy(publicParams.Exponent, 0, publicKeyBytes, index, publicParams.Exponent.Length);
        index += publicParams.Exponent.Length;
        
        // 写入模数(去掉开头可能存在的0x00字节)
        var modulus = publicParams.Modulus;
        if (modulus[0] == 0)
        {
            var trimmedModulus = new byte[modulus.Length - 1];
            Array.Copy(modulus, 1, trimmedModulus, 0, trimmedModulus.Length);
            modulus = trimmedModulus;
        }
        WriteBigEndianInt(modulus.Length, publicKeyBytes, ref index);
        Array.Copy(modulus, 0, publicKeyBytes, index, modulus.Length);
        
        var publicKey = $"ssh-rsa {Convert.ToBase64String(publicKeyBytes)} your-app@server";
        
        // 生成兼容OpenSSH的PKCS#8格式私钥
        var privateKey = rsa.ExportPkcs8PrivateKeyPem();
        
        return (publicKey, privateKey);
    }
    
    private static void WriteBigEndianInt(int value, byte[] buffer, ref int index)
    {
        buffer[index++] = (byte)(value >> 24);
        buffer[index++] = (byte)(value >> 16);
        buffer[index++] = (byte)(value >> 8);
        buffer[index++] = (byte)value;
    }
}

优点:完全依赖.NET框架,不需要任何额外组件,兼容性强。
缺点:需要手动处理OpenSSH的编码规则,如果要支持ED25519等其他算法,编码逻辑会更复杂。

方案2:使用BouncyCastle NuGet库(推荐)

BouncyCastle是一款成熟的开源加密库,支持几乎所有主流加密算法,并且可以直接导出OpenSSH格式的密钥对,省去手动编码的麻烦。

首先安装对应版本的NuGet包:

  • .NET Core/.NET 5+:Install-Package BouncyCastle.NetCore
  • .NET Framework:Install-Package BouncyCastle

示例代码(生成ED25519密钥对):

using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
using System.IO;
using System.Text;

public static class SshKeyGenerator
{
    public static (string PublicKey, string PrivateKey) GenerateEd25519KeyPair()
    {
        var generator = new Ed25519KeyPairGenerator();
        generator.Init(new Ed25519KeyGenerationParameters(new SecureRandom()));
        var keyPair = generator.GenerateKeyPair();
        
        // 生成OpenSSH公钥
        var pubParams = (Ed25519PublicKeyParameters)keyPair.Public;
        var pubKeyBytes = new byte[Encoding.ASCII.GetByteCount("ssh-ed25519") + 4 + pubParams.GetEncoded().Length];
        var index = 0;
        
        var sshEdBytes = Encoding.ASCII.GetBytes("ssh-ed25519");
        WriteBigEndianInt(sshEdBytes.Length, pubKeyBytes, ref index);
        Array.Copy(sshEdBytes, 0, pubKeyBytes, index, sshEdBytes.Length);
        index += sshEdBytes.Length;
        
        WriteBigEndianInt(pubParams.GetEncoded().Length, pubKeyBytes, ref index);
        Array.Copy(pubParams.GetEncoded(), 0, pubKeyBytes, index, pubParams.GetEncoded().Length);
        
        var publicKey = $"ssh-ed25519 {Convert.ToBase64String(pubKeyBytes)} your-app@server";
        
        // 生成OpenSSH格式私钥(兼容PKCS#8)
        using var ms = new MemoryStream();
        var writer = new PemWriter(new StreamWriter(ms));
        writer.WriteObject(keyPair.Private);
        writer.Writer.Flush();
        var privateKey = Encoding.UTF8.GetString(ms.ToArray());
        
        return (publicKey, privateKey);
    }
    
    private static void WriteBigEndianInt(int value, byte[] buffer, ref int index)
    {
        buffer[index++] = (byte)(value >> 24);
        buffer[index++] = (byte)(value >> 16);
        buffer[index++] = (byte)(value >> 8);
        buffer[index++] = (byte)value;
    }
}

优点:支持多种算法(RSA、ED25519、ECDSA等),无需手动处理编码细节,成熟稳定。
缺点:需要引入第三方库,但BouncyCastle是完全开源免费的,在.NET生态中非常常用。

方案3:调用Windows自带的ssh-keygen.exe(仅适用于Windows 10 1809+/Server 2019+)

从Windows 10 1809版本和Windows Server 2019开始,系统默认预装了OpenSSH客户端,其中包含ssh-keygen.exe(路径为C:\Windows\System32\OpenSSH\ssh-keygen.exe)。你可以在C#中通过进程调用这个工具生成密钥对。

示例代码:

using System;
using System.Diagnostics;
using System.IO;

public static class SshKeyGenerator
{
    public static (string PublicKey, string PrivateKey) GenerateKeyPairWithSshKeyGen(string tempOutputPath, string passphrase = null)
    {
        var sshKeyGenPath = Path.Combine(Environment.SystemDirectory, "OpenSSH", "ssh-keygen.exe");
        if (!File.Exists(sshKeyGenPath))
        {
            throw new InvalidOperationException("未找到ssh-keygen.exe,请确保系统为Windows 10 1809+/Server 2019+,或手动安装OpenSSH客户端组件");
        }
        
        var args = $"-t rsa -b 2048 -f \"{tempOutputPath}\"";
        args += string.IsNullOrEmpty(passphrase) ? " -N \"\"" : $" -N \"{passphrase}\"";
        
        var processInfo = new ProcessStartInfo
        {
            FileName = sshKeyGenPath,
            Arguments = args,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            UseShellExecute = false,
            CreateNoWindow = true
        };
        
        using var process = Process.Start(processInfo);
        process.WaitForExit();
        
        if (process.ExitCode != 0)
        {
            var errorMsg = process.StandardError.ReadToEnd();
            throw new InvalidOperationException($"生成密钥失败:{errorMsg}");
        }
        
        var publicKey = File.ReadAllText($"{tempOutputPath}.pub");
        var privateKey = File.ReadAllText(tempOutputPath);
        
        // 清理临时文件
        File.Delete(tempOutputPath);
        File.Delete($"{tempOutputPath}.pub");
        
        return (publicKey, privateKey);
    }
}

优点:生成的密钥完全符合OpenSSH标准,支持ssh-keygen的所有参数(如指定算法、密码保护等),无需自己处理格式细节。
缺点:依赖特定Windows版本,旧版本服务器需要手动通过「Windows功能」安装OpenSSH客户端。

关于自行实现的必要性

如果你的场景必须完全脱离第三方库和系统工具,那可以基于方案1的思路,参考OpenSSH密钥格式规范手动实现,但需要处理大量边缘情况(如不同算法的编码差异、密钥校验等)。对于大多数业务场景,方案2或3会更省心可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 09:14:49