blank
blank
127018, Москва, ул.Сущевский Вал д.16 стр.5
Тел./факс:
+7 (495) 780 4820
+7 (495) 660 2330
сайт: http://www.cryptopro.ru
e-mail: info@cryptopro.ru
blank
blank

Средство
Криптографической
Защиты
Информации

КриптоПро JCP
Версия 1.0


Руководство программиста. Модули шифрования

ЖТЯИ.00031-01 33 02


© OOO "Крипто-Про", 2005-2009. Все права защищены.

Авторские права на средство криптографической защиты информации КриптоПро JCP и эксплуатационную документацию зарегистрированы в Российском агентстве по патентам и товарным знакам (Роспатент).

Документ входит в комплект поставки программного обеспечения КриптоПро JCP, и на него распространяются все условия лицензионного соглашения. Без специального письменного разрешения OOO "Крипто-Про" документ или его часть в электронном или печатном виде не могут быть скопированы и переданы третьим лицам с коммерческой целью.

blank

Описание стандартного интерфейса JCE.

Описание основной функциональности криптопровайдера КриптоПро JCP

Связь с разработчиком.
Поддержка.
Форум.





Содержание

  1. Введение
  2. Работа с ключами в криптопровайдере КриптоПро JCP (модули шифрования)
  3. Имитозащита данных в соответствии с алгоритмом ГОСТ 28147-89
  4. Шифрование данных и ключей в соответствии с алгоритмом ГОСТ 28147-89
  5. Шифрование XML-документов

Введение

Настоящее руководство содержит описание основной функциональности криптопровайдера КриптоПро JCP (модули шифрования) и примеры их использования.

Криптопровайдер КриптоПро JCP является средством криптографической защиты информации (СКЗИ КриптоПро JCP 1.0), реализующим российские криптографические алгоритмы и функционирующим под управлением виртуальной машины Java 2 Runtime Environment версии 1.4.2 и выше, соответствующей спецификации Sun Java 2 TM Virtual Machine.

Криптопровайдер КриптоПро JCP (модули шифрования) реализует стандартный интерфейс Java Cryptography Extension (JCE) в соответствии с российскими криптографическими алгоритмами и обеспечивает выполнение следующих операций через стандартный интерфейс JCE:

Основные технические данные и характеристики СКЗИ, а также информацию о совместимости с другими продуктами КриптоПро см. в Руководстве администратора безопасности

Работа с ключами в криптопровайдере КриптоПро JCP (модули шифрования)

Основная работа с ключами в криптопровайдере КриптоПро JCP (модули шифрования) осуществляется в соответствии с интерфейсами JCE. К ним относятся выработка ключей согласования по алгоритму Диффи-Хелмана, генерирование симметричных ключей шифрования. Но существуют также методы, работающие с ключами через интерфейс JCA. К ним относятся генерирование ключевых пар обмена, соответствующих алгоритмам обмена Диффи-Хелмана и подписи ГОСТ Р 34.10-2001.

Работа с ключевыми парами (закрытый и открытый ключи) обмена, соответствующими алгоритмам обмена Диффи-Хелмана и подписи ГОСТ Р 34.10-2001

Работа с ключевыми парами обмена в криптопровайдере КриптоПро JCP (модули шифрования) по большей своей части осуществляется через стандартный интерфейс JCA при помощи криптопровайдера КриптоПро JCP, описание которого приводится в Руководстве программиста КриптоПро JCP. Основной класс провайдера КриптоПро JCP (модули шифрования) - ru.CryptoPro.Crypto.CryptoProvider.

