Вопрос

я спрашиваю себя, было бы опасно на заднем плане кода asp.net страниц использовать статическую (общую) переменную, которая содержит экземпляр HMACSHA1.проблема в том, что же HMACSHA1 инстанции будет использоваться всеми рабочего процесса ASP.NET темы для обработки нескольких одновременных запросов на тот же АСП.нет-страницу.все переменные экземпляра (HMACSHA1) и метода ComputeHash(), которые используются / модифицируются ComputeHash(), будут совместно использоваться (= могут быть изменены) всеми потоками?!верно ли это предположение?в результате возвращаемое значение ComputeHash не было бы гарантированно правильным ?!?!таким образом, мне не разрешено использовать статический / общий экземпляр HMACSHA1 во всех потоках asp.net..

мне просто интересно, что вы думаете об этой проблеме.

единственным решением для этого было бы что-то вроде критического пути и т.д. В ComputeHash()-методе.но это "вне нашей досягаемости"..

с уважением, крис

Это было полезно?

Решение

Алгоритмы хеширования детерминированы, они должен каждый раз возвращайте один и тот же хэш для заданного ввода.

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

Определенно опасно использовать статический экземпляр.Если Thread1 задает значение, подлежащее вычислению, а затем Thread2 устанавливает значение перед тем, как Thread1 вызовет ComputerHash(), то Thread1 получит хэш значения Thread2.То же самое произойдет, если любой из потоков устанавливает ключ.

Другие советы

Я только что получил неизвестное криптографическое исключение из SHA256Cng.ComputeHash при выполнении 8 или 16 параллельных задач, которые, помимо прочего, выполняли вычисление хэша, на четырехъядерном процессоре HT.

Добавление семантики блокировки вокруг ComputeHash решило проблему - так что, похоже, по крайней мере, версия SHA256Cng не является потокобезопасной.

Стоит знать, что KeyedHashAlgorithm.ComputeHash() не является потокобезопасным, потому что это дает недетерминированный результат для одного и того же KeyedHashAlgorithm.Key.

В моем случае я хочу кэшировать KeyedHashAlgorithm, поскольку мой KeyedHashAlgorithm.Key всегда одно и то же для проверки подлинность со стороны клиента.Я понимаю , что ComputeHash() не согласован, вероятно, он кэширует внутреннюю переменную в KeyedHashAlgorithm пример.Я должен кэшировать экземпляр для каждого потока ThreadStatic или ThreadLocal.Это и есть испытание:

Статический KeyedHashAlgorithm дает противоречивый результат:

var kha = KeyedHashAlgorithm.Create("HMACSHA256");
kha.Key = Encoding.UTF8.GetBytes("key");
Action comp = () =>
{
    var computed = kha.ComputeHash(Encoding.UTF8.GetBytes("message"));
    Console.WriteLine(Convert.ToBase64String(computed));
};
Parallel.Invoke(comp, comp, comp, comp, comp, comp, comp, comp);

По сравнению с KeyedHashAlgorithm на поток:

ThreadLocal<KeyedHashAlgorithm> tl= new ThreadLocal<KeyedHashAlgorithm>(() =>
{
    var kha = KeyedHashAlgorithm.Create("HMACSHA256");
    kha.Key = Encoding.UTF8.GetBytes("key");
    return kha;
});
Action comp = () =>
{
    var computed = tl.Value.ComputeHash(Encoding.UTF8.GetBytes("message"));
    Console.WriteLine(Convert.ToBase64String(computed));
};
Parallel.Invoke(comp, comp, comp, comp, comp, comp, comp, comp);

Этот код можно использовать для тестирования других функций на предмет "потокобезопасности".Надеюсь, это поможет другим.

Если вы хотите потокобезопасности без блокировки, вы можете использовать атрибут ThreadStatic для создания уникального экземпляра в каждом потоке следующим образом:

[ThreadStatic]
private static HMACSHA1 _hmacSha1;

public static HMACSHA1 HmacSha1
{
    get 
    {
        if (_hmacSha1 == null)
        {
            // this will happen once on each thread
            _hmacSha1 = new HMACSHA1(GetKeyBytes());
        }               

        return _hmacSha1;
    }
}

Теперь два дополнительных замечания:

  1. Доступ к статическому полю потока занимает значительно больше времени, чем доступ к обычному статическому полю.Таким образом, потоково-статическая версия может быть или не быть лучше для вас.

  2. Если вы делаете это один раз для каждого запроса страницы, то разница будет настолько незначительной, что не будет иметь значения, какой подход вы выберете.Если вы делали это в очень узком цикле, или код в вашем разделе блокировки занимал очень много времени, то выбор мог быть важным.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top