<PackageReference Include="SSH.NET" Version="2020.0.1" />

EcdsaKey

public class EcdsaKey : Key, IDisposable
Contains ECDSA (ecdsa-sha2-nistp{256,384,521}) private and public key
using Renci.SshNet.Common; using Renci.SshNet.Security.Cryptography; using System; using System.Security.Cryptography; using System.Text; namespace Renci.SshNet.Security { public class EcdsaKey : Key, IDisposable { internal const string ECDSA_P256_OID_VALUE = "1.2.840.10045.3.1.7"; internal const string ECDSA_P384_OID_VALUE = "1.3.132.0.34"; internal const string ECDSA_P521_OID_VALUE = "1.3.132.0.35"; private EcdsaDigitalSignature _digitalSignature; private bool _isDisposed; public HashAlgorithmName HashAlgorithm { get { switch (KeyLength) { case 256: return HashAlgorithmName.SHA256; case 384: return HashAlgorithmName.SHA384; case 521: return HashAlgorithmName.SHA512; default: return HashAlgorithmName.SHA256; } } } public override int KeyLength => Ecdsa.KeySize; protected override DigitalSignature DigitalSignature { get { if (_digitalSignature == null) _digitalSignature = new EcdsaDigitalSignature(this); return _digitalSignature; } } public override BigInteger[] Public { get { ECParameters eCParameters = Ecdsa.ExportParameters(false); byte[] x = eCParameters.Q.X; byte[] y = eCParameters.Q.Y; byte[] bytes; switch (eCParameters.Curve.Oid.FriendlyName) { case "ECDSA_P256": case "nistP256": bytes = Encoding.ASCII.GetBytes("nistp256"); break; case "ECDSA_P384": case "nistP384": bytes = Encoding.ASCII.GetBytes("nistp384"); break; case "ECDSA_P521": case "nistP521": bytes = Encoding.ASCII.GetBytes("nistp521"); break; default: throw new SshException("Unexpected Curve Name: " + eCParameters.Curve.Oid.FriendlyName); } byte[] array = new byte[1 + x.Length + y.Length]; Buffer.SetByte(array, 0, 4); Buffer.BlockCopy(x, 0, array, 1, x.Length); Buffer.BlockCopy(y, 0, array, x.Length + 1, y.Length); return new BigInteger[2] { new BigInteger(bytes.Reverse()), new BigInteger(array.Reverse()) }; } set { string string = Encoding.ASCII.GetString(value[0].ToByteArray().Reverse()); string curveOid = GetCurveOid(string); byte[] publickey = value[1].ToByteArray().Reverse(); Import(curveOid, publickey, null); } } public ECDsa Ecdsa { get; set; } public override string ToString() { return $"""{KeyLength}"; } public EcdsaKey() { } public EcdsaKey(string curve, byte[] publickey, byte[] privatekey) { Import(GetCurveOid(curve), publickey, privatekey); } public EcdsaKey(byte[] data) { DerData derData = new DerData(data, false); derData.ReadBigInteger(); byte[] privatekey = derData.ReadOctetString().TrimLeadingZeros(); byte b = derData.ReadByte(); if ((b & 224) != 160) throw new SshException($"""{b:""}"); int num = b & 31; if (num != 0) throw new SshException($"""{num}"); byte[] oid = new DerData(derData.ReadBytes(derData.ReadLength()), true).ReadObject(); b = derData.ReadByte(); if ((b & 224) != 160) throw new SshException($"""{b:""}"); num = (b & 31); if (num != 1) throw new SshException($"""{num}"); byte[] publickey = new DerData(derData.ReadBytes(derData.ReadLength()), true).ReadBitString().TrimLeadingZeros(); Import(OidByteArrayToString(oid), publickey, privatekey); } private void Import(string curve_oid, byte[] publickey, byte[] privatekey) { ECCurve curve = ECCurve.CreateFromValue(curve_oid); ECParameters eCParameters = default(ECParameters); eCParameters.Curve = curve; ECParameters parameters = eCParameters; int num = (publickey.Length - 1) / 2; byte[] array = new byte[num]; Buffer.BlockCopy(publickey, 1, array, 0, array.Length); byte[] array2 = new byte[num]; Buffer.BlockCopy(publickey, num + 1, array2, 0, array2.Length); parameters.Q.X = array; parameters.Q.Y = array2; if (privatekey != null) parameters.D = privatekey.TrimLeadingZeros().Pad(num); Ecdsa = ECDsa.Create(parameters); } private string GetCurveOid(string curve_s) { switch (curve_s.ToLower()) { case "nistp256": return "1.2.840.10045.3.1.7"; case "nistp384": return "1.3.132.0.34"; case "nistp521": return "1.3.132.0.35"; default: throw new SshException("Unexpected Curve Name: " + curve_s); } } private string GetCurveName(string oid) { if (oid != null) { if (oid == "1.2.840.10045.3.1.7") return "nistp256"; if (oid == "1.3.132.0.34") return "nistp384"; if (oid == "1.3.132.0.35") return "nistp521"; } throw new SshException("Unexpected OID: " + oid); } private string OidByteArrayToString(byte[] oid) { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < oid.Length; i++) { if (i == 0) { int num = (int)oid[0] % 40; int num2 = (oid[0] - num) / 40; stringBuilder.AppendFormat("{0}.{1}", num2, num); } else if (oid[i] < 128) { stringBuilder.AppendFormat(".{0}", oid[i]); } else { stringBuilder.AppendFormat(".{0}", (oid[i] - 128) * 128 + oid[i + 1]); i++; } } return stringBuilder.ToString(); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (!_isDisposed && disposing) _isDisposed = true; } ~EcdsaKey() { Dispose(false); } } }