Небольшие отличия в использовании интерфейса JCA в криптопровайдерах КриптоПро JCP и КриптоПро JCP (модули шифрования) возникают в процессе генерирования ключевой пары:

  1. Первое отличие возникает в процессе создания генератора ключевой пары. Для генерирования ключевой пары обмена, соответствующей алгоритмам обмена Диффи-Хелмана и подписи ГОСТ Р 34.10-2001, необходимо при создании генератора в качестве имени, идентифицирующего требуемые алгоритмы, указывать имя "GOST3410DH" или JCP.GOST_DH_NAME. Таким образом, в криптопровайдере КриптоПро JCP (модули шифрования) генератор ключевой пары обмена, соответствующей алгоритмам обмена Диффи-Хелмана и подписи ГОСТ Р 34.10-2001 производится одним из следующих способов:
        KeyPairGenerator kg = KeyPairGenerator.getInstance("GOST3410DH");
    
        KeyPairGenerator kg = KeyPairGenerator.getInstance("GOST3410DH", "Crypto");
    
        KeyPairGenerator kg = KeyPairGenerator.getInstance(JCP.GOST_DH_NAME, CryptoProvider.PROVIDER_NAME);
        
  2. Второе отличие возникает в процессе изменения параметров генератора ключевой пары. Также, как и в криптопровайдере КриптоПро JCP, генератор осуществляет создание ключевой пары обмена с параметрами, установленными в контрольной панели (с параметрами по умолчанию). Для того, чтобы изменить набор параметров, в соответствии с которым будет осуществляться создание ключевой пары обмена, следует воспользоваться описанным в документации интерфейсом набора параметров для генерирования ключевой пары AlgIdInterface. В криптопровайдере КриптоПро JCP (модули шифрования) в этот набор параметров входят: Наборы параметров для криптопровайдеров КриптоПро JCP (генерирование ключевой пары подписи) и КриптоПро JCP (модули шифрования) (генерирование ключевой пары обмена) различаются двумя элементами:

К созданным таким способам ключевым парам обмена могут быть применены все операции, реализуемые криптопровайдером КриптоПро JCP (таких как хранение на носителях закрытых ключей и соответствующих им сертификатов, создание ЭЦП по алгоритму ГОСТ Р 34.10-2001, генерирование сертификатов и так далее). Подробное описание реализаций всех операций приводится в Руководстве программиста КриптоПро JCP.

Но помимо этих операций, ключевые пары обмена могут также участвовать в формировании ключей согласования, что не верно для ключей ЭЦП, созданных при помощи криптопровайдера КриптоПро JCP. Таким образом, в рамках криптопровайдера КриптоПро JCP функциональные возможности ключевых пар подписи и обмена одинаковы. В рамках же криптопровайдера КриптоПро JCP (модули шифрования) имеет смысл использование только ключевых пар обмена.

Работа с ключами согласования в соответствии с алгоритмом обмена Диффи-Хелмана

Криптопровайдер КриптоПро JCP (модули шифрования) осуществляет работу с ключами согласования в соответствии с алгоритмом обмена Диффи-Хелмана, через стандартный интерфейс JCE при помощи класса KeyAgreement.

Создание объекта генерирования (генератора) ключей согласования

Объект генерирования ключей согласования (далее генератор) создается посредством вызова метода getInstance() класса KeyAgreement. Этот метод является статическим и возвращает ссылку на класс KeyAgreement, который обеспечивает выполнение требуемой операции.

Для создания генератора ключей согласования в соответствии с алгоритмом обмена Диффи-Хелмана методу getInstance() необходимо в качестве параметра передать имя, идентифицирующее данный алгоритм ("GOST3410DH" или JCP.GOST_DH_NAME). При таком вызове метода getInstance() совместно с определением требуемого алгоритма генерирования ключей согласования осуществляется также определение требуемого типа криптопровайдера (КриптоПро JCP (модули шифрования)). Также стандартный интерфейс JCE позволяет в качестве параметра функции getInstance() класса KeyAgreement вместе с именем алгоритма передавать имя криптопровайдера, используемого для выполнения требуемой операции.

Таким образом, создание генератора ключей обмена в соответствии с алгоритмом Диффи-Хелмана осуществляется одним из следующих способов:

    KeyAgreement ka = KeyAgreement.getInstance("GOST3410DH");

    KeyAgreement ka = KeyAgreement.getInstance("GOST3410DH", "Crypto");

    KeyAgreement ka = KeyAgreement.getInstance(JCP.GOST_DH_NAME, CryptoProvider.PROVIDER_NAME);

Созданный таким образом генератор осуществляет выработку ключей согласования из ключей обмена, соответствующих алгоритмам ГОСТ Р 34.10-94 и ГОСТ Р 34.10-2001 по алгоритму Диффи-Хелмана. Ключи обмена, соответствующие алгоритму ГОСТ Р 34.10-94, могут быть прочитаны из контейнера (см. соответствующий раздел в Руководстве программиста КриптоПро JCP), а ключи обмена, соответствующие алгоритму ГОСТ Р 34.10-2001, могут быть как прочитаны из контейнера, так и получены при помощи генератора ключевой пары обмена (см. выше).

