Плохая крипто ошибка в .NET 4.0 - PullRequest
4 голосов
/ 13 мая 2010

Сегодня я переместил свое веб-приложение на .net 4.0, и Forms Auth просто перестал работать. После нескольких часов копания в моем SqlMembershipProvider (упрощенная версия встроенного SqlMembershipProvider) я обнаружил, что хеш HMACSHA256 не согласован. Это метод шифрования:

internal string EncodePassword(string pass, int passwordFormat, string salt)
{
    if (passwordFormat == 0) // MembershipPasswordFormat.Clear
        return pass;

    byte[] bIn = Encoding.Unicode.GetBytes(pass);
    byte[] bSalt = Convert.FromBase64String(salt);
    byte[] bAll = new byte[bSalt.Length + bIn.Length];
    byte[] bRet = null;

    Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
    Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
    if (passwordFormat == 1)
    { // MembershipPasswordFormat.Hashed
        HashAlgorithm s = HashAlgorithm.Create( Membership.HashAlgorithmType );
        bRet = s.ComputeHash(bAll);
    } else
    {
        bRet = EncryptPassword( bAll );
    }

    return Convert.ToBase64String(bRet);
}

Передача одного и того же пароля и соли дважды возвращает разные результаты !!! Он отлично работал в .NET 3.5

Кто-нибудь знает о любых критических изменениях, или это известная ошибка?

ОБНОВЛЕНИЕ: Когда я указываю SHA512 в качестве алгоритма хеширования, все работает нормально, поэтому я считаю, что это ошибка в реализации алгоритма хеширования HMACSHA256 в .NET 4.0

Спасибо! Андрей

Ответы [ 2 ]

2 голосов
/ 20 августа 2010

Я тоже столкнулся с этой проблемой.

В моей ситуации конечная цель состояла в том, чтобы иметь возможность динамически устанавливать connectionString (вместо жестко заданного в web.config). Я сделал это, загрузив исходный код MS для провайдеров ASP.NET и изменив некоторые внутренние функции для получения строки подключения.

Однако все это было для .NET 2.0 и выглядит так же, как код, который выложил выше Андрей. Как только я все это установил, я заметил, что не могу войти на свой сайт. Поэтому после поиска я нашел этот пост. Спасибо!

Я скачал код .NET Framework 4.0 и (если кто-то хочет знать) вот новая версия метода EncodePassword. Я планирую скопировать это в мою старую версию SqlMembershipProvider, чтобы я мог использовать новые методы шифрования и снова иметь возможность войти на свой сайт ASP.NET 4.0!

    private string EncodePassword(string pass, int passwordFormat, string salt)
    { 
        if (passwordFormat == 0) // MembershipPasswordFormat.Clear
            return pass;

        byte[] bIn = Encoding.Unicode.GetBytes(pass); 
        byte[] bSalt = Convert.FromBase64String(salt);
        byte[] bRet = null; 

        if (passwordFormat == 1)
        { // MembershipPasswordFormat.Hashed 
            HashAlgorithm hm = GetHashAlgorithm();
            if (hm is KeyedHashAlgorithm) {
                KeyedHashAlgorithm kha = (KeyedHashAlgorithm) hm;
                if (kha.Key.Length == bSalt.Length) { 
                    kha.Key = bSalt;
                } else if (kha.Key.Length < bSalt.Length) { 
                    byte[] bKey = new byte[kha.Key.Length]; 
                    Buffer.BlockCopy(bSalt, 0, bKey, 0, bKey.Length);
                    kha.Key = bKey; 
                } else {
                    byte[] bKey = new byte[kha.Key.Length];
                    for (int iter = 0; iter < bKey.Length; ) {
                        int len = Math.Min(bSalt.Length, bKey.Length - iter); 
                        Buffer.BlockCopy(bSalt, 0, bKey, iter, len);
                        iter += len; 
                    } 
                    kha.Key = bKey;
                } 
                bRet = kha.ComputeHash(bIn);
            }
            else {
                byte[] bAll = new byte[bSalt.Length + bIn.Length]; 
                Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
                Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length); 
                bRet = hm.ComputeHash(bAll); 
            }
        } else { 
            byte[] bAll = new byte[bSalt.Length + bIn.Length];
            Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
            Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
            bRet = EncryptPassword(bAll, _LegacyPasswordCompatibilityMode); 
        }

        return Convert.ToBase64String(bRet); 
    }

Edit: Попытка скопировать этот метод в старую версию SqlMembershipProvider была плохой идеей. Слишком многое изменилось. (

2 голосов
/ 19 мая 2010

Я полагаю, что в .net 4.0 произошли некоторые изменения, связанные с безопасностью, посмотрите на это ...

http://www.asp.net/(S(ywiyuluxr3qb2dfva1z5lgeg))/learn/whitepapers/aspnet4/breaking-changes

Первое, что бросается в глаза, это ...

Алгоритм хеширования по умолчанию теперь HMACSHA256

ASP.NET использует как шифрование, так и алгоритмы хеширования для защиты данных такие как куки проверки подлинности форм и просматривать состояние. По умолчанию ASP.NET 4 теперь использует алгоритм HMACSHA256 для хэш-операции с файлами cookie и просмотр государство. Более ранние версии ASP.NET использовал более старый алгоритм HMACSHA1.

Ваши приложения могут быть затронуты, если вы используете смешанный ASP.NET 2.0 / ASP.NET 4 среды, в которых такие данные, как формы куки аутентификации должны работать через .NET Framework версии. к настроить веб-приложение ASP.NET 4 использовать более старый алгоритм HMACSHA1, добавить следующий параметр в Файл Web.config:

      <machineKey validation="SHA1" />

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

Сказав это, M $, возможно, удалил тот, который вы используете, так что это может быть причиной, чёрт побери ... я только что понял, что мне нужно проверить мою CMS ... это не произошло со мной.

Спасибо за внимание, надеюсь, мои мысли помогут нам обоим !!!

...