Подтвердить что ты не робот

ASP.NET членская соль?

Как членство ASP.NET генерирует свой ключ соли, а затем как они кодируют его (то есть, это соль + пароль или пароль + соль)?

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

Изменить 2: Ничего. Я неправильно понял и думал, что он сказал байты, а не бит. Таким образом, я проходил 128 байтов, а не 128 бит.

Изменить: Я пытался это сделать. Это то, что у меня есть,

public string EncodePassword(string password, string salt)
{
    byte[] bytes = Encoding.Unicode.GetBytes(password);
    byte[] src = Encoding.Unicode.GetBytes(salt);
    byte[] dst = new byte[src.Length + bytes.Length];

    Buffer.BlockCopy(src, 0, dst, 0, src.Length);
    Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);

    HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");

    byte[] inArray = algorithm.ComputeHash(dst);

    return Convert.ToBase64String(inArray);
}

private byte[] createSalt(byte[] saltSize)
{
    byte[] saltBytes = saltSize;

    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
    rng.GetNonZeroBytes(saltBytes);

    return saltBytes;
}

Итак, я не пытался узнать, узнает ли членство ASP.NET, но хешированный пароль выглядит близко. Я просто не знаю, как преобразовать его в base64 для соли.

Я сделал это

byte[] storeSalt = createSalt(new byte[128]);
string salt = Encoding.Unicode.GetString(storeSalt);
string base64Salt = Convert.ToBase64String(storeSalt);

int test = base64Salt.Length;

Длина теста равна 172, что намного превышает 128 бит, так что я делаю неправильно?

Это их соль выглядит как

vkNj4EvbEPbk1HHW+K8y/A==

Это то, что моя соль выглядит как

E9oEtqo0livLke9+csUkf2AOLzFsOvhkB/NocSQm33aySyNOphplx9yH2bgsHoEeR/aw/pMe4SkeDvNVfnemoB4PDNRUB9drFhzXOW5jypF9NQmBZaJDvJ+uK3mPXsWkEcxANn9mdRzYCEYCaVhgAZ5oQRnnT721mbFKpfc4kpI=
4b9b3361

Ответ 1

Что такое хэш-алгоритм по умолчанию, который использует членство ASP.NET? имеет хорошее обсуждение их алгоритма по умолчанию.

Я надеюсь, что это поможет!

Edit- Ответ, на который я имел в виду, - это код в верхнем сообщении,

   public string EncodePassword(string pass, string salt)
    {
        byte[] bytes = Encoding.Unicode.GetBytes(pass);
        //byte[] src = Encoding.Unicode.GetBytes(salt); Corrected 5/15/2013
        byte[] src = Convert.FromBase64String(salt); 
        byte[] dst = new byte[src.Length + bytes.Length];
        Buffer.BlockCopy(src, 0, dst, 0, src.Length);
        Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
        HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
        byte[] inArray = algorithm.ComputeHash(dst);
        return Convert.ToBase64String(inArray);
    } 

Они объединяют Unicode Salt + Pass, используя BlockCopy

- В ответ на ваш вопрос:

Оба алгоритма необходимы и выполняют разные роли...

RNG Crypto используется для получения соли. Это в основном длинная строка случайных данных. Это генерируется и сохраняется на основе каждого пользователя. Обычно это делается при создании пользователя или изменении пароля.

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

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

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

Я думаю, что мы оба по-другому читаем ваш вопрос. Код, который я написал, не будет генерировать соль, но он позволит вам использовать его таким образом, который совместим с членством в ASP.NET.

Извините, мое объяснение не самое лучшее - это ответ на ваш вопрос?

Ответ 2

Вот как SQLMembershipProvider генерирует соль.

    private string GenerateSalt() {
        var buf = new byte[16];
        (new RNGCryptoServiceProvider()).GetBytes(buf);
        return Convert.ToBase64String(buf);
   }

Вы можете загрузить код поставщика ASP.NET SQL здесь.

Проблема, с которой я столкнулась, - это приложение для разработки, работающее на IIS7. В .NET 4.0 использовался другой хэш-алгоритм по умолчанию, отличный от HashAlgorithmType по умолчанию для .NET 2.0.

В примере кода "EncodePassword" от Microsoft они ссылаются на Membership.HashAlgorithmType, который, как мне кажется, возвращает значение по умолчанию для фреймворка, если оно не указано в web.config.

Мне удалось заставить оба метода GenerateSalt и EncodePassword работать для моего приложения.

Мой комбинированный код:

internal string GenerateSalt()
{
    byte[] buf = new byte[16];
    (new RNGCryptoServiceProvider()).GetBytes(buf);
    return Convert.ToBase64String(buf);
}

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("SHA1");
        // Hardcoded "SHA1" instead of Membership.HashAlgorithmType
        bRet = s.ComputeHash(bAll);
    }
    else
    {
        bRet = EncryptPassword(bAll);
    }
    return Convert.ToBase64String(bRet);
}

Ответ 3

Вот один из способов сделать это. Соль - это просто случайное число, вы можете использовать класс RNGCryptoServiceProvider в библиотеке фреймов для получения хорошего случайного числа для использования в качестве соли

private const int ITERATIONS = 10000;
private const int SALT_SIZE = 32;
private const int HASH_SIZE = 32;

public void SaltAndHashPassword(string password, out byte[] salt,
  out byte[] hash)
{
  Rfc2898DeriveBytes rdb = new Rfc2898DeriveBytes(
    password,
    SALT_SIZE,
    ITERATIONS);

  salt = rdb.Salt;
  hash = rdb.GetBytes(HASH_SIZE);
}