Инициализация генератора ключей согласования

После того, как генератор ключей согласования был создан, необходимо проинициализировать его закрытым ключом обмена, в соответствии с которым будет осуществляться выработка ключей согласования, а также параметрами, на основе которых эта выработка будет производиться. Такая инициализация осуществляется при помощи метода init(Key key, AlgorithmParameterSpec params) класса KeyAgreement. Этому методу в качестве параметра key передается закрытый ключ обмена, соответствующий алгоритму ГОСТ Р 34.10-94 или ГОСТ Р 34.10-2001. В качестве параметров params, участвующих в выработке ключей согласования, передается объект класса IvParameterSpec, представляющий собой стартовый вектор для выработки ключей согласования.

Таким образом, инициализация генератора ключей согласования осуществляется:

    PrivateKey privateKey;  // обязательно закрытый ключ обмена, соответствующий
                            // алгоритму ГОСТ Р 34.10-94 или ГОСТ Р 34.10-2001

    IvParameterSpec spec;   // стартовый вектор

    ka.init(key, spec);

Выполнение фазы согласования ключей

После того, как генератор ключей согласования был создан и проинициализирован закрытым ключом и стартовым вектором, требуется проинициализировать его открытым ключом, в соответствии с которым будет сформирован ключ согласования (фаза согласования ключей). Выполнение фазы осуществляется при помощи метода doPhase(Key key, boolean lastPhase) класса KeyAgreement. Этому методу в качестве параметра передается открытый ключ, соответствующий алгоритму ГОСТ Р 34.10-94 или ГОСТ Р 34.10-2001. Следует помнить, что параметры хеширования и ЭЦП этого ключа должны совпадать с соответствующими параметрами поданного на инициализацию закрытого ключа. Второй параметр метода doPhase() игнорируется. Считается, что эта величина всегда равна true.

    PublicKey publicKey;    // обязательно открытый ключ обмена, соответствующий
                            // закрытому ключу privateKey

    ka.doPhase(publicKey, true);

Стандартный интерфейс JCE допускает возвращение данным методом объекта класса Key. В криптопровайдере КриптоПро JCP (модули шифрования) в качестве такого объекта возвращается переданный методу doPhase() открытый ключ. Для получения самого ключа согласования необходимо сделать еще один шаг.

Генерирование ключа согласования

После того, как определены закрытый и открытый ключи, на основе которых осуществляется выработка ключа согласования, а также параметры (стартовый вектор), участвующие в этой выработке, необходимо сгенерировать собственно ключ согласования. Генерирование такого ключа осуществляется при помощи метода generateSecret(String algorithm) класса KeyAgreement. В качестве параметра этот метода получает строковое представление алгоритма ключа согласования ("GOST28147" или CryptoProvider.GOST_CIPHER_NAME). Возвращает этот метод объект класса SecretKey, представляющий собой ключ согласования закрытого и открытого ключей обмена, который создан при помощи стартового вектора. Этот ключ является ключом шифрования алгоритма ГОСТ 28147-89 с параметрами шифрования, соответствующими параметрам открытого ключа.

Таким образом, генерирование ключа согласования осуществляется:

    SecretKey agreeKey = ka.generateSecret("GOST28147");

    SecretKey agreeKey = ka.generateSecret(CryptoProvider.GOST_CIPHER_NAME);

Пример выработки ключей согласования сторонами см. samples/samples_src.jar/userSamples/CheckImita.java (входит в комплект поставки программного обеспечения КриптоПро JCP).

Работа с симметричными ключами шифрования, соответствующими алгоритму ГОСТ 28147-89

Криптопровайдер КриптоПро JCP (модули шифрования) осуществляет генерирование симметричных ключей шифрования, через стандартный интерфейс JCE при помощи класса KeyGenerator.

Создание объекта генерирования (генератора) симметричных ключей шифрования

Объект генерирования симметричных ключей шифрования (далее генератор) создается посредством вызова метода getInstance() класса KeyGenerator. Этот метод является статическим и возвращает ссылку на класс KeyGenerator, который обеспечивает выполнение требуемой операции.

