Browse Source

Introduce abstraction for generating a strong random sequence, as UWP/WinRT does not come with RandomNumberGenerator.

On UWP/WinRT, we'll use CryptographicBuffer.GenerateRandom(uint).

We'll probably revisit this once CoreFX is more stable (after RC2).
drieseng 9 years ago
parent
commit
2310845728

+ 1 - 3
src/Renci.SshNet/Common/BigInteger.cs

@@ -67,8 +67,6 @@ namespace Renci.SshNet.Common
     /// </summary>
     /// </summary>
     public struct BigInteger : IComparable, IFormattable, IComparable<BigInteger>, IEquatable<BigInteger>
     public struct BigInteger : IComparable, IFormattable, IComparable<BigInteger>, IEquatable<BigInteger>
     {
     {
-        private static readonly RandomNumberGenerator _randomizer = HashAlgorithmFactory.CreateRandomNumberGenerator();
-
         private const ulong _BASE = 0x100000000;
         private const ulong _BASE = 0x100000000;
         private const Int32 _DECIMALSIGNMASK = unchecked((Int32)0x80000000);
         private const Int32 _DECIMALSIGNMASK = unchecked((Int32)0x80000000);
         private const int _BIAS = 1075;
         private const int _BIAS = 1075;
@@ -1968,7 +1966,7 @@ namespace Renci.SshNet.Common
         public static BigInteger Random(int bitLength)
         public static BigInteger Random(int bitLength)
         {
         {
             var bytesArray = new byte[bitLength / 8 + (((bitLength % 8) > 0) ? 1 : 0)];
             var bytesArray = new byte[bitLength / 8 + (((bitLength % 8) > 0) ? 1 : 0)];
-            _randomizer.GetBytes(bytesArray);
+            HashAlgorithmFactory.GenerateRandom(bytesArray);
             bytesArray[bytesArray.Length - 1] = (byte)(bytesArray[bytesArray.Length - 1] & 0x7F);   //  Ensure not a negative value
             bytesArray[bytesArray.Length - 1] = (byte)(bytesArray[bytesArray.Length - 1] & 0x7F);   //  Ensure not a negative value
 #if TUNING
 #if TUNING
             return new BigInteger(bytesArray);
             return new BigInteger(bytesArray);

+ 2 - 5
src/Renci.SshNet/Messages/Message.cs

@@ -1,6 +1,5 @@
 using System.IO;
 using System.IO;
 using System.Linq;
 using System.Linq;
-using System.Security.Cryptography;
 using Renci.SshNet.Common;
 using Renci.SshNet.Common;
 using System.Globalization;
 using System.Globalization;
 using Renci.SshNet.Abstractions;
 using Renci.SshNet.Abstractions;
@@ -14,8 +13,6 @@ namespace Renci.SshNet.Messages
     /// </summary>
     /// </summary>
     public abstract class Message : SshData
     public abstract class Message : SshData
     {
     {
-        private static readonly RandomNumberGenerator Randomizer = HashAlgorithmFactory.CreateRandomNumberGenerator();
-
         /// <summary>
         /// <summary>
         /// Gets the index that represents zero in current data type.
         /// Gets the index that represents zero in current data type.
         /// </summary>
         /// </summary>
@@ -104,7 +101,7 @@ namespace Renci.SshNet.Messages
 
 
                 // add padding bytes
                 // add padding bytes
                 var paddingBytes = new byte[paddingLength];
                 var paddingBytes = new byte[paddingLength];
-                Randomizer.GetBytes(paddingBytes);
+                HashAlgorithmFactory.GenerateRandom(paddingBytes);
                 sshDataStream.Write(paddingBytes, 0, paddingLength);
                 sshDataStream.Write(paddingBytes, 0, paddingLength);
 
 
                 var packetDataLength = GetPacketDataLength(messageLength, paddingLength);
                 var packetDataLength = GetPacketDataLength(messageLength, paddingLength);
@@ -144,7 +141,7 @@ namespace Renci.SshNet.Messages
 
 
                 // add padding bytes
                 // add padding bytes
                 var paddingBytes = new byte[paddingLength];
                 var paddingBytes = new byte[paddingLength];
-                Randomizer.GetBytes(paddingBytes);
+                HashAlgorithmFactory.GenerateRandom(paddingBytes);
                 sshDataStream.Write(paddingBytes, 0, paddingLength);
                 sshDataStream.Write(paddingBytes, 0, paddingLength);
             }
             }
 
 

+ 1 - 4
src/Renci.SshNet/Messages/Transport/KeyExchangeInitMessage.cs

@@ -1,5 +1,4 @@
 using System;
 using System;
-using System.Security.Cryptography;
 using Renci.SshNet.Security.Cryptography;
 using Renci.SshNet.Security.Cryptography;
 
 
 namespace Renci.SshNet.Messages.Transport
 namespace Renci.SshNet.Messages.Transport
@@ -10,15 +9,13 @@ namespace Renci.SshNet.Messages.Transport
     [Message("SSH_MSG_KEXINIT", 20)]
     [Message("SSH_MSG_KEXINIT", 20)]
     public class KeyExchangeInitMessage : Message, IKeyExchangedAllowed
     public class KeyExchangeInitMessage : Message, IKeyExchangedAllowed
     {
     {
-        private static readonly RandomNumberGenerator Randomizer = HashAlgorithmFactory.CreateRandomNumberGenerator();
-
         /// <summary>
         /// <summary>
         /// Initializes a new instance of the <see cref="KeyExchangeInitMessage"/> class.
         /// Initializes a new instance of the <see cref="KeyExchangeInitMessage"/> class.
         /// </summary>
         /// </summary>
         public KeyExchangeInitMessage()
         public KeyExchangeInitMessage()
         {
         {
             var cookie = new byte[16];
             var cookie = new byte[16];
-            Randomizer.GetBytes(cookie);
+            HashAlgorithmFactory.GenerateRandom(cookie);
             Cookie = cookie;
             Cookie = cookie;
         }
         }
 
 

+ 61 - 36
src/Renci.SshNet/Security/Cryptography/HashAlgorithmFactory.cs

@@ -1,9 +1,33 @@
-using System.Security.Cryptography;
+using System;
+using System.Security.Cryptography;
+using Renci.SshNet.Messages.Authentication;
 
 
 namespace Renci.SshNet.Security.Cryptography
 namespace Renci.SshNet.Security.Cryptography
 {
 {
     internal static class HashAlgorithmFactory
     internal static class HashAlgorithmFactory
     {
     {
+#if FEATURE_RNG_CREATE || FEATURE_RNG_CSP
+        private static readonly RandomNumberGenerator _randomizer = HashAlgorithmFactory.CreateRandomNumberGenerator();
+#endif
+
+        /// <summary>
+        /// Fills an array of bytes with a cryptographically strong random sequence of values.
+        /// </summary>
+        /// <param name="data">The array to fill with cryptographically strong random bytes.</param>
+        /// <remarks>
+        /// The length of the byte array determines how many random bytes are produced.
+        /// </remarks>
+        public static void GenerateRandom(byte[] data)
+        {
+#if FEATURE_RNG_CREATE || FEATURE_RNG_CSP
+            _randomizer.GetBytes(data);
+#else
+            var buffer = Windows.Security.Cryptography.CryptographicBuffer.GenerateRandom((uint) data.Length);
+            Windows.Security.Cryptography.CryptographicBuffer.CopyToByteArray(buffer, out data);
+#endif
+        }
+
+#if FEATURE_RNG_CREATE || FEATURE_RNG_CSP
         public static RandomNumberGenerator CreateRandomNumberGenerator()
         public static RandomNumberGenerator CreateRandomNumberGenerator()
         {
         {
 #if FEATURE_RNG_CREATE
 #if FEATURE_RNG_CREATE
@@ -11,9 +35,10 @@ namespace Renci.SshNet.Security.Cryptography
 #elif FEATURE_RNG_CSP
 #elif FEATURE_RNG_CSP
             return new RNGCryptoServiceProvider();
             return new RNGCryptoServiceProvider();
 #else
 #else
-            #error Creation of RandomNumberGenerator is not implemented.
+#error Creation of RandomNumberGenerator is not implemented.
 #endif
 #endif
         }
         }
+#endif // FEATURE_RNG_CREATE || FEATURE_RNG_CSP
 
 
 #if FEATURE_HASH_MD5
 #if FEATURE_HASH_MD5
         public static System.Security.Cryptography.MD5 CreateMD5()
         public static System.Security.Cryptography.MD5 CreateMD5()
@@ -21,9 +46,9 @@ namespace Renci.SshNet.Security.Cryptography
             return System.Security.Cryptography.MD5.Create();
             return System.Security.Cryptography.MD5.Create();
         }
         }
 #else
 #else
-        public static Renci.Security.Cryptography.MD5 CreateMD5()
+        public static global::SshNet.Security.Cryptography.MD5 CreateMD5()
         {
         {
-            return new Renci.Security.Cryptography.MD5();
+            return new global::SshNet.Security.Cryptography.MD5();
         }
         }
 #endif // FEATURE_HASH_MD5
 #endif // FEATURE_HASH_MD5
 
 
@@ -33,9 +58,9 @@ namespace Renci.SshNet.Security.Cryptography
             return new System.Security.Cryptography.SHA1Managed();
             return new System.Security.Cryptography.SHA1Managed();
         }
         }
 #else
 #else
-        public static Renci.Security.Cryptography.SHA1 CreateSHA1()
+        public static global::SshNet.Security.Cryptography.SHA1 CreateSHA1()
         {
         {
-            return new Renci.Security.Cryptography.SHA1();
+            return new global::SshNet.Security.Cryptography.SHA1();
         }
         }
 #endif
 #endif
 
 
@@ -45,9 +70,9 @@ namespace Renci.SshNet.Security.Cryptography
             return new System.Security.Cryptography.SHA256Managed();
             return new System.Security.Cryptography.SHA256Managed();
         }
         }
 #else
 #else
-        public static Renci.Security.Cryptography.SHA256 CreateSHA256()
+        public static global::SshNet.Security.Cryptography.SHA256 CreateSHA256()
         {
         {
-            return new Renci.Security.Cryptography.SHA256();
+            return new global::SshNet.Security.Cryptography.SHA256();
         }
         }
 #endif
 #endif
 
 
@@ -57,9 +82,9 @@ namespace Renci.SshNet.Security.Cryptography
             return new System.Security.Cryptography.SHA384Managed();
             return new System.Security.Cryptography.SHA384Managed();
         }
         }
 #else
 #else
-        public static Renci.Security.Cryptography.SHA384 CreateSHA384()
+        public static global::SshNet.Security.Cryptography.SHA384 CreateSHA384()
         {
         {
-            return new Renci.Security.Cryptography.SHA384();
+            return new global::SshNet.Security.Cryptography.SHA384();
         }
         }
 #endif
 #endif
 
 
@@ -69,9 +94,9 @@ namespace Renci.SshNet.Security.Cryptography
             return new System.Security.Cryptography.SHA512Managed();
             return new System.Security.Cryptography.SHA512Managed();
         }
         }
 #else
 #else
