Генерируйте хеш пароля, используя строковую соль - PullRequest
0 голосов
/ 11 мая 2018

Я работаю над REST Api с использованием .NET Core в существующей базе данных, в которой используется аутентификация .Net Framework Identity.

У меня есть таблица aspnet_Users, которая содержит username, и таблица aspnet_Membership, которая содержит passwordHash и passwordSalt.

Моя идея состояла в том, чтобы проверить пароль с помощью соли для генерации хеша и сравнить его с предоставленным строковым паролем в запросе на вход в систему. Но ...

passwordHash и passwordSalt в БД хранятся в виде строк.

Мой вопрос: как мне использовать строковую соль для генерации хеша. Я привык к byte[], а не string ...

Ответы [ 3 ]

0 голосов
/ 11 мая 2018

Благодаря: https://stackoverflow.com/posts/2138588

static byte[] GenerateSaltedHash(byte[] plainText, byte[] salt)
{
  HashAlgorithm algorithm = new SHA256Managed();

  byte[] plainTextWithSaltBytes = 
    new byte[plainText.Length + salt.Length];

  for (int i = 0; i < plainText.Length; i++)
  {
    plainTextWithSaltBytes[i] = plainText[i];
  }
  for (int i = 0; i < salt.Length; i++)
  {
    plainTextWithSaltBytes[plainText.Length + i] = salt[i];
  }

  return algorithm.ComputeHash(plainTextWithSaltBytes);            
}

Вы можете преобразовать текст в байтовые массивы, используя Encoding.UTF8.GetBytes(string). Если вам необходимо преобразовать хеш в его строковое представление, вы можете использовать Convert.ToBase64String и Convert.FromBase64String, чтобы преобразовать его обратно.

Вы должны заметить, что вы не можете использовать оператор равенства в байтовых массивах, он проверяет ссылки, и поэтому вы должны просто перебрать оба массива, проверяя каждый байт, таким образом

public static bool CompareByteArrays(byte[] array1, byte[] array2)
{
  if (array1.Length != array2.Length)
  {
    return false;
  }

  for (int i = 0; i < array1.Length; i++)
  {
    if (array1[i] != array2[i])
    {
      return false;
    }
  }

  return true;
}
0 голосов
/ 12 мая 2018

Ну, вы не сказали, какой тип хэширования вы хотите;) Итак, вот один, который я всегда использую для своих проектов.Он написан моим бывшим штатным инженером.

Я проверял этот кусок кода раньше.Вы можете попробовать отладку, чтобы увидеть, действительно ли нужен объект мьютекса.Я сомневаюсь в этом, но всегда безопаснее предоставить вам оригинальный код, чтобы вы могли поиграть с ним.

public class AES256Hash
    {
        private static byte[] key;
        private static Object mutex = new Object();

        private const int KEY_SIZE = 256;
        private const int BLOCK_SIZE = 128;
        private const int IV_KEY_SIZE = 16; // 16 byte

        private AES256Hash()
        {
        }

        /// <summary>
        /// Create a new randomized cipher on each startup
        /// </summary>
        private static void InitializeCipherKey()
        {
            lock (mutex)
            {
                if (key == null)
                {
                    key = new byte[32];

                    var cr = new System.Security.Cryptography.RNGCryptoServiceProvider();
                    cr.GetBytes(key, 0, key.Length);
                }
            }
        }

        /// <summary>
        /// Converts the input data into an IV key
        /// </summary>
        /// <param name="Data"></param>
        /// <returns></returns>
        private static byte[] CreateIvKey(string Data)
        {
            byte[] IvKey = new UTF8Encoding().GetBytes(Data);
            if (IvKey.Length != IV_KEY_SIZE)
            {
                byte[] NewTruncatedIvKey = new byte[IV_KEY_SIZE];
                Buffer.BlockCopy(IvKey, 0, NewTruncatedIvKey, 0, Math.Min(IV_KEY_SIZE, IvKey.Length)); // the rest of the bytes are 0 padded

                return NewTruncatedIvKey;
            }
            return IvKey;
        }

        /// <summary>
        /// Encrypts a string with AES256 with the given key and string data
        /// </summary>
        /// <param name="Key"></param>
        /// <param name="Data"></param>
        /// <returns></returns>
        public static string EncryptString(string Key, string Data)
        {
            InitializeCipherKey();

            byte[] IvKey = CreateIvKey(Key);
            byte[] dataB = new UTF8Encoding().GetBytes(Data);

            using (AesCryptoServiceProvider csp = new AesCryptoServiceProvider())
            {
                csp.Padding = PaddingMode.PKCS7;
                csp.Mode = CipherMode.ECB;

                csp.KeySize = KEY_SIZE;
                csp.BlockSize = BLOCK_SIZE;
                csp.Key = key;
                csp.IV = IvKey;
                ICryptoTransform encrypter = csp.CreateEncryptor();

                return Convert.ToBase64String(encrypter.TransformFinalBlock(dataB, 0, dataB.Length));
            }
        }

        /// <summary>
        /// Decrypts a string with AES256 with the given key and string data
        /// </summary>
        /// <param name="Key"></param>
        /// <param name="Data"></param>
        /// <returns></returns>
        public static string DecryptString(string Key, string Data)
        {
            InitializeCipherKey();

            byte[] IvKey = CreateIvKey(Key);
            byte[] dataB = Convert.FromBase64String(Data);

            using (AesCryptoServiceProvider csp = new AesCryptoServiceProvider())
            {
                csp.Padding = PaddingMode.PKCS7;
                csp.Mode = CipherMode.ECB;

                csp.KeySize = KEY_SIZE;
                csp.BlockSize = BLOCK_SIZE;
                csp.Key = key;
                csp.IV = IvKey;
                ICryptoTransform decrypter = csp.CreateDecryptor();

                return new UTF8Encoding().GetString( decrypter.TransformFinalBlock(dataB, 0, dataB.Length) );
            }
        }
    }
0 голосов
/ 11 мая 2018

Чтобы ответить на ваш вопрос, самый простой способ преобразовать строку в байт [] - использовать System.Text.Encoding.UTF8.GetBytes().

При этом вам следует выяснить, хотите ли вы использовать собственный код для проверки пароля, поскольку распространено мнение, что вам следует избегать его . Там есть библиотеки, которые могут сделать это для вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...