Для создания генератора симметричных ключей шифрования, соответствующих алгоритму ГОСТ 28147-89 методу getInstance() необходимо в качестве параметра передать имя, идентифицирующее данный алгоритм ("GOST28147" или CryptoProvider.GOST_CIPHER_NAME). При таком вызове метода getInstance() совместно с определением требуемого алгоритма генерирования ключей согласования осуществляется также определение требуемого типа криптопровайдера (КриптоПро JCP (модули шифрования)). Также стандартный интерфейс JCE позволяет в качестве параметра функции getInstance() класса KeyGenerator вместе с именем алгоритма передавать имя криптопровайдера, используемого для выполнения требуемой операции.

Таким образом, создание генератора симметричных ключей шифрования, соответствующих алгоритму ГОСТ 28147-89 осуществляется одним из следующих способов:

    KeyGenerator kg = KeyGenerator.getInstance("GOST28147");

    KeyGenerator kg = KeyGenerator.getInstance("GOST28147", "Crypto");

    KeyGenerator kg = KeyGenerator.getInstance(CryptoProvider.GOST_CIPHER_NAME, CryptoProvider.PROVIDER_NAME);

Генерирование симметричных ключей шифрования при помощи такого генератора kg будет осуществляться в соответствии с алгоритмом ГОСТ 28147-89 и с установленными в контрольной панели параметрами (параметрами по умолчанию). Если существует необходимость использования другого набора параметров (отличного от параметров по умолчанию), то следует установить требуемый набор параметров созданному генератору.

Определение параметров генерирования симметричных ключей шифрования

После того, как генератор симметричных ключей был создан, может возникнуть необходимость установить некий набор параметров генерирования симметричных ключей шифрования, отличный от параметров, установленных в контрольной панели. Операция изменения существующего набора параметров осуществляется при помощи метода init(AlgorithmParameterSpec params) класса KeyGenerator. Этому методу в качестве параметра может быть передан объект следующих двух классов:

В обоих случаях имеют значение лишь параметры шифрования (параметры алгоритма ГОСТ 28147-89), поскольку создаваемый генератором симметричный ключ может быть использован только для шифрования данных (операции создания ЭЦП, выработки ключей согласования и записи его на носитель запрещены).

Таким образом, изменение набора параметров генератора симметричных ключей шифрования производится следующим образом:

    AlgIdInterface keyParams;     // интерфейс набора параметров

    ParamsInterface cryptParams;  // интерфейс параметров шифрования

    kg.init(keyParams);           // установка полного набора параметров

    kg.init(cryptParams);         // установка параметров шифрования

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

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

Генерирование симметричных ключей шифрования, соответствующих алгоритму ГОСТ 28147-89, осуществляется только после создания генератора и, если это необходимо, определения его параметров. Вызов метода generateKey() класса KeyGenerator возвращает ключ шифрования, соответствующий алгоритму ГОСТ 28147-89 и установленному набору параметров (или параметрам по умолчанию):

    SecretKey key = kg.generateKey();

Пример генерирования симметричного ключа шифрования при выполнении операции зашифрования данных см. samples/samples_src.jar/userSamples/SessionEncrypt.java (входит в комплект поставки программного обеспечения КриптоПро JCP).

Имитозащита данных в соответствии с алгоритмом ГОСТ 28147-89

Криптопровайдер КриптоПро JCP (модули шифрования) осуществляет имитозащиту данных в соответствии с алгоритмом ГОСТ 28147-89, через стандартный интерфейс JCE при помощи класса Mac.

Создание объекта имитозащиты данных

Объект имитозащиты данных в соответствии с алгоритмом ГОСТ 28147-89 создается посредством вызова метода getInstance() класса Mac. Этот метод является статическим и возвращает ссылку на класс Mac, который обеспечивает выполнение требуемой операции.

Для создания объекта имитозащиты в соответствии с алгоритмом ГОСТ 28147-89 методу getInstance() необходимо в качестве параметра передать имя, идентифицирующее данный алгоритм ("GOST28147" или CryptoProvider.GOST_CIPHER_NAME). При вызове метода getInstance() совместно с определением требуемого алгоритма имитозащиты данных осуществляется также определение требуемого типа криптопровайдера (КриптоПро JCP (модули шифрования)). Также стандартный интерфейс JCE позволяет в качестве параметра функции getInstance() класса Mac вместе с именем алгоритма указывать имя криптопровайдера, используемого для выполнения требуемой операции.