-        public static Renci.Security.Cryptography.SHA512 CreateSHA512()
+        public static global::SshNet.Security.Cryptography.SHA512 CreateSHA512()
         {
         {
-            return new Renci.Security.Cryptography.SHA512();
+            return new global::SshNet.Security.Cryptography.SHA512();
         }
         }
 #endif
 #endif
 
 
@@ -81,9 +106,9 @@ namespace Renci.SshNet.Security.Cryptography
             return new System.Security.Cryptography.RIPEMD160Managed();
             return new System.Security.Cryptography.RIPEMD160Managed();
         }
         }
 #else
 #else
-        public static Renci.Security.Cryptography.RIPEMD160 CreateRIPEMD160()
+        public static global::SshNet.Security.Cryptography.RIPEMD160 CreateRIPEMD160()
         {
         {
-            return new Renci.Security.Cryptography.RIPEMD160();
+            return new global::SshNet.Security.Cryptography.RIPEMD160();
         }
         }
 #endif // FEATURE_HASH_RIPEMD160
 #endif // FEATURE_HASH_RIPEMD160
 
 
@@ -98,14 +123,14 @@ namespace Renci.SshNet.Security.Cryptography
             return new HMACMD5(key, hashSize);
             return new HMACMD5(key, hashSize);
         }
         }
 #else
 #else
