diff --git a/.gitignore b/.gitignore
index 7d6bdbf60..37c55e1b0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,4 @@ project.lock.json
# Build outputs
build/target/
+/.vs
diff --git a/src/Renci.SshNet/Abstractions/CryptoAbstraction.cs b/src/Renci.SshNet/Abstractions/CryptoAbstraction.cs
index ff9e50a52..1eb3ff78e 100644
--- a/src/Renci.SshNet/Abstractions/CryptoAbstraction.cs
+++ b/src/Renci.SshNet/Abstractions/CryptoAbstraction.cs
@@ -56,9 +56,12 @@ public static System.Security.Cryptography.RandomNumberGenerator CreateRandomNum
#endif // FEATURE_RNG_CREATE || FEATURE_RNG_CSP
#if FEATURE_HASH_MD5
- public static System.Security.Cryptography.MD5 CreateMD5()
+ public static System.Security.Cryptography.HashAlgorithm CreateMD5()
{
- return System.Security.Cryptography.MD5.Create();
+ if (SftpClient.UseFIPS)
+ return new System.Security.Cryptography.SHA1CryptoServiceProvider();
+ else
+ return System.Security.Cryptography.MD5.Create();
}
#else
public static global::SshNet.Security.Cryptography.MD5 CreateMD5()
@@ -70,11 +73,18 @@ public static System.Security.Cryptography.MD5 CreateMD5()
#if FEATURE_HASH_SHA1_CREATE || FEATURE_HASH_SHA1_MANAGED
public static System.Security.Cryptography.SHA1 CreateSHA1()
{
+ if (SftpClient.UseFIPS)
+ {
+ return new System.Security.Cryptography.SHA1CryptoServiceProvider();
+ }
+ else
+ {
#if FEATURE_HASH_SHA1_CREATE
- return System.Security.Cryptography.SHA1.Create();
+ return System.Security.Cryptography.SHA1.Create();
#elif FEATURE_HASH_SHA1_MANAGED
return new System.Security.Cryptography.SHA1Managed();
#endif
+ }
}
#else
public static global::SshNet.Security.Cryptography.SHA1 CreateSHA1()
@@ -86,11 +96,18 @@ public static System.Security.Cryptography.SHA1 CreateSHA1()
#if FEATURE_HASH_SHA256_CREATE || FEATURE_HASH_SHA256_MANAGED
public static System.Security.Cryptography.SHA256 CreateSHA256()
{
+ if (SftpClient.UseFIPS)
+ {
+ return new System.Security.Cryptography.SHA256CryptoServiceProvider();
+ }
+ else
+ {
#if FEATURE_HASH_SHA256_CREATE
- return System.Security.Cryptography.SHA256.Create();
+ return System.Security.Cryptography.SHA256.Create();
#elif FEATURE_HASH_SHA256_MANAGED
return new System.Security.Cryptography.SHA256Managed();
#endif
+ }
}
#else
public static global::SshNet.Security.Cryptography.SHA256 CreateSHA256()
@@ -102,11 +119,18 @@ public static System.Security.Cryptography.SHA256 CreateSHA256()
#if FEATURE_HASH_SHA384_CREATE || FEATURE_HASH_SHA384_MANAGED
public static System.Security.Cryptography.SHA384 CreateSHA384()
{
+ if (SftpClient.UseFIPS)
+ {
+ return new System.Security.Cryptography.SHA384CryptoServiceProvider();
+ }
+ else
+ {
#if FEATURE_HASH_SHA384_CREATE
- return System.Security.Cryptography.SHA384.Create();
+ return System.Security.Cryptography.SHA384.Create();
#elif FEATURE_HASH_SHA384_MANAGED
return new System.Security.Cryptography.SHA384Managed();
#endif
+ }
}
#else
public static global::SshNet.Security.Cryptography.SHA384 CreateSHA384()
@@ -118,11 +142,18 @@ public static System.Security.Cryptography.SHA384 CreateSHA384()
#if FEATURE_HASH_SHA512_CREATE || FEATURE_HASH_SHA512_MANAGED
public static System.Security.Cryptography.SHA512 CreateSHA512()
{
+ if (SftpClient.UseFIPS)
+ {
+ return new System.Security.Cryptography.SHA512CryptoServiceProvider();
+ }
+ else
+ {
#if FEATURE_HASH_SHA512_CREATE
- return System.Security.Cryptography.SHA512.Create();
+ return System.Security.Cryptography.SHA512.Create();
#elif FEATURE_HASH_SHA512_MANAGED
return new System.Security.Cryptography.SHA512Managed();
#endif
+ }
}
#else
public static global::SshNet.Security.Cryptography.SHA512 CreateSHA512()
diff --git a/src/Renci.SshNet/BaseClient.cs b/src/Renci.SshNet/BaseClient.cs
index 5b0e01c90..e4f188cd2 100644
--- a/src/Renci.SshNet/BaseClient.cs
+++ b/src/Renci.SshNet/BaseClient.cs
@@ -17,6 +17,9 @@ public abstract class BaseClient : IDisposable
///
private readonly bool _ownsConnectionInfo;
+
+
+ private static bool _useFips = false;
private readonly IServiceFactory _serviceFactory;
private readonly object _keepAliveLock = new object();
private TimeSpan _keepAliveInterval;
@@ -31,6 +34,11 @@ public abstract class BaseClient : IDisposable
///
internal ISession Session { get; private set; }
+ ///
+ /// Requests FIPS Compliance on the SFTP client
+ ///
+ public static bool UseFIPS { get { return _useFips; } set { _useFips = value; } }
+
///
/// Gets the factory for creating new services.
///
@@ -74,7 +82,6 @@ public bool IsConnected
get
{
CheckDisposed();
-
return IsSessionConnected();
}
}
diff --git a/src/Renci.SshNet/ConnectionInfo.cs b/src/Renci.SshNet/ConnectionInfo.cs
index af8e1ca5c..6620394a7 100644
--- a/src/Renci.SshNet/ConnectionInfo.cs
+++ b/src/Renci.SshNet/ConnectionInfo.cs
@@ -323,7 +323,9 @@ public ConnectionInfo(string host, int port, string username, ProxyTypes proxyTy
MaxSessions = 10;
Encoding = Encoding.UTF8;
- KeyExchangeAlgorithms = new Dictionary
+ if (SftpClient.UseFIPS)
+ {
+ KeyExchangeAlgorithms = new Dictionary
{
{"curve25519-sha256", typeof(KeyExchangeECCurve25519)},
{"curve25519-sha256@libssh.org", typeof(KeyExchangeECCurve25519)},
@@ -338,7 +340,68 @@ public ConnectionInfo(string host, int port, string username, ProxyTypes proxyTy
{"diffie-hellman-group1-sha1", typeof (KeyExchangeDiffieHellmanGroup1Sha1)},
};
- Encryptions = new Dictionary
+ Encryptions = new Dictionary
+ {
+ {"aes256-ctr", new CipherInfo(256, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))},
+ {"3des-cbc", new CipherInfo(192, (key, iv) => new TripleDesCipher(key, new CbcCipherMode(iv), null))},
+ {"aes128-cbc", new CipherInfo(128, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))},
+ {"aes192-cbc", new CipherInfo(192, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))},
+ {"aes256-cbc", new CipherInfo(256, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))},
+ {"blowfish-cbc", new CipherInfo(128, (key, iv) => new BlowfishCipher(key, new CbcCipherMode(iv), null))},
+ {"twofish-cbc", new CipherInfo(256, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))},
+ {"twofish192-cbc", new CipherInfo(192, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))},
+ {"twofish128-cbc", new CipherInfo(128, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))},
+ {"twofish256-cbc", new CipherInfo(256, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))},
+ {"arcfour", new CipherInfo(128, (key, iv) => new Arc4Cipher(key, false))},
+ {"arcfour128", new CipherInfo(128, (key, iv) => new Arc4Cipher(key, true))},
+ {"arcfour256", new CipherInfo(256, (key, iv) => new Arc4Cipher(key, true))},
+ {"cast128-cbc", new CipherInfo(128, (key, iv) => new CastCipher(key, new CbcCipherMode(iv), null))},
+ {"aes128-ctr", new CipherInfo(128, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))},
+ {"aes192-ctr", new CipherInfo(192, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))},
+ };
+
+ HmacAlgorithms = new Dictionary
+ {
+ {"hmac-sha1", new HashInfo(20*8, CryptoAbstraction.CreateHMACSHA1)},
+ {"hmac-sha1-96", new HashInfo(20*8, key => CryptoAbstraction.CreateHMACSHA1(key, 96))},
+ {"hmac-sha2-256", new HashInfo(32*8, CryptoAbstraction.CreateHMACSHA256)},
+ {"hmac-sha2-256-96", new HashInfo(32*8, key => CryptoAbstraction.CreateHMACSHA256(key, 96))},
+ {"hmac-sha2-512", new HashInfo(64 * 8, CryptoAbstraction.CreateHMACSHA512)},
+ {"hmac-sha2-512-96", new HashInfo(64 * 8, key => CryptoAbstraction.CreateHMACSHA512(key, 96))},
+ {"hmac-ripemd160", new HashInfo(160, CryptoAbstraction.CreateHMACRIPEMD160)},
+ {"hmac-ripemd160@openssh.com", new HashInfo(160, CryptoAbstraction.CreateHMACRIPEMD160)},
+ };
+
+ HostKeyAlgorithms = new Dictionary>
+ {
+ {"ssh-ed25519", data => new KeyHostAlgorithm("ssh-ed25519", new ED25519Key(), data)},
+#if FEATURE_ECDSA
+ {"ecdsa-sha2-nistp256", data => new KeyHostAlgorithm("ecdsa-sha2-nistp256", new EcdsaKey(), data)},
+ {"ecdsa-sha2-nistp384", data => new KeyHostAlgorithm("ecdsa-sha2-nistp384", new EcdsaKey(), data)},
+ {"ecdsa-sha2-nistp521", data => new KeyHostAlgorithm("ecdsa-sha2-nistp521", new EcdsaKey(), data)},
+#endif
+ {"ssh-rsa", data => new KeyHostAlgorithm("ssh-rsa", new RsaKey(), data)},
+ {"ssh-dss", data => new KeyHostAlgorithm("ssh-dss", new DsaKey(), data)},
+ };
+ }
+ else
+ {
+ KeyExchangeAlgorithms = new Dictionary
+ {
+ {"curve25519-sha256", typeof(KeyExchangeECCurve25519)},
+ {"curve25519-sha256@libssh.org", typeof(KeyExchangeECCurve25519)},
+ {"ecdh-sha2-nistp256", typeof(KeyExchangeECDH256)},
+ {"ecdh-sha2-nistp384", typeof(KeyExchangeECDH384)},
+ {"ecdh-sha2-nistp521", typeof(KeyExchangeECDH521)},
+ {"diffie-hellman-group-exchange-sha256", typeof (KeyExchangeDiffieHellmanGroupExchangeSha256)},
+ {"diffie-hellman-group-exchange-sha1", typeof (KeyExchangeDiffieHellmanGroupExchangeSha1)},
+ {"diffie-hellman-group16-sha512", typeof(KeyExchangeDiffieHellmanGroup16Sha512)},
+ {"diffie-hellman-group14-sha256", typeof (KeyExchangeDiffieHellmanGroup14Sha256)},
+ {"diffie-hellman-group14-sha1", typeof (KeyExchangeDiffieHellmanGroup14Sha1)},
+ {"diffie-hellman-group1-sha1", typeof (KeyExchangeDiffieHellmanGroup1Sha1)},
+ };
+
+ Encryptions = new Dictionary
{
{"aes256-ctr", new CipherInfo(256, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))},
{"3des-cbc", new CipherInfo(192, (key, iv) => new TripleDesCipher(key, new CbcCipherMode(iv), null))},
@@ -363,7 +426,7 @@ public ConnectionInfo(string host, int port, string username, ProxyTypes proxyTy
{"aes192-ctr", new CipherInfo(192, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))},
};
- HmacAlgorithms = new Dictionary
+ HmacAlgorithms = new Dictionary
{
{"hmac-md5", new HashInfo(16*8, CryptoAbstraction.CreateHMACMD5)},
{"hmac-md5-96", new HashInfo(16*8, key => CryptoAbstraction.CreateHMACMD5(key, 96))},
@@ -379,7 +442,7 @@ public ConnectionInfo(string host, int port, string username, ProxyTypes proxyTy
//{"none", typeof(...)},
};
- HostKeyAlgorithms = new Dictionary>
+ HostKeyAlgorithms = new Dictionary>
{
{"ssh-ed25519", data => new KeyHostAlgorithm("ssh-ed25519", new ED25519Key(), data)},
#if FEATURE_ECDSA
@@ -396,6 +459,8 @@ public ConnectionInfo(string host, int port, string username, ProxyTypes proxyTy
//{"pgp-sign-rsa", () => { ... },
//{"pgp-sign-dss", () => { ... },
};
+ }
+
CompressionAlgorithms = new Dictionary
{
diff --git a/src/Renci.SshNet/Renci.SshNet.csproj b/src/Renci.SshNet/Renci.SshNet.csproj
index 124ce9d4b..8ccd05528 100644
--- a/src/Renci.SshNet/Renci.SshNet.csproj
+++ b/src/Renci.SshNet/Renci.SshNet.csproj
@@ -7,7 +7,7 @@
../Renci.SshNet.snk
5
true
- net35;net40;netstandard1.3;netstandard2.0
+ net35;net40;netstandard2.0