Таким образом, создание объекта имитозащиты данных осуществляется одним из следующих способов:

    Mac mac = Mac.getInstance("GOST28147");

    Mac mac = Mac.getInstance("GOST28147", "Crypto");

    Mac mac = Mac.getInstance(CryptoProvider.GOST_CIPHER_NAME, CryptoProvider.PROVIDER_NAME);

Инициализация объекта имитозащиты данных и определение его параметров

После того, как объект имитозащиты данных был создан, необходимо определить набор параметров алгоритма ГОСТ 28147-89, в соответствии с которыми будет осуществляться операция имитозащиты. Определение параметров алгоритма осуществляется во время инициализации операции имитозащиты данных методом init() класса Mac одним из следующих способов:

В обоих случаях передаваемый ключ key используется в процессе выработки имитовставки.

Существуют некоторые ограничения на параметры, передаваемые функции init(). В обоих способах вызова этой функции ключ key должен соответствовать типу SecretKey и удовлетворять алгоритму шифрования ГОСТ 28147-89 (такие ключи могут быть получены при помощи операции согласования ключей или при помощи генерирования симметричных ключей шифрования). Необходимо также, чтобы параметры, передаваемые функции init() во втором способе ее вызова соответствовали интерфейсу ParamsInterface параметров алгоритма шифрования ГОСТ 28147-89 (см. Работа с параметрами алгоритма шифрования ГОСТ 28147-89).

Таким образом, инициализация операции имитозащиты данных, во время которой происходит определение параметров имитовставки, осуществляется одним из следующих способов:

    ParamsInterface cryptParams;    // интерфейс параметров шифрования

    SecretKey key;                  // обязательно ключ шифрования с алгоритмом "GOST28147"
                                    // (соответствующий алгоритму ГОСТ 28147-89)
    mac.init(key);
    mac.init(key, cryptParams);

Копирование объекта имитозащиты данных

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

Для этих целей используется метод clone() класса Mac, который возвращает точную копию существующего объекта имитозащиты. Этот метод может быть вызван на любом этапе выполнения операции выработки имитовставки после того, как объект имитозащиты был проинициализирован и до того, как операция имитозащиты данных была завершена.

Использование метода клонирования объекта имитозащиты данных в следующем примере samples/samples_src.jar/userSamples/CloneImita.java (входит в комплект поставки программного обеспечения КриптоПро JCP).

Выработка имитовставки данных

После того, как объект имитозащиты был создан и проинициализирован, выработка имитовставки данных в соответствии с алгоритмом ГОСТ 28147-89 производится в два этапа: обработка данных и последующее вычисление значения имитовставки, завершающее операцию имитозащиты данных.

Обработка защищаемых данных

Обработка защищаемых данных осуществляется при помощи метода update() класса Mac. Этот метод осуществляет обработку защищаемых данных, представленных в виде байтового массива и подаваемых ему в качестве параметра. Существует 3 варианта обработки байтового массива данных при помощи этого метода:

  1. Последовательная обработка каждого байта данных (при этом количество вызовов метода update(byte b) равно длине массива данных):
        byte[] data;
        for(int i = 0; i < data.length; i++)
            mac.update(data[i]);
        
  2. Блочная обработка данных (данные обрабатываются блоками определенной длины):
        byte[] data;
        int BLOC_LEN = 1024;
    
        //если длина исходных данных меньше длины блока
        if(data.length/BLOC_LEN == 0)
            mac.update(data);
        else {
            //цикл по блокам
            for (int i = 0; i < data.length/BLOC_LEN; i++) {
                byte[] bloc = new byte[BLOC_LEN];
                for(int j = 0; j < BLOC_LEN; j++) 
                    bloc[j] = data[j + i * BLOC_LEN];
                mac.update(bloc);
            }
    
            //обработка остатка
            byte[] endBloc = new byte[data.length % BLOC_LEN];
            for(int j = 0; j < data.length % BLOC_LEN; j++)
                endBloc[j] = data[j + data.length - data.length % BLOC_LEN];
            mac.update(endBloc);
        }
        
  3. Обработка данных целиком:
        byte[] data;
        mac.update(data);
        