-        public static Renci.Security.Cryptography.HMACMD5 CreateHMACMD5(byte[] key)
+        public static global::SshNet.Security.Cryptography.HMACMD5 CreateHMACMD5(byte[] key)
         {
         {
-            return new Renci.Security.Cryptography.HMACMD5(key);
+            return new global::SshNet.Security.Cryptography.HMACMD5(key);
         }
         }
 
 
-        public static Renci.Security.Cryptography.HMACMD5 CreateHMACMD5(byte[] key, int hashSize)
+        public static global::SshNet.Security.Cryptography.HMACMD5 CreateHMACMD5(byte[] key, int hashSize)
         {
         {
-            return new Renci.Security.Cryptography.HMACMD5(key, hashSize);
+            return new global::SshNet.Security.Cryptography.HMACMD5(key, hashSize);
         }
         }
 #endif // FEATURE_HMAC_MD5
 #endif // FEATURE_HMAC_MD5
 
 
@@ -120,14 +145,14 @@ namespace Renci.SshNet.Security.Cryptography
             return new HMACSHA1(key, hashSize);
             return new HMACSHA1(key, hashSize);
         }
         }
 #else
 #else
-        public static Renci.Security.Cryptography.HMACSHA1 CreateHMACSHA1(byte[] key)
+        public static global::SshNet.Security.Cryptography.HMACSHA1 CreateHMACSHA1(byte[] key)
         {
         {
-            return new Renci.Security.Cryptography.HMACSHA1(key);
+            return new global::SshNet.Security.Cryptography.HMACSHA1(key);
         }
         }
 
 
