using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using System.Windows; namespace Ramitta.lib { public class CryptoHelper { /// /// 通过OpenSSH格式私钥计算公钥(Base64格式) /// /// OpenSSH格式的Base64私钥(不带PEM头尾) /// Base64格式的公钥,失败返回null public static string? GetPublicKeyFromPrivate(string openSshPrivateKey) { try { using (var rsa = RSA.Create()) { // 解析OpenSSH私钥格式 ImportOpenSshPrivateKey(rsa, openSshPrivateKey); // 导出公钥为Base64 byte[] publicKeyBytes = rsa.ExportRSAPublicKey(); return Convert.ToBase64String(publicKeyBytes); } } catch (Exception ex) { MessageBox.Show($"从私钥提取公钥失败: {ex.Message}"); return null; } } /// /// 导入OpenSSH格式的私钥(纯Base64编码) /// private static void ImportOpenSshPrivateKey(RSA rsa, string openSshBase64) { byte[] keyData = Convert.FromBase64String(openSshBase64); using (var reader = new BinaryReader(new MemoryStream(keyData))) { // 读取魔术字 var magic = reader.ReadBytes(15); string magicString = Encoding.ASCII.GetString(magic); if (magicString != "openssh-key-v1\0") throw new FormatException("无效的OpenSSH私钥格式"); // 读取加密信息 var cipherName = ReadLengthPrefixedString(reader); var kdfName = ReadLengthPrefixedString(reader); var kdfOptions = ReadLengthPrefixedData(reader); // 检查是否加密 if (cipherName != "none" || kdfName != "none") throw new FormatException("不支持加密的OpenSSH私钥"); // 读取密钥数量 var keyCount = ReadUInt32BigEndian(reader); if (keyCount != 1) throw new FormatException("不支持多个密钥"); // 读取公钥(跳过) var publicKey = ReadLengthPrefixedData(reader); // 读取私钥数据 var privateKeyData = ReadLengthPrefixedData(reader); // 解析私钥数据 using (var privateReader = new BinaryReader(new MemoryStream(privateKeyData))) { // 检查字节序标记 var check1 = privateReader.ReadUInt32(); var check2 = privateReader.ReadUInt32(); if (check1 != check2) throw new FormatException("私钥检查值不匹配"); // 读取密钥类型 var keyType = ReadLengthPrefixedString(privateReader); if (keyType != "ssh-rsa") throw new FormatException("非RSA密钥"); // 读取RSA参数 var modulus = ReadLengthPrefixedData(privateReader); // n var publicExponent = ReadLengthPrefixedData(privateReader); // e var privateExponent = ReadLengthPrefixedData(privateReader); // d var coefficient = ReadLengthPrefixedData(privateReader); // iqmp var prime1 = ReadLengthPrefixedData(privateReader); // p var prime2 = ReadLengthPrefixedData(privateReader); // q // 创建RSA参数并导入 var rsaParameters = new RSAParameters { Modulus = modulus, Exponent = publicExponent, D = privateExponent, P = prime1, Q = prime2, InverseQ = coefficient }; rsa.ImportParameters(rsaParameters); } } } /// /// 读取长度前缀字符串 /// private static string ReadLengthPrefixedString(BinaryReader reader) { var data = ReadLengthPrefixedData(reader); return Encoding.ASCII.GetString(data); } /// /// 读取长度前缀数据 /// private static byte[] ReadLengthPrefixedData(BinaryReader reader) { var length = ReadUInt32BigEndian(reader); return reader.ReadBytes((int)length); } /// /// 以大端序读取uint32 /// private static uint ReadUInt32BigEndian(BinaryReader reader) { var data = reader.ReadBytes(4); if (BitConverter.IsLittleEndian) Array.Reverse(data); return BitConverter.ToUInt32(data, 0); } /// /// 使用OpenSSH格式私钥对数据进行签名 /// public static string? SignDataWithOpenSsh(string data, string openSshPrivateKey) { try { using (var rsa = RSA.Create()) { ImportOpenSshPrivateKey(rsa, openSshPrivateKey); byte[] dataBytes = Encoding.UTF8.GetBytes(data); byte[] signature = rsa.SignData(dataBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); return Convert.ToBase64String(signature); } } catch (Exception ex) { return null; } } /// /// 使用OpenSSH格式私钥解密数据 /// public static string? DecryptWithOpenSsh(string encryptedData, string openSshPrivateKey) { try { using (var rsa = RSA.Create()) { ImportOpenSshPrivateKey(rsa, openSshPrivateKey); byte[] encryptedBytes = Convert.FromBase64String(encryptedData); byte[] decryptedBytes = rsa.Decrypt(encryptedBytes, RSAEncryptionPadding.OaepSHA256); return Encoding.UTF8.GetString(decryptedBytes); } } catch (Exception ex) { return null; } } /// /// 获取OpenSSH格式私钥的密钥长度 /// public static int GetOpenSshKeySize(string openSshPrivateKey) { try { using (var rsa = RSA.Create()) { ImportOpenSshPrivateKey(rsa, openSshPrivateKey); return rsa.KeySize; } } catch (Exception ex) { MessageBox.Show($"获取密钥长度失败: {ex.Message}"); return -1; } } // 其他原有方法保持不变... public static (string publicKey, string privateKey) GenerateKeyPair(int keySize = 2048) { try { using (var rsa = RSA.Create(keySize)) { byte[] publicKeyBytes = rsa.ExportRSAPublicKey(); byte[] privateKeyBytes = rsa.ExportRSAPrivateKey(); string publicKey = Convert.ToBase64String(publicKeyBytes); string privateKey = Convert.ToBase64String(privateKeyBytes); return (publicKey, privateKey); } } catch (Exception ex) { MessageBox.Show($"密钥生成失败: {ex.Message}"); return (null, null); } } public static string? SignData(string data, string privateKey) { try { using (var rsa = RSA.Create()) { byte[] privateKeyBytes = Convert.FromBase64String(privateKey); try { rsa.ImportRSAPrivateKey(privateKeyBytes, out _); } catch { rsa.ImportPkcs8PrivateKey(privateKeyBytes, out _); } byte[] dataBytes = Encoding.UTF8.GetBytes(data); byte[] signature = rsa.SignData(dataBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); return Convert.ToBase64String(signature); } } catch (Exception ex) { return null; } } // 其他方法... } }