Допускается комбинирование первого и второго варианта, обработка блоками различной длины, а также использование метода update(byte[]data, int offset, int len) - обработка массива данных со смещением.

Вычисление значения имитовставки

Вычисление значения имитовставки осуществляется при помощи метода doFinal() класса Mac. Существуют различные варианты вызова данного метода. Если обработке подверглись все защищаемые данные, то остается только получить значение имитовставки. Получить это значение можно двумя способами:

  1. Вызов метода без параметров - doFinal(). В этом случае метод возвращает байтовый массив, содержащий значение имитовставки;
  2. Вызов метода с параметрами - doFinal(byte[] buf, int offset). В этом случае метод записывает значение имитовставки в передаваемый ему массив со смещением.

Если же часть данных осталось не обработанной, то следует предварительно обработать ее, а лишь потом получать значение имитовставки. Для этих целей используется функция doFinal(byte[] buf), обрабатывающая переданные в массиве buf данные и возвращающая байтовый массив, содержащий значение имитовставки.

Пример создания и проверки имитовставки на ключах согласования сторон см. samples/samples_src.jar/userSamples/CheckImita.java (входит в комплект поставки программного обеспечения КриптоПро JCP).

Использование алгоритма HMAC

С помощью криптопровайдера КриптоПро JCP можно осуществлять защиту данных в соответствии с алгоритмом HMAC_GOSTR3411. Стандарт HMAC_GOSTR3411 описан в документе rfc4357, который базируется на стандарте rfc2104. OID "1.2.643.2.2.10" для алгоритма определен в rfc4490

Работать с реализацией алгоритма можно через стандартный интерфейс JCE при помощи класса Mac Использование HMAC_GOSTR3411 аналогично работе с имитозащитой по алгоритму ГОСТ 28147-89, только при создании объекта в качестве имени надо указывать "HMAC_GOSTR3411" Примеры создания объекта:

    Mac mac = Mac.getInstance("HMAC_GOSTR3411");

    Mac mac = Mac.getInstance("HMAC_GOSTR3411", "Crypto");

    Mac mac = Mac.getInstance(ru.CryptoPro.Crypto.Cipher.GostHMAC.STR_NAME, CryptoProvider.PROVIDER_NAME);

    Mac mac = Mac.getInstance("1.2.643.2.2.10", "Crypto");

Шифрование данных и ключей в соответствии с алгоритмом ГОСТ 28147-89

Криптопровайдер КриптоПро JCP (модули шифрования) осуществляет шифрование данных и ключей в соответствии с алгоритмом ГОСТ 28147-89, через стандартный интерфейс JCE при помощи класса Cipher.

Создание объекта шифрования данных и ключей (шифратора)

Объект шифрования данных и ключей (далее шифратор) в соответствии с алгоритмом ГОСТ 28147-89 создается посредством вызова метода getInstance() класса Cipher. Этот метод является статическим и возвращает ссылку на класс Cipher, который обеспечивает выполнение требуемой операции.

Следуя интерфейсу класса Cipher, методу getInstance() в качестве параметра следует передавать строковое представление алгоритма шифратора вида "algorithm/mode/padding" либо "algorithm". Ниже описаны допустимые варианты значений каждого из элементов такого строкового представления.

  1. в качестве элемента "algorithm" указывается собственно алгоритм шифрования. Алгоритм ГОСТ 28147-89 идентифицируется именем "GOST28147" или CryptoProvider.GOST_CIPHER_NAME.
  2. в качестве элемента "mode" указывается режим шифрования. В криптопровайдере КриптоПро JCP (модули шифрования) допустимы следующие режимы:

    Если элемент "mode" отсутствует (т.е. в качестве строкового представления алгоритма шифратора указан лишь алгоритм шифрования), то при осуществлении последующей операции шифрования будет использован режим по умолчанию: для операций шифрования данных (см. ниже) используется режим "CFB", для операций шифрования ключей (см. ниже) - режим "SIMPLE_EXPORT".

  3. в качестве элемента "padding" указывается алгоритм заполнения последнего неполного блока данных при выполнении операции блочного шифрования. В криптопровайдере КриптоПро JCP (модули шифрования) допустимы следующие алгоритмы:

    Если элемент "padding" отсутствует (т.е. в качестве строкового представления алгоритма шифратора указан лишь алгоритм шифрования), то при осуществлении последующей операции шифрования будет использован алгоритм "NoPadding".

    Следует помнить, что установление отличного от "NoPadding" алгоритма заполнения имеет смысл только при выполнении операций блочного шифрования (таких как "ECB" и "CBC"). Если операция шифрования поточная ("CNT" или "CFB"), то установленный режим заполнения будет игнорироваться. В случае выполнения блочного зашифрования отсутствие заполнения ("NoPadding") допускается только когда размер всего массива входных данных кратен длине блока. Если общий размер данных не кратен длине блока шифрования и при этом алгоритм заполнения не установлен, то при обработке последнего (неполного) блока данных будет выброшено исключение.