-        public static Renci.Security.Cryptography.HMACSHA1 CreateHMACSHA1(byte[] key, int hashSize)
+        public static global::SshNet.Security.Cryptography.HMACSHA1 CreateHMACSHA1(byte[] key, int hashSize)
         {
         {
-            return new Renci.Security.Cryptography.HMACSHA1(key, hashSize);
+            return new global::SshNet.Security.Cryptography.HMACSHA1(key, hashSize);
         }
         }
 #endif // FEATURE_HMAC_SHA1
 #endif // FEATURE_HMAC_SHA1
 
 
@@ -142,14 +167,14 @@ namespace Renci.SshNet.Security.Cryptography
             return new HMACSHA256(key, hashSize);
             return new HMACSHA256(key, hashSize);
         }
         }
 #else
 #else
-        public static Renci.Security.Cryptography.HMACSHA256 CreateHMACSHA256(byte[] key)
+        public static global::SshNet.Security.Cryptography.HMACSHA256 CreateHMACSHA256(byte[] key)
         {
         {
-            return new Renci.Security.Cryptography.HMACSHA256(key);
+            return new global::SshNet.Security.Cryptography.HMACSHA256(key);
         }
         }
 
 
-        public static Renci.Security.Cryptography.HMACSHA256 CreateHMACSHA256(byte[] key, int hashSize)
+        public static global::SshNet.Security.Cryptography.HMACSHA256 CreateHMACSHA256(byte[] key, int hashSize)
         {
         {
-            return new Renci.Security.Cryptography.HMACSHA256(key, hashSize);
+            return new global::SshNet.Security.Cryptography.HMACSHA256(key, hashSize);
         }
         }
 #endif // FEATURE_HMAC_SHA256
 #endif // FEATURE_HMAC_SHA256
 
 
@@ -164,14 +189,14 @@ namespace Renci.SshNet.Security.Cryptography
             return new HMACSHA384(key, hashSize);
             return new HMACSHA384(key, hashSize);
         }
         }
 #else
 #else
-        public static Renci.Security.Cryptography.HMACSHA384 CreateHMACSHA384(byte[] key)
+        public static global::SshNet.Security.Cryptography.HMACSHA384 CreateHMACSHA384(byte[] key)
         {
         {
-            return new Renci.Security.Cryptography.HMACSHA384(key);
+            return new global::SshNet.Security.Cryptography.HMACSHA384(key);
         }
         }
 
 
-        public static Renci.Security.Cryptography.HMACSHA384 CreateHMACSHA384(byte[] key, int hashSize)
+        public static global::SshNet.Security.Cryptography.HMACSHA384 CreateHMACSHA384(byte[] key, int hashSize)
         {
         {
-            return new Renci.Security.Cryptography.HMACSHA384(key, hashSize);
+            return new global::SshNet.Security.Cryptography.HMACSHA384(key, hashSize);
         }
         }
 #endif // FEATURE_HMAC_SHA384
 #endif // FEATURE_HMAC_SHA384
 
 
@@ -186,14 +211,14 @@ namespace Renci.SshNet.Security.Cryptography
             return new HMACSHA512(key, hashSize);
             return new HMACSHA512(key, hashSize);
         }
         }
 #else
 #else
-        public static Renci.Security.Cryptography.HMACSHA512 CreateHMACSHA512(byte[] key)
+        public static global::SshNet.Security.Cryptography.HMACSHA512 CreateHMACSHA512(byte[] key)
         {
         {
-            return new Renci.Security.Cryptography.HMACSHA512(key);
+            return new global::SshNet.Security.Cryptography.HMACSHA512(key);
         }
         }
 
 
-        public static Renci.Security.Cryptography.HMACSHA512 CreateHMACSHA512(byte[] key, int hashSize)
+        public static global::SshNet.Security.Cryptography.HMACSHA512 CreateHMACSHA512(byte[] key, int hashSize)
         {
         {
-            return new Renci.Security.Cryptography.HMACSHA512(key, hashSize);
+            return new global::SshNet.Security.Cryptography.HMACSHA512(key, hashSize);
         }
         }
 #endif // FEATURE_HMAC_SHA512
 #endif // FEATURE_HMAC_SHA512
 
 
@@ -203,9 +228,9 @@ namespace Renci.SshNet.Security.Cryptography
             return new System.Security.Cryptography.HMACRIPEMD160(key);
             return new System.Security.Cryptography.HMACRIPEMD160(key);
         }
         }
 #else
 #else
-        public static Renci.Security.Cryptography.HMACRIPEMD160 CreateHMACRIPEMD160(byte[] key)
+        public static global::SshNet.Security.Cryptography.HMACRIPEMD160 CreateHMACRIPEMD160(byte[] key)
         {
         {
-            return new Renci.Security.Cryptography.HMACRIPEMD160(key);
+            return new global::SshNet.Security.Cryptography.HMACRIPEMD160(key);
         }
         }
 #endif // FEATURE_HMAC_RIPEMD160
 #endif // FEATURE_HMAC_RIPEMD160
     }
     }