Хеширование в формате обновляемого состояния строится вокруг идеи постепенной подачи данных в алгоритм вместо формирования хеша за один вызов. Такой подход становится критически важным при работе с потоками данных, большими файлами, сетевыми буферами и любыми ситуациями, где весь массив данных недоступен сразу или его обработка целиком неэффективна по памяти.
В Jsrsasign эта модель реализована через объект
KJUR.crypto.MessageDigest, который поддерживает
инкрементное обновление внутреннего состояния и финализацию результата
через digest.
Любая криптографическая хеш-функция в инкрементной форме работает как конечный автомат с внутренним состоянием:
Ключевая особенность — после каждого update состояние не
теряется, а модифицируется.
В Jsrsasign объект хеширования создаётся через фабричный метод:
var md = new KJUR.crypto.MessageDigest({alg: "sha256"});
Поддерживаемые алгоритмы включают:
sha1sha256sha512md5 (не рекомендуется для криптографических целей)Внутри создаётся состояние алгоритма, аналогичное контексту в низкоуровневых реализациях OpenSSL-подобного типа.
Основной метод инкрементного хеширования:
md.updateString("Hello ");
md.updateString("world");
Jsrsasign поддерживает несколько форматов входных данных:
md.updateString("data");
Данные интерпретируются как UTF-8 последовательность.
md.updateHex("616263"); // "abc"
Каждая пара символов рассматривается как байт.
Прямой Uint8Array не всегда используется напрямую, поэтому часто применяется промежуточное преобразование.
После накопления данных вызывается метод завершения:
var hash = md.digest();
Возвращаемое значение зависит от выбранного формата:
Пример полного цикла:
var md = new KJUR.crypto.MessageDigest({alg: "sha256"});
md.updateString("Hello ");
md.updateString("world");
var result = md.digest();
После вызова digest() объект:
Практически это означает, что повторное использование требует нового экземпляра:
md = new KJUR.crypto.MessageDigest({alg: "sha256"});
Основная область применения update/digest — работа с данными, поступающими порциями.
Пример сценария: обработка файла блоками
var md = new KJUR.crypto.MessageDigest({alg: "sha256"});
md.updateString(chunk1);
md.updateString(chunk2);
md.updateString(chunk3);
var hash = md.digest();
Если данные приходят из потока, модель остаётся той же:
Jsrsasign также предоставляет более простой способ:
KJUR.crypto.Util.hashString("sha256", "Hello world");
Но этот вариант:
Инкрементная модель через MessageDigest предпочтительна
при любом масштабировании данных.
Хеш-функции работают блоками фиксированного размера:
Метод update не вызывает вычисление финального
результата сразу. Вместо этого:
Это соответствует классической Merkle–Damgård конструкции.
Jsrsasign допускает смешивание форматов:
md.updateString("abc");
md.updateHex("646566");
md.updateString("ghi");
Внутренне всё приводится к единому байтовому представлению.
Критический момент — согласованность кодировки:
updateString использует UTF-8updateHex не зависит от кодировкиПри смешивании важно учитывать, что строка и hex не эквивалентны на уровне представления байтов.
Некоторые сценарии требуют вычисления нескольких хешей:
var md = new KJUR.crypto.MessageDigest({alg: "sha256"});
md.updateString("A");
var h1 = md.digest();
md = new KJUR.crypto.MessageDigest({alg: "sha256"});
md.updateString("B");
var h2 = md.digest();
Попытка повторного update после digest без
переинициализации может приводить к некорректным результатам.
Инкрементная модель показывает преимущества:
Однако существует накладной расход:
update вызывает обработку состоянияОптимальная стратегия — подавать данные крупными блоками.
На практике встречаются характерные проблемы:
md.updateString("a");
md.digest();
md.updateString("b"); // некорректно
Смешивание UTF-8 строк и hex без контроля приводит к разным результатам хеша.
for (var i = 0; i < str.length; i++) {
md.updateString(str[i]);
}
Такой подход создаёт значительные накладные расходы.
Типичная архитектура обработки потоков:
function processStream(chunks) {
var md = new KJUR.crypto.MessageDigest({alg: "sha256"});
for (var i = 0; i < chunks.length; i++) {
md.updateString(chunks[i]);
}
return md.digest();
}
Такая схема легко масштабируется до:
Инкрементный подход используется как базовый механизм в:
Jsrsasign строит многие криптографические примитивы поверх
MessageDigest, что делает понимание update/digest
фундаментальным для всей библиотеки.