При вызове метода getInstance() со строковым представлением алгоритма, состоящем из перечисленных выше допустимых значений имени алгоритма, режима шифрования и алгоритма заполнения последнего неполного блока, помимо определения в соответствии с этим строковым представлением алгоритма работы шифратора осуществляется также определение требуемого типа криптопровайдера (КриптоПро JCP (модули шифрования)). Также стандартный интерфейс JCE позволяет в качестве параметра функции getInstance() класса Cipher вместе с именем алгоритма указывать имя криптопровайдера, используемого для выполнения требуемой операции. Таким образом, создание, например, объекта шифрования данных в соответствии с алгоритмом ГОСТ 28147-89 в режиме простой замены с зацеплением с алгоритмом PKCS5 заполнения последнего неполного блока осуществляется одним из следующих способов:

    Cipher cipher = Cipher.getInstance("GOST28147/CBC/PKCS5_PADDING");

    Cipher cipher = Cipher.getInstance("GOST28147/CBC/PKCS5_PADDING", "Crypto");

Инициализация шифратора и определение его параметров

После того, как шифратор был создан, необходимо определить собственно метод шифрования и набор параметров, в соответствии с которым будет осуществляться операция шифрования. Инициализация шифратора осуществляется посредством вызова метода init() класса Cipher. Вызов данного метода может быть осуществлен двумя способами:

Ниже описываются особенности каждого из этих способов для криптопровайдера КриптоПро JCP (модули шифрования).

В обоих случаях необходимо следить за согласованностью параметров шифрования (узла шифрования), а также вектора инициализации при выполнении соответствующих друг другу операций зашифрования и расшифрования. Так, например, если инициализация операции зашифровании данных производилась без передачи вектора инициализации, то созданный в процессе выполнения этой операции вектор инициализации следует передать вместе с зашифрованным текстом для корректного выполнения операции расшифрования. Получить вектор инициализации можно при помощи метода getIV(), возвращающего его в виде байтового массива. Аналогичные действия следует производить в случае зашифрования ключа на симметричном ключе шифрования, полученным при помощи генерирования. Необходимо помнить, что вызов этой функции следует производить только после того, как шифратор был проинициализирован, и до того как операция зашифрования была завершена.

Таким образом, инициализация, соответствующих друг другу операций зашифрования и расшифрования данных для алгоритма ГОСТ 28147-89 может быть осуществлена следующим образом:

    SecretKey key;    // обязательно ключ шифрования с алгоритмом "GOST28147"
                      // (соответствующий алгоритму ГОСТ 28147-89)
                      // считаем, что известен обоим сторонам

    /*Зашифрование*/

    // инициализация операции зашифрования. Вектор будет сгенерирован
    // в процессе выполнения операции
    cipher.init(Cipher.ENCRYPT_MODE, key);

    // получение сгенерированного вектора инициализации
    byte[] iv = cipher.getIV();

    /*Расшифрование*/

    // создание параметров, содержащих требуемый вектор
    IvParameterSpec spec = new IvParameterSpec(iv);

    // инициализация операции расшифрования с тем же
    // ключом и вектором
    cipher.init(Cipher.DECRYPT_MODE, key, spec);

Зашифрование и расшифрование данных

После того, как шифратор был создан и проинициализирован методом шифрования данных (ENCRYPT_MODE или DECRYPT_MODE), операция зашифрования (расшифрования) данных производится в два этапа: обработка данных и последующее завершение операции.

Последовательное зашифрование (расшифрование) данных

Последовательное зашифрование (расшифрование) данных осуществляется при помощи метода update() класса Cipher. Этот метод выполняет последовательное зашифрование (расшифрование) данных, представленных в виде байтового массива и подаваемых ему в качестве параметра. Существует четыре способа вызова метода:

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

