From dfee3ef82d2219faadb84e4f2b2ccf5da5c823af Mon Sep 17 00:00:00 2001 From: Scott Xu Date: Fri, 20 Sep 2024 23:11:17 +0800 Subject: [PATCH] Minimize the change --- src/Renci.SshNet/PrivateKeyFile.cs | 86 +++++++++++++++---- .../Security/Cryptography/DsaKey.cs | 16 +--- .../Security/Cryptography/EcdsaKey.cs | 2 +- .../Security/Cryptography/RsaKey.cs | 1 + test/Renci.SshNet.Tests/.editorconfig | 4 + 5 files changed, 74 insertions(+), 35 deletions(-) diff --git a/src/Renci.SshNet/PrivateKeyFile.cs b/src/Renci.SshNet/PrivateKeyFile.cs index 2b00d30b5..d50902b92 100644 --- a/src/Renci.SshNet/PrivateKeyFile.cs +++ b/src/Renci.SshNet/PrivateKeyFile.cs @@ -314,25 +314,80 @@ private void Open(Stream privateKey, string? passPhrase) switch (keyName) { case "RSA PRIVATE KEY": - _key = new RsaKey(decryptedData); + var rsaKey = new RsaKey(decryptedData); + _key = rsaKey; + _hostAlgorithms.Add(new KeyHostAlgorithm("ssh-rsa", _key)); +#pragma warning disable CA2000 // Dispose objects before losing scope + _hostAlgorithms.Add(new KeyHostAlgorithm("rsa-sha2-512", _key, new RsaDigitalSignature(rsaKey, HashAlgorithmName.SHA512))); + _hostAlgorithms.Add(new KeyHostAlgorithm("rsa-sha2-256", _key, new RsaDigitalSignature(rsaKey, HashAlgorithmName.SHA256))); +#pragma warning restore CA2000 // Dispose objects before losing scope break; case "DSA PRIVATE KEY": _key = new DsaKey(decryptedData); + _hostAlgorithms.Add(new KeyHostAlgorithm("ssh-dss", _key)); break; case "EC PRIVATE KEY": _key = new EcdsaKey(decryptedData); + _hostAlgorithms.Add(new KeyHostAlgorithm(_key.ToString(), _key)); break; case "PRIVATE KEY": var privateKeyInfo = PrivateKeyInfo.GetInstance(binaryData); _key = ParseOpenSslPkcs8PrivateKey(privateKeyInfo); + if (_key is RsaKey parsedRsaKey) + { + _hostAlgorithms.Add(new KeyHostAlgorithm("ssh-rsa", _key)); +#pragma warning disable CA2000 // Dispose objects before losing scope + _hostAlgorithms.Add(new KeyHostAlgorithm("rsa-sha2-512", _key, new RsaDigitalSignature(parsedRsaKey, HashAlgorithmName.SHA512))); + _hostAlgorithms.Add(new KeyHostAlgorithm("rsa-sha2-256", _key, new RsaDigitalSignature(parsedRsaKey, HashAlgorithmName.SHA256))); +#pragma warning restore CA2000 // Dispose objects before losing scope + } + else if (_key is DsaKey parsedDsaKey) + { + _hostAlgorithms.Add(new KeyHostAlgorithm("ssh-dss", _key)); + } + else + { + _hostAlgorithms.Add(new KeyHostAlgorithm(_key.ToString(), _key)); + } + break; case "ENCRYPTED PRIVATE KEY": var encryptedPrivateKeyInfo = EncryptedPrivateKeyInfo.GetInstance(binaryData); privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(passPhrase?.ToCharArray(), encryptedPrivateKeyInfo); _key = ParseOpenSslPkcs8PrivateKey(privateKeyInfo); + if (_key is RsaKey parsedRsaKey2) + { + _hostAlgorithms.Add(new KeyHostAlgorithm("ssh-rsa", _key)); +#pragma warning disable CA2000 // Dispose objects before losing scope + _hostAlgorithms.Add(new KeyHostAlgorithm("rsa-sha2-512", _key, new RsaDigitalSignature(parsedRsaKey2, HashAlgorithmName.SHA512))); + _hostAlgorithms.Add(new KeyHostAlgorithm("rsa-sha2-256", _key, new RsaDigitalSignature(parsedRsaKey2, HashAlgorithmName.SHA256))); +#pragma warning restore CA2000 // Dispose objects before losing scope + } + else if (_key is DsaKey parsedDsaKey) + { + _hostAlgorithms.Add(new KeyHostAlgorithm("ssh-dss", _key)); + } + else + { + _hostAlgorithms.Add(new KeyHostAlgorithm(_key.ToString(), _key)); + } + break; case "OPENSSH PRIVATE KEY": _key = ParseOpenSshV1Key(decryptedData, passPhrase); + if (_key is RsaKey parsedRsaKey3) + { + _hostAlgorithms.Add(new KeyHostAlgorithm("ssh-rsa", _key)); +#pragma warning disable CA2000 // Dispose objects before losing scope + _hostAlgorithms.Add(new KeyHostAlgorithm("rsa-sha2-512", _key, new RsaDigitalSignature(parsedRsaKey3, HashAlgorithmName.SHA512))); + _hostAlgorithms.Add(new KeyHostAlgorithm("rsa-sha2-256", _key, new RsaDigitalSignature(parsedRsaKey3, HashAlgorithmName.SHA256))); +#pragma warning restore CA2000 // Dispose objects before losing scope + } + else + { + _hostAlgorithms.Add(new KeyHostAlgorithm(_key.ToString(), _key)); + } + break; case "SSH2 ENCRYPTED PRIVATE KEY": var reader = new SshDataReader(decryptedData); @@ -389,7 +444,13 @@ private void Open(Stream privateKey, string? passPhrase) var inverseQ = reader.ReadBigIntWithBits(); // u var q = reader.ReadBigIntWithBits(); // p var p = reader.ReadBigIntWithBits(); // q - _key = new RsaKey(modulus, exponent, d, p, q, inverseQ); + var decryptedRsaKey = new RsaKey(modulus, exponent, d, p, q, inverseQ); + _key = decryptedRsaKey; + _hostAlgorithms.Add(new KeyHostAlgorithm("ssh-rsa", _key)); +#pragma warning disable CA2000 // Dispose objects before losing scope + _hostAlgorithms.Add(new KeyHostAlgorithm("rsa-sha2-512", _key, new RsaDigitalSignature(decryptedRsaKey, HashAlgorithmName.SHA512))); + _hostAlgorithms.Add(new KeyHostAlgorithm("rsa-sha2-256", _key, new RsaDigitalSignature(decryptedRsaKey, HashAlgorithmName.SHA256))); +#pragma warning restore CA2000 // Dispose objects before losing scope } else if (keyType.Contains("dsa")) { @@ -405,6 +466,7 @@ private void Open(Stream privateKey, string? passPhrase) var y = reader.ReadBigIntWithBits(); var x = reader.ReadBigIntWithBits(); _key = new DsaKey(p, q, g, y, x); + _hostAlgorithms.Add(new KeyHostAlgorithm("ssh-dss", _key)); } else { @@ -415,19 +477,6 @@ private void Open(Stream privateKey, string? passPhrase) default: throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Key '{0}' is not supported.", keyName)); } - - if (_key is RsaKey parsedRsaKey) - { - _hostAlgorithms.Add(new KeyHostAlgorithm("ssh-rsa", _key)); -#pragma warning disable CA2000 // Dispose objects before losing scope - _hostAlgorithms.Add(new KeyHostAlgorithm("rsa-sha2-512", _key, new RsaDigitalSignature(parsedRsaKey, HashAlgorithmName.SHA512))); - _hostAlgorithms.Add(new KeyHostAlgorithm("rsa-sha2-256", _key, new RsaDigitalSignature(parsedRsaKey, HashAlgorithmName.SHA256))); -#pragma warning restore CA2000 // Dispose objects before losing scope - } - else - { - _hostAlgorithms.Add(new KeyHostAlgorithm(_key.ToString(), _key)); - } } private static byte[] GetCipherKey(string passphrase, int length) @@ -692,15 +741,14 @@ private static Key ParseOpenSshV1Key(byte[] keyFileData, string? passPhrase) case "ecdsa-sha2-nistp521": // curve var len = (int)privateKeyReader.ReadUInt32(); - var curveName = Encoding.ASCII.GetString(privateKeyReader.ReadBytes(len)); - var curveOid = SshNamedCurves.GetOid(curveName).GetID(); + var curve = Encoding.ASCII.GetString(privateKeyReader.ReadBytes(len)); // public key publicKey = privateKeyReader.ReadBignum2(); // private key unencryptedPrivateKey = privateKeyReader.ReadBignum2(); - parsedKey = new EcdsaKey(curveOid, publicKey, unencryptedPrivateKey); + parsedKey = new EcdsaKey(curve, publicKey, unencryptedPrivateKey.TrimLeadingZeros()); break; case "ssh-rsa": var modulus = privateKeyReader.ReadBignum(); // n @@ -796,7 +844,7 @@ private static Key ParseOpenSslPkcs8PrivateKey(PrivateKeyInfo privateKeyInfo) sequenceReader.ThrowIfNotEmpty(); - return new EcdsaKey(curve, publickey, privatekey); + return new EcdsaKey(curve, publickey, privatekey.TrimLeadingZeros()); } if (algorithmOid.Equals(EdECObjectIdentifiers.id_Ed25519)) diff --git a/src/Renci.SshNet/Security/Cryptography/DsaKey.cs b/src/Renci.SshNet/Security/Cryptography/DsaKey.cs index 2a394b25b..a1102b572 100644 --- a/src/Renci.SshNet/Security/Cryptography/DsaKey.cs +++ b/src/Renci.SshNet/Security/Cryptography/DsaKey.cs @@ -16,17 +16,6 @@ public class DsaKey : Key, IDisposable { private DsaDigitalSignature? _digitalSignature; - /// - /// Gets the SSH name of the DSA Key. - /// - /// - /// The SSH name of the DSA Key. - /// - public override string ToString() - { - return "ssh-dss"; - } - internal DSA DSA { get; } /// @@ -122,10 +111,7 @@ public DsaKey(SshKeyData publicKeyData) /// DER encoded private key data. public DsaKey(byte[] privateKeyData) { - if (privateKeyData is null) - { - throw new ArgumentNullException(nameof(privateKeyData)); - } + ThrowHelper.ThrowIfNull(privateKeyData); var der = new AsnReader(privateKeyData, AsnEncodingRules.DER).ReadSequence(); _ = der.ReadInteger(); // skip version diff --git a/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs b/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs index 31957c10e..c970a323e 100644 --- a/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs +++ b/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs @@ -209,7 +209,7 @@ public EcdsaKey(SshKeyData publicKeyData) /// Value of privatekey. public EcdsaKey(string curve, byte[] publickey, byte[] privatekey) { - _impl = Import(GetCurveOid(curve), publickey, privatekey.TrimLeadingZeros()); + _impl = Import(GetCurveOid(curve), publickey, privatekey); } /// diff --git a/src/Renci.SshNet/Security/Cryptography/RsaKey.cs b/src/Renci.SshNet/Security/Cryptography/RsaKey.cs index e30502941..e1456ea61 100644 --- a/src/Renci.SshNet/Security/Cryptography/RsaKey.cs +++ b/src/Renci.SshNet/Security/Cryptography/RsaKey.cs @@ -174,6 +174,7 @@ public RsaKey(byte[] privateKeyData) InverseQ = der.ReadInteger(); der.ThrowIfNotEmpty(); + RSA = RSA.Create(); RSA.ImportParameters(GetRSAParameters()); } diff --git a/test/Renci.SshNet.Tests/.editorconfig b/test/Renci.SshNet.Tests/.editorconfig index ae7f49219..f8a68f99c 100644 --- a/test/Renci.SshNet.Tests/.editorconfig +++ b/test/Renci.SshNet.Tests/.editorconfig @@ -10,6 +10,10 @@ dotnet_diagnostic.S108.severity = silent # https://rules.sonarsource.com/csharp/RSPEC-125/ dotnet_diagnostic.S125.severity = silent +# S1133: Deprecated code should be removed +# https://rules.sonarsource.com/csharp/RSPEC-1133/ +dotnet_diagnostic.S1133.severity = silent + # S1144: Unused private types or members should be removed # https://rules.sonarsource.com/csharp/RSPEC-1144/ dotnet_diagnostic.S1144.severity = silent