Подключение сторонних алгоритмов

Библиотека CryptoJS построена как модульная система, в которой каждый криптографический примитив реализуется через единый набор базовых абстракций: WordArray, Base, BufferedBlockAlgorithm, Hasher, Cipher, BlockCipher, StreamCipher. Такая структура позволяет подключать сторонние алгоритмы без изменения ядра библиотеки.

Все расширения регистрируются в пространстве имён CryptoJS.algo, а их поведение определяется через наследование базовых классов.


Базовые сущности для расширения

WordArray

Основной контейнер данных, используемый во всех алгоритмах:

const data = CryptoJS.enc.Utf8.parse("test");

Структура хранит массив 32-битных слов и длину в байтах. Любой сторонний алгоритм работает именно с этим форматом.


Base

Корневой класс для всех компонентов библиотеки:

  • обеспечивает наследование
  • реализует extend
  • управляет инициализацией
const CustomAlgo = CryptoJS.lib.Base.extend({
    init: function () {
        this.state = 0;
    }
});

Hasher

Абстракция для криптографических хеш-функций:

  • MD5
  • SHA-1
  • SHA-256

Структура стороннего хеша строится на переопределении методов _doReset, _doProcessBlock, _doFinalize.


Подключение собственного хеш-алгоритма

Кастомный алгоритм хеширования определяется через наследование CryptoJS.algo.SHA256 или CryptoJS.lib.Hasher.

Пример структуры

const CustomHash = CryptoJS.lib.Hasher.extend({

    _doReset: function () {
        this._state = 0;
    },

    _doProcessBlock: function (words, offset) {
        for (let i = 0; i < 16; i++) {
            this._state ^= words[offset + i];
        }
    },

    _doFinalize: function () {
        const result = CryptoJS.lib.WordArray.create();
        result.words[0] = this._state;
        result.sigBytes = 4;
        return result;
    }
});

Регистрация алгоритма

CryptoJS.algo.CustomHash = CustomHash;

Использование происходит через стандартный интерфейс:

const hash = CryptoJS.algo.CustomHash.create();
hash.update("data");
const result = hash.finalize();

Подключение сторонних режимов шифрования

Режимы шифрования реализуются через CryptoJS.mode.

Базовый класс:

  • CryptoJS.lib.BlockCipherMode
  • CryptoJS.lib.BlockCipherMode.Encryptor
  • CryptoJS.lib.BlockCipherMode.Decryptor

Структура пользовательского режима

const CustomMode = CryptoJS.lib.BlockCipherMode.extend({

    Encryptor: CryptoJS.lib.BlockCipherMode.Encryptor.extend({
        processBlock: function (words, offset) {
            this._cipher.encryptBlock(words, offset);
        }
    }),

    Decryptor: CryptoJS.lib.BlockCipherMode.Decryptor.extend({
        processBlock: function (words, offset) {
            this._cipher.decryptBlock(words, offset);
        }
    })
});

Регистрация:

CryptoJS.mode.CustomMode = CustomMode;

Подключение собственного алгоритма блочного шифрования

Блочные шифры наследуются от CryptoJS.lib.BlockCipher.

Основные методы:

  • _doReset — инициализация ключа
  • _encryptBlock — шифрование блока
  • _decryptBlock — расшифрование блока
  • _doFinalize — финальная обработка

Пример минимального шифра

const CustomCipher = CryptoJS.lib.BlockCipher.extend({

    _doReset: function () {
        this._subKey = this.key.words[0];
    },

    _encryptBlock: function (words, offset) {
        words[offset] ^= this._subKey;
        words[offset + 1] ^= this._subKey;
    },

    _decryptBlock: function (words, offset) {
        words[offset] ^= this._subKey;
        words[offset + 1] ^= this._subKey;
    }
});

Регистрация:

CryptoJS.algo.CustomCipher = CustomCipher;

Подключение собственных схем паддинга

Паддинг реализуется через CryptoJS.pad.

Стандартный интерфейс:

  • pad
  • unpad

Пример кастомного паддинга

const CustomPad = {
    pad: function (data, blockSize) {
        const padding = blockSize - (data.sigBytes % blockSize);
        for (let i = 0; i < padding; i++) {
            data.words.push(padding);
        }
        data.sigBytes += padding;
    },

    unpad: function (data) {
        const padding = data.words[data.sigBytes - 1];
        data.sigBytes -= padding;
    }
};

Регистрация:

CryptoJS.pad.CustomPad = CustomPad;

Подключение генераторов ключей

KDF (Key Derivation Function) подключаются через CryptoJS.algo.

Основная структура:

const CustomKDF = CryptoJS.algo.EvpKDF.extend({

    cfg: CryptoJS.algo.EvpKDF.cfg.extend({
        keySize: 4,
        iterations: 1
    }),

    compute: function (password, salt) {
        const result = CryptoJS.lib.WordArray.create();
        result.words[0] = password.words[0] ^ salt.words[0];
        result.sigBytes = 16;
        return result;
    }
});

Регистрация:

CryptoJS.algo.CustomKDF = CustomKDF;

Использование пространства CryptoJS.algo

Все подключаемые алгоритмы фиксируются в одном реестре:

  • CryptoJS.algo — хеши и ключевые функции
  • CryptoJS.mode — режимы шифрования
  • CryptoJS.pad — схемы дополнения
  • CryptoJS.format — форматы сериализации

Структура расширения всегда предполагает явное добавление:

CryptoJS.algo.MyAlgorithm = MyAlgorithm;

Взаимодействие с CipherParams

Результат работы криптографических операций инкапсулируется в CipherParams:

  • ciphertext
  • key
  • iv
  • salt

Подключаемые алгоритмы автоматически используют эту структуру при вызове encrypt и decrypt.


Подключение внешних модулей через UMD и расширения

Сторонние реализации часто поставляются как отдельные файлы:

  • UMD-модули
  • плагины для CryptoJS
  • кастомные сборки

Типичная схема интеграции:

(function (CryptoJS) {

    const ExternalAlgo = CryptoJS.algo.Base.extend({
        process: function () {}
    });

    CryptoJS.algo.ExternalAlgo = ExternalAlgo;

})(CryptoJS);

Особенности совместимости алгоритмов

При подключении сторонних реализаций учитываются внутренние ограничения:

  • работа исключительно через WordArray
  • 32-битная модель обработки данных
  • блочная структура для BlockCipher
  • обязательная реализация _doProcessBlock для хешей
  • использование BufferedBlockAlgorithm для потоковой обработки

Интеграция нестандартных режимов и алгоритмов в цепочку шифрования

CryptoJS поддерживает композицию:

  • алгоритм шифрования
  • режим работы
  • схема паддинга
  • кодировка результата

Структура вызова:

CryptoJS.AES.encrypt(data, key, {
    mode: CryptoJS.mode.CustomMode,
    padding: CryptoJS.pad.CustomPad
});

Каждый компонент может быть заменён внешней реализацией без изменения ядра библиотеки.