Завершение операции зашифрования (расшифрования)

Завершение операции зашифрования (расшифрования) данных осуществляется при помощи метода doFinal() класса Cipher. Даже если все входные данные были поданы на последовательное шифрование, то это не гарантирует того, что результат шифрования был выдан полностью. Такое, например, возможно при блочном зашифровании данных, длина которых не кратна длине блока. Ввиду этого операцию шифрования следует завершить (для получения последней части результата шифрования, либо же для обработки и получения конечного результата еще не обработанных входных данных).

Если в процессе последовательного шифрования все входные данные были поданы на зашифрование (расшифрование), то завершить операцию шифрования можно двумя способами:

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

Примеры зашифрования и расшифрования данных входят в комплект поставки программного обеспечения КриптоПро JCP: samples/samples_src.jar/userSamples/SessionEncrypt.java - пример шифрования данных на симметричном ключе (соответственно, с зашифрованием этого ключа для передачи его противоположной стороне),
samples/samples_src.jar/userSamples/ClassicEncrypt.java - пример шифрования данных по классической схеме (на ключах согласования противоположных сторон).

Зашифрование и расшифрование ключей

После того, как шифратор был создан и проинициализирован методом шифрования ключа (WRAP_MODE или UNWRAP_MODE), выполняется собственно операция зашифрования или расшифрования ключа.

Зашифрование ключа

Операция зашифрования ключа выполняется методом wrap(Key key) класса Cipher. В качестве параметра данному методу подается ключ key, который подлежит зашифрованию. Зашифрование переданного ключа производится на ключе, которым был проинициализирован шифратор. Криптопровайдер КриптоПро JCP (модули шифрования) допускает зашифрование только следующих типов ключей:

Зашифрованный ключ возвращается в виде байтового массива.

Расшифрование ключа

Операция расшифрования ключа выполняется методом unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, int wrappedKeyType) класса Cipher. Этот метод возвращает расшифрованный ключ. В качестве параметра данному методу передается зашифрованный ключ wrappedKey, представленный в виде байтового массива. Параметр wrappedKeyAlgorithm в криптопровайдере КриптоПро JCP (модули шифрования) не используется. Расшифрование ключа производится на ключе, которым был проинициализирован шифратор. Криптопровайдер КриптоПро JCP (модули шифрования) допускает расшифрование только симметричных ключей шифрования (соответствующих типу SecretKey и удовлетворяющих алгоритму шифрования ГОСТ 28147-89. Ввиду этого в качестве параметра wrappedKeyType допускает использование только типа ключа, соответствующего классу SecretKey. Тип такого ключа определяется константой SECRET_KEY класса Cipher.

Пример зашифрования и расшифрования симметричного ключа, на котором осуществляется зашифрования и расшифрование данных см. samples/samples_src.jar/userSamples/SessionEncrypt.java (входит в комплект поставки программного обеспечения КриптоПро JCP).

Примеры зашифрования/расшифрования сессионного ключа и текста на нем, совместимые с примерами зашифрования/расшифрования с использованием КриптоПро CSP см. samples/samples_src.jar/Crypt_samples (входит в комплект поставки программного обеспечения КриптоПро JCP).

Шифрование XML-документов

Использование криптопровайдера КриптоПро JCP совместно с библиотекой Apache XML Security позволяет шифровать XML-документы по алгоритму ГОСТ 28147-89. Описание совместной работы JCP с библиотекой XML Security и способы регистрации ГОСТ алгоритмов приводятся в документе Руководство программиста КриптоПро JCP

Константы, задающие имена алгоритмов, определены в файле ru.CryptoPro.JCPxml.Consts

        
/**
 * алгоритм шифрования данных
 */
public static final String URI_GOST_CIPHER =
        "urn:ietf:params:xml:ns:cpxmlsec:algorithms:gost28147";
/**
 * URI алгоритма шифрования ключа
 */
public static final String URI_GOST_TRANSPORT =
        "urn:ietf:params:xml:ns:cpxmlsec:algorithms:transport-gost2001";

Пример CryptXML шифрования XML-документа входит в комплект поставки программного обеспечения КриптоПро JCP samples/samples_src.jar/xmlSign/.