Forráskód Böngészése

remove unused bcrypt code (#1626)

mus65 6 hónapja
szülő
commit
ad174829cc
1 módosított fájl, 5 hozzáadás és 407 törlés
  1. 5 407
      src/Renci.SshNet/Security/Cryptography/Bcrypt.cs

+ 5 - 407
src/Renci.SshNet/Security/Cryptography/Bcrypt.cs

@@ -22,53 +22,12 @@ using System.Text;
 
 namespace Renci.SshNet.Security.Cryptography
 {
-    /// <summary>BCrypt implementation.</summary>
-    /// <remarks>
-    ///  <para>
-    ///        BCrypt implements OpenBSD-style Blowfish password hashing using the scheme described in
-    ///        <a href="http://www.usenix.org/event/usenix99/provos/provos_html/index.html">"A Future-
-    ///        Adaptable Password Scheme"</a> by Niels Provos and David Mazieres.
-    ///  </para>
-    ///  <para>
-    ///        This password hashing system tries to thwart off-line password cracking using a
-    ///        computationally-intensive hashing algorithm, based on Bruce Schneier's Blowfish cipher.
-    ///        The work factor of the algorithm is parameterised, so it can be increased as computers
-    ///        get faster.
-    ///  </para>
-    ///  <para>
-    ///        Usage is really simple. To hash a password for the first time, call the <see
-    ///        cref="HashPassword(string)"/> method with a random salt, like this:
-    ///  </para>
-    ///  <code>string pw_hash = BCrypt.HashPassword(plain_password);</code>
-    ///  <para>
-    ///        To check whether a plaintext password matches one that has been hashed previously,
-    ///        use the <see cref="Verify"/> method:
-    ///  </para>
-    ///  <code>
-    ///     if (BCrypt.Verify(candidate_password, stored_hash))
-    ///         Console.WriteLine("It matches");
-    ///     else
-    ///         Console.WriteLine("It does not match");
-    ///   </code>
-    ///   <para>
-    ///         The <see cref="GenerateSalt()"/> method takes an optional parameter (workFactor) that
-    ///         determines the computational complexity of the hashing:
-    ///   </para>
-    ///   <code>
-    ///     string strong_salt = BCrypt.GenerateSalt(10);
-    ///     string stronger_salt = BCrypt.GenerateSalt(12);
-    ///   </code>
-    ///   <para>
-    ///         The amount of work increases exponentially (2^workFactor), so each increment is twice
-    ///         as much work. The default workFactor is 10, and the valid range is 4 to 31.
-    ///   </para>
-    /// </remarks>
+    /// <summary>
+    /// BCrypt Pbkdf implementation.
+    /// This was originally based on https://github.com/hierynomus/sshj/blob/master/src/main/java/com/hierynomus/sshj/userauth/keyprovider/bcrypt/BCrypt.java .
+    /// </summary>
     internal sealed class BCrypt
     {
-        // BCrypt parameters
-        private const int GENSALT_DEFAULT_LOG2_ROUNDS = 10;
-        private const int BCRYPT_SALT_LEN = 16;
-
         // Blowfish parameters
         private const int BLOWFISH_NUM_ROUNDS = 16;
 
@@ -346,299 +305,10 @@ namespace Renci.SshNet.Security.Cryptography
             0x66697368, 0x53776174, 0x44796e61, 0x6d697465,
         };
 
-        // bcrypt IV: "OrpheanBeholderScryDoubt"
-        private static readonly uint[] _BfCryptCiphertext = {
-            0x4f727068, 0x65616e42, 0x65686f6c,
-            0x64657253, 0x63727944, 0x6f756274
-        };
-
-        // Table for Base64 encoding
-        private static readonly char[] _Base64Code = {
-            '.', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
-            'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
-            'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
-            'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
-            'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5',
-            '6', '7', '8', '9'
-        };
-
-        // Table for Base64 decoding
-        private static readonly int[] _Index64 = {
-            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-            -1, -1, -1, -1, -1, -1, 0, 1, 54, 55,
-            56, 57, 58, 59, 60, 61, 62, 63, -1, -1,
-            -1, -1, -1, -1, -1, 2, 3, 4, 5, 6,
-            7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
-            17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
-            -1, -1, -1, -1, -1, -1, 28, 29, 30,
-            31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
-            41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
-            51, 52, 53, -1, -1, -1, -1, -1
-        };
-
         // Expanded Blowfish key
         private uint[] _P;
         private uint[] _S;
 
-        /// <summary>
-        ///  Hash a string using the OpenBSD bcrypt scheme and a salt generated by <see
-        ///  cref="BCrypt.GenerateSalt()"/>.
-        /// </summary>
-        /// <remarks>Just an alias for HashPassword.</remarks>
-        /// <param name="source">The string to hash.</param>
-        /// <returns>The hashed string.</returns>
-        public static string HashString(string source)
-        {
-            return HashPassword(source);
-        }
-
-        /// <summary>
-        ///  Hash a string using the OpenBSD bcrypt scheme and a salt generated by <see
-        ///  cref="BCrypt.GenerateSalt()"/>.
-        /// </summary>
-        /// <remarks>Just an alias for HashPassword.</remarks>
-        /// <param name="source">  The string to hash.</param>
-        /// <param name="workFactor">The log2 of the number of rounds of hashing to apply - the work
-        ///                          factor therefore increases as 2^workFactor.</param>
-        /// <returns>The hashed string.</returns>
-        public static string HashString(string source, int workFactor)
-        {
-            return HashPassword(source, GenerateSalt(workFactor));
-        }
-
-        /// <summary>
-        ///  Hash a password using the OpenBSD bcrypt scheme and a salt generated by <see
-        ///  cref="BCrypt.GenerateSalt()"/>.
-        /// </summary>
-        /// <param name="input">The password to hash.</param>
-        /// <returns>The hashed password.</returns>
-        public static string HashPassword(string input)
-        {
-            return HashPassword(input, GenerateSalt());
-        }
-
-        /// <summary>
-        ///  Hash a password using the OpenBSD bcrypt scheme and a salt generated by <see
-        ///  cref="BCrypt.GenerateSalt(int)"/> using the given <paramref name="workFactor"/>.
-        /// </summary>
-        /// <param name="input">     The password to hash.</param>
-        /// <param name="workFactor">The log2 of the number of rounds of hashing to apply - the work
-        ///                          factor therefore increases as 2^workFactor.</param>
-        /// <returns>The hashed password.</returns>
-        public static string HashPassword(string input, int workFactor)
-        {
-            return HashPassword(input, GenerateSalt(workFactor));
-        }
-
-        /// <summary>Hash a password using the OpenBSD bcrypt scheme.</summary>
-        /// <exception cref="ArgumentException">Thrown when one or more arguments have unsupported or
-        ///                                     illegal values.</exception>
-        /// <param name="input">The password to hash.</param>
-        /// <param name="salt">    the salt to hash with (perhaps generated using BCrypt.gensalt).</param>
-        /// <returns>The hashed password</returns>
-        public static string HashPassword(string input, string salt)
-        {
-            if (input == null)
-                throw new ArgumentNullException("input");
-
-            if (string.IsNullOrEmpty(salt))
-                throw new ArgumentException("Invalid salt", "salt");
-
-            // Determinthe starting offset and validate the salt
-            int startingOffset;
-            char minor = (char)0;
-            if (salt[0] != '$' || salt[1] != '2')
-                throw new SaltParseException("Invalid salt version");
-            if (salt[2] == '$')
-                startingOffset = 3;
-            else
-            {
-                minor = salt[2];
-                if (minor != 'a' || salt[3] != '$')
-                    throw new SaltParseException("Invalid salt revision");
-                startingOffset = 4;
-            }
-
-            // Extract number of rounds
-            if (salt[startingOffset + 2] > '$')
-                throw new SaltParseException("Missing salt rounds");
-
-            // Extract details from salt
-            int logRounds = Convert.ToInt32(salt.Substring(startingOffset, 2));
-            string extractedSalt = salt.Substring(startingOffset + 3, 22);
-
-            byte[] inputBytes = Encoding.UTF8.GetBytes((input + (minor >= 'a' ? "\0" : "")));
-            byte[] saltBytes = DecodeBase64(extractedSalt, BCRYPT_SALT_LEN);
-
-            BCrypt bCrypt = new BCrypt();
-            byte[] hashed = bCrypt.CryptRaw(inputBytes, saltBytes, logRounds);
-
-            // Generate result string
-            StringBuilder result = new StringBuilder();
-            result.Append("$2");
-            if (minor >= 'a')
-                result.Append(minor);
-            result.AppendFormat("${0:00}$", logRounds);
-            result.Append(EncodeBase64(saltBytes, saltBytes.Length));
-            result.Append(EncodeBase64(hashed, (_BfCryptCiphertext.Length * 4) - 1));
-            return result.ToString();
-        }
-
-        /// <summary>
-        ///  Generate a salt for use with the <see cref="BCrypt.HashPassword(string,string)"/> method.
-        /// </summary>
-        /// <param name="workFactor">The log2 of the number of rounds of hashing to apply - the work
-        ///                          factor therefore increases as 2**workFactor.</param>
-        /// <returns>A base64 encoded salt value.</returns>
-        public static string GenerateSalt(int workFactor)
-        {
-            if (workFactor < 4 || workFactor > 31)
-                throw new ArgumentOutOfRangeException("workFactor", "The work factor must be between 4 and 31 (inclusive)");
-
-            byte[] rnd = new byte[BCRYPT_SALT_LEN];
-
-            RandomNumberGenerator rng = RandomNumberGenerator.Create();
-
-            rng.GetBytes(rnd);
-
-            StringBuilder rs = new StringBuilder();
-            rs.AppendFormat("$2a${0:00}$", workFactor);
-            rs.Append(EncodeBase64(rnd, rnd.Length));
-            return rs.ToString();
-        }
-
-        /// <summary>
-        ///  Generate a salt for use with the <see cref="BCrypt.HashPassword(string,string)"/> method
-        ///  selecting a reasonable default for the number of hashing rounds to apply.
-        /// </summary>
-        /// <returns>A base64 encoded salt value.</returns>
-        public static string GenerateSalt()
-        {
-            return GenerateSalt(GENSALT_DEFAULT_LOG2_ROUNDS);
-        }
-
-        /// <summary>
-        ///  Verifies that the hash of the given <paramref name="text"/> matches the provided
-        ///  <paramref name="hash"/>
-        /// </summary>
-        /// <param name="text">The text to verify.</param>
-        /// <param name="hash"> The previously-hashed password.</param>
-        /// <returns>true if the passwords match, false otherwise.</returns>
-        public static bool Verify(string text, string hash)
-        {
-            return hash == HashPassword(text, hash);
-        }
-
-        /// <summary>
-        ///  Encode a byte array using bcrypt's slightly-modified base64 encoding scheme. Note that this
-        ///  is *not* compatible with the standard MIME-base64 encoding.
-        /// </summary>
-        /// <exception cref="ArgumentException">Thrown when one or more arguments have unsupported or
-        ///                                     illegal values.</exception>
-        /// <param name="byteArray">The byte array to encode.</param>
-        /// <param name="length">   The number of bytes to encode.</param>
-        /// <returns>Base64-encoded string.</returns>
-        private static string EncodeBase64(byte[] byteArray, int length)
-        {
-            if (length <= 0 || length > byteArray.Length)
-                throw new ArgumentException("Invalid length", "length");
-
-            int off = 0;
-            StringBuilder rs = new StringBuilder();
-            while (off < length)
-            {
-                int c1 = byteArray[off++] & 0xff;
-                rs.Append(_Base64Code[(c1 >> 2) & 0x3f]);
-                c1 = (c1 & 0x03) << 4;
-                if (off >= length)
-                {
-                    rs.Append(_Base64Code[c1 & 0x3f]);
-                    break;
-                }
-                int c2 = byteArray[off++] & 0xff;
-                c1 |= (c2 >> 4) & 0x0f;
-                rs.Append(_Base64Code[c1 & 0x3f]);
-                c1 = (c2 & 0x0f) << 2;
-                if (off >= length)
-                {
-                    rs.Append(_Base64Code[c1 & 0x3f]);
-                    break;
-                }
-                c2 = byteArray[off++] & 0xff;
-                c1 |= (c2 >> 6) & 0x03;
-                rs.Append(_Base64Code[c1 & 0x3f]);
-                rs.Append(_Base64Code[c2 & 0x3f]);
-            }
-            return rs.ToString();
-        }
-
-        /// <summary>
-        ///  Decode a string encoded using bcrypt's base64 scheme to a byte array. Note that this is *not*
-        ///  compatible with the standard MIME-base64 encoding.
-        /// </summary>
-        /// <exception cref="ArgumentException">Thrown when one or more arguments have unsupported or
-        ///                                     illegal values.</exception>
-        /// <param name="encodedstring">The string to decode.</param>
-        /// <param name="maximumBytes"> The maximum bytes to decode.</param>
-        /// <returns>The decoded byte array.</returns>
-        private static byte[] DecodeBase64(string encodedstring, int maximumBytes)
-        {
-            int position = 0,
-                sourceLength = encodedstring.Length,
-                outputLength = 0;
-
-            if (maximumBytes <= 0)
-                throw new ArgumentException("Invalid maximum bytes value", "maximumBytes");
-
-            // TODO: update to use a List<byte> - it's only ever 16 bytes, so it's not a big deal
-            StringBuilder rs = new StringBuilder();
-            while (position < sourceLength - 1 && outputLength < maximumBytes)
-            {
-                int c1 = Char64(encodedstring[position++]);
-                int c2 = Char64(encodedstring[position++]);
-                if (c1 == -1 || c2 == -1)
-                    break;
-
-                rs.Append((char)((c1 << 2) | ((c2 & 0x30) >> 4)));
-                if (++outputLength >= maximumBytes || position >= sourceLength)
-                    break;
-
-                int c3 = Char64(encodedstring[position++]);
-                if (c3 == -1)
-                    break;
-
-                rs.Append((char)(((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2)));
-                if (++outputLength >= maximumBytes || position >= sourceLength)
-                    break;
-
-                int c4 = Char64(encodedstring[position++]);
-                rs.Append((char)(((c3 & 0x03) << 6) | c4));
-
-                ++outputLength;
-            }
-
-            byte[] ret = new byte[outputLength];
-            for (position = 0; position < outputLength; position++)
-                ret[position] = (byte)rs[position];
-            return ret;
-        }
-
-        /// <summary>
-        ///  Look up the 3 bits base64-encoded by the specified character, range-checking against
-        ///  conversion table.
-        /// </summary>
-        /// <param name="character">The base64-encoded value.</param>
-        /// <returns>The decoded value of x.</returns>
-        private static int Char64(char character)
-        {
-            if (character < 0 || character > _Index64.Length)
-                return -1;
-            return _Index64[character];
-        }
-
         /// <summary>Blowfish encipher a single 64-bit block encoded as two 32-bit halves.</summary>
         /// <param name="blockArray">An array containing the two 32-bit half blocks.</param>
         /// <param name="offset">    The position in the array of the blocks.</param>
@@ -759,59 +429,11 @@ namespace Renci.SshNet.Security.Cryptography
             }
         }
 
-        /// <summary>Perform the central hashing step in the bcrypt scheme.</summary>
-        /// <exception cref="ArgumentException">Thrown when one or more arguments have unsupported or
-        ///                                     illegal values.</exception>
-        /// <param name="inputBytes">The input byte array to hash.</param>
-        /// <param name="saltBytes"> The salt byte array to hash with.</param>
-        /// <param name="logRounds"> The binary logarithm of the number of rounds of hashing to apply.</param>
-        /// <returns>A byte array containing the hashed result.</returns>
-        private byte[] CryptRaw(byte[] inputBytes, byte[] saltBytes, int logRounds)
-        {
-            uint[] cdata = new uint[_BfCryptCiphertext.Length];
-            Array.Copy(_BfCryptCiphertext, cdata, _BfCryptCiphertext.Length);
-            int clen = cdata.Length;
-
-            if (logRounds < 4 || logRounds > 31)
-                throw new ArgumentException("Bad number of rounds", "logRounds");
-
-            if (saltBytes.Length != BCRYPT_SALT_LEN)
-                throw new ArgumentException("Bad salt Length", "saltBytes");
-
-            uint rounds = 1u << logRounds;
-            Debug.Assert(rounds > 0, "Rounds must be > 0"); // We overflowed rounds at 31 - added safety check
-
-            InitializeKey();
-            EKSKey(saltBytes, inputBytes);
-
-            for (int i = 0; i < rounds; i++)
-            {
-                Key(inputBytes);
-                Key(saltBytes);
-            }
-
-            for (int i = 0; i < 64; i++)
-            {
-                for (int j = 0; j < (clen >> 1); j++)
-                    Encipher(cdata, j << 1);
-            }
-
-            byte[] ret = new byte[clen * 4];
-            for (int i = 0, j = 0; i < clen; i++)
-            {
-                ret[j++] = (byte)((cdata[i] >> 24) & 0xff);
-                ret[j++] = (byte)((cdata[i] >> 16) & 0xff);
-                ret[j++] = (byte)((cdata[i] >> 8) & 0xff);
-                ret[j++] = (byte)(cdata[i] & 0xff);
-            }
-            return ret;
-        }
-
         /**
          * Compatibility with new OpenBSD function.
          * Ported from SSHJ library (https://github.com/hierynomus/sshj)
          */
-        public void Hash(byte[] hpass, byte[] hsalt, byte[] output)
+        private void Hash(byte[] hpass, byte[] hsalt, byte[] output)
         {
             InitializeKey();
             EKSKey(hsalt, hpass);
@@ -924,29 +546,5 @@ namespace Renci.SshNet.Security.Cryptography
 
             return result;
         }
-
-        /// <summary>Exception for signalling parse errors. </summary>
-        public class SaltParseException : Exception
-        {
-            /// <summary>Default constructor. </summary>
-            public SaltParseException()
-            {
-            }
-
-            /// <summary>Initializes a new instance of <see cref="SaltParseException"/>.</summary>
-            /// <param name="message">The message.</param>
-            public SaltParseException(string message)
-                : base(message)
-            {
-            }
-
-            /// <summary>Initializes a new instance of <see cref="SaltParseException"/>.</summary>
-            /// <param name="message">       The message.</param>
-            /// <param name="innerException">The inner exception.</param>
-            public SaltParseException(string message, Exception innerException)
-                : base(message, innerException)
-            {
-            }
-        }
     }
 }