127018, Москва, ул.Сущевский Вал д.16 стр.5 Тел./факс: +7 (495) 780 4820 +7 (495) 660 2330 сайт: http://www.cryptopro.ru e-mail: info@cryptopro.ru |
|
|
Описание стандартного интерфейса JCE. Описание основной функциональности криптопровайдера КриптоПро JCP Связь с разработчиком. |
Настоящее руководство содержит описание основной функциональности криптопровайдера КриптоПро 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 (модули шифрования) осуществляется в соответствии с интерфейсами JCE. К ним относятся выработка ключей согласования по алгоритму Диффи-Хелмана, генерирование симметричных ключей шифрования. Но существуют также методы, работающие с ключами через интерфейс JCA. К ним относятся генерирование ключевых пар обмена, соответствующих алгоритмам обмена Диффи-Хелмана и подписи ГОСТ Р 34.10-2001.
Работа с ключевыми парами обмена в криптопровайдере КриптоПро JCP (модули шифрования) по большей своей части осуществляется через стандартный интерфейс JCA при помощи криптопровайдера КриптоПро JCP, описание которого приводится в Руководстве программиста КриптоПро JCP. Основной класс провайдера КриптоПро JCP (модули шифрования) - ru.CryptoPro.Crypto.CryptoProvider.
Небольшие отличия в использовании интерфейса JCA в криптопровайдерах КриптоПро JCP и КриптоПро JCP (модули шифрования) возникают в процессе генерирования ключевой пары:
KeyPairGenerator kg = KeyPairGenerator.getInstance("GOST3410DH"); KeyPairGenerator kg = KeyPairGenerator.getInstance("GOST3410DH", "Crypto"); KeyPairGenerator kg = KeyPairGenerator.getInstance(JCP.GOST_DH_NAME, CryptoProvider.PROVIDER_NAME);
AlgIdSpec
, получающего ссылку на интерфейс параметров подписи по умолчанию,
следует пользоваться методом getDefaultExchangeParams() того же класса.
Этот метод возвращает ссылку на интерфейс ParamsInterface
параметров
обмена по умолчанию (установленных в контрольной панели):
ParamsInterface exchParams = AlgIdSpec.getDefaultExchangeParams();Остальные действия могут быть проведены аналогичным с параметрами подписи образом.
К созданным таким способам ключевым парам обмена могут быть применены все операции, реализуемые криптопровайдером КриптоПро 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).
Криптопровайдер КриптоПро 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. Этому методу в качестве параметра может быть передан объект следующих двух классов:
AlgIdInterface
(определяет набор параметров
для генерирования ключевой пары обмена, но может быть использован и для генерирования симметричных
ключей шифрования. В этом случае из передаваемого набора параметров в процессе генерирования
будут использованы лишь параметры шифрования.
См. Работа с набором параметров для генерирования ключей ЭЦП
с замечаниями, описанными выше);ParamsInterface
параметров алгоритма
шифрования ГОСТ 28147-89
(см. Работа с параметрами алгоритма шифрования ГОСТ 28147-89).В обоих случаях имеют значение лишь параметры шифрования (параметры алгоритма ГОСТ 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).
Криптопровайдер КриптоПро 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
;params
.В обоих случаях передаваемый ключ 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 варианта обработки байтового массива данных при помощи этого метода:
byte[] data; for(int i = 0; i < data.length; i++) mac.update(data[i]);
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); }
byte[] data; mac.update(data);
Допускается комбинирование первого и второго варианта, обработка блоками различной длины, а также использование метода update(byte[]data, int offset, int len) - обработка массива данных со смещением.
Вычисление значения имитовставки осуществляется при помощи метода doFinal() класса Mac. Существуют различные варианты вызова данного метода. Если обработке подверглись все защищаемые данные, то остается только получить значение имитовставки. Получить это значение можно двумя способами:
Если же часть данных осталось не обработанной, то следует предварительно обработать
ее, а лишь потом получать значение имитовставки. Для этих целей используется
функция doFinal(byte[] buf), обрабатывающая переданные в массиве buf
данные и возвращающая байтовый массив, содержащий значение имитовставки.
Пример создания и проверки имитовставки на ключах согласования сторон см. samples/samples_src.jar/userSamples/CheckImita.java
(входит в комплект поставки программного обеспечения КриптоПро JCP).
С помощью криптопровайдера КриптоПро 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");
Криптопровайдер КриптоПро JCP (модули шифрования) осуществляет шифрование данных и ключей в соответствии с алгоритмом ГОСТ 28147-89, через стандартный интерфейс JCE при помощи класса Cipher.
Объект шифрования данных и ключей (далее шифратор) в соответствии с алгоритмом ГОСТ 28147-89 создается посредством вызова метода getInstance() класса Cipher. Этот метод является статическим и возвращает ссылку на класс Cipher, который обеспечивает выполнение требуемой операции.
Следуя интерфейсу класса Cipher, методу getInstance() в качестве параметра следует передавать строковое представление алгоритма шифратора вида "algorithm/mode/padding" либо "algorithm". Ниже описаны допустимые варианты значений каждого из элементов такого строкового представления.
Если элемент "mode" отсутствует (т.е. в качестве строкового представления алгоритма шифратора указан лишь алгоритм шифрования), то при осуществлении последующей операции шифрования будет использован режим по умолчанию: для операций шифрования данных (см. ниже) используется режим "CFB", для операций шифрования ключей (см. ниже) - режим "SIMPLE_EXPORT".
Если элемент "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 (модули шифрования).
opmode
передается
число, определяющее собственно метод шифрования. Криптопровайдер КриптоПро JCP (модули шифрования) поддерживает
четыре метода шифрования, определяемых следующим образом:
ENCRYPT_MODE
класса Cipher);DECRYPT_MODE
класса Cipher);WRAP_MODE
класса Cipher);UNWRAP_MODE
класса Cipher);key
передается ключ, на котором будет производится
указанная операция шифрования. Требуется, чтобы этот ключ являлся объектом типа
SecretKey и удовлетворял
алгоритму шифрования ГОСТ 28147-89 (такие ключи могут быть получены при помощи операции
согласования ключей или при помощи генерирования симметричных ключей шифрования).key
;ENCRYPT_MODE
) в режиме,
требующем вектора инициализации
(такими режимами являются "CBC", "CFB" и "CNT") вектор инициализации будет выработан
случайным образом;DECRYPT_MODE
) в режиме,
требующем вектора инициализации
(такими режимами являются "CBC", "CFB" и "CNT") будет выдано исключение;WRAP_MODE
или UNWRAP_MODE
)
ключом key
, полученным при помощи операции согласования ключей,
необходимый для дальнейшего выполнения операции шифрования вектор инициализации будет пронаследован
от стартового вектора, который участвовал в процессе создания ключа согласования key
;WRAP_MODE
)
ключом key
, полученным при помощи генерирования симметричных ключей шифрования,
необходимый для дальнейшего выполнения операции шифрования вектор инициализации будет выработан
случайным образом;UNWRAP_MODE
)
ключом key
, полученным при помощи генерирования симметричных ключей шифрования,
будет выдано исключение.params
, определяющие работу шифратора. В качестве
таких параметров в криптопровайдере КриптоПро JCP (модули шифрования) допускается передавать
объекты следующих типов:
ParamsInterface
параметров алгоритма
шифрования ГОСТ 28147-89 (описание работы с этим интерфейсом приводится
в соответствующем разделе
документации по криптопровайдеру КриптоПро JCP).
Таким образом, объект типа ParamsInterface
, передаваемый в качестве
параметров params
определяет параметры шифрования (узел замены)params
определяет
вектор инициализации.GostCipherSpec
- этот класс представляет собой набор параметров
алгоритма ГОСТ 28147-89, а также вектор инициализации шифратора,
и является реализацией стандартного класса
AlgorithmParameterSpec.
Создание объекта класса GostCipherSpec
в соответствии с требуемыми параметрами (узлом)
шифрования и вектором инициализации
производится следующим образом:
ParamsInterface cryptParams; // интерфейс параметров шифрования byte[] iv; //вектор инициализации GostCipherSpec spec = new GostCipherSpec(iv, cryptParams);Таким образом, объект типа
GostCipherSpec
, передаваемый в качестве
параметров params
определяет параметры шифрования (узел замены) и
вектор инициализации.params
для
второго способа вызова функции init(int opmode, Key key, AlgorithmParameterSpec params)
возникают следующие особенностями такого вызова функции:
params
объекта интерфейса параметров шифрования ParamsInterface
или класса GostCipherSpec
), то они и будут использованы в процессе
выполнения операции шифрования. В противном случае, параметры шифрования
определяются в соответствии с параметрами
шифрования передаваемого ключа key
;params
объекта класса IvParameterSpec
или
класса GostCipherSpec
), то он и будет использован в процессе
выполнения операции шифрования. В противном случае:
ENCRYPT_MODE
) в режиме,
требующем вектора инициализации
(такими режимами являются "CBC", "CFB" и "CNT") вектор инициализации будет сгенерирован
случайным образом;DECRYPT_MODE
) в режиме,
требующем вектора инициализации
(такими режимами являются "CBC", "CFB" и "CNT") будет выдано исключение;WRAP_MODE
или UNWRAP_MODE
)
ключом key
, полученным при помощи операции согласования ключей,
необходимый для дальнейшего выполнения операции шифрования вектор инициализации будет пронаследован
от стартового вектора, который участвовал в процессе создания ключа согласования key
;WRAP_MODE
)
ключом key
, полученным при помощи генерирования симметричных ключей шифрования,
необходимый для дальнейшего выполнения операции шифрования вектор инициализации будет выработан
случайным образом;UNWRAP_MODE
)
ключом key
, полученным при помощи генерирования симметричных ключей шифрования,
будет выдано исключение.В обоих случаях необходимо следить за согласованностью параметров шифрования (узла шифрования), а также вектора инициализации при выполнении соответствующих друг другу операций зашифрования и расшифрования. Так, например, если инициализация операции зашифровании данных производилась без передачи вектора инициализации, то созданный в процессе выполнения этой операции вектор инициализации следует передать вместе с зашифрованным текстом для корректного выполнения операции расшифрования. Получить вектор инициализации можно при помощи метода 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. Этот метод выполняет последовательное зашифрование (расшифрование) данных, представленных в виде байтового массива и подаваемых ему в качестве параметра. Существует четыре способа вызова метода:
input
. Результат шифрования выдается
в качестве байтового массива;input
, начиная с позиции inputOffset
в количестве inputLen
байт. Результат шифрования выдается
в качестве байтового массива;input
, начиная с позиции inputOffset
в количестве inputLen
байт. Результат шифрования записывается
в массив output
. Такой вызов функции возвращает количество записанных в выходной
буфер байт;input
, начиная с позиции inputOffset
в количестве inputLen
байт. Результат шифрования записывается
в массив output
, начиная с позиции outputOffset
.
Такой вызов функции возвращает количество записанных в выходной
буфер байт;Допускается комбинирование этих методов, причем подаваемые на каждый вызов функции update() массивы зашифровываемых (расшифровываемых) данных могут быть разной длины.
Завершение операции зашифрования (расшифрования) данных осуществляется при помощи метода doFinal() класса Cipher. Даже если все входные данные были поданы на последовательное шифрование, то это не гарантирует того, что результат шифрования был выдан полностью. Такое, например, возможно при блочном зашифровании данных, длина которых не кратна длине блока. Ввиду этого операцию шифрования следует завершить (для получения последней части результата шифрования, либо же для обработки и получения конечного результата еще не обработанных входных данных).
Если в процессе последовательного шифрования все входные данные были поданы на зашифрование (расшифрование), то завершить операцию шифрования можно двумя способами:
Если же не все входные данные были поданы на последовательное шифрование, то следует обработать оставшиеся данные, и лишь потом завершать операцию шифрования для получения конечного результата. Для этих целей может быть использовано несколько вариантов вызова функции doFinal:
input
и выдает окончательный результат
шифрования в виде байтового массива;input
, начиная с позиции inputOffset
в количестве inputLen
и выдает окончательный результат
шифрования в виде байтового массива;input
, начиная с позиции inputOffset
в количестве inputLen
и записывает окончательный результат
шифрования в массив output
. При этом метод возвращает количество записанных
в выходной буфер байт;input
, начиная с позиции inputOffset
в количестве inputLen
и записывает окончательный результат
шифрования в массив output
, начиная с позиции outputOffset
.
При этом метод возвращает количество записанных
в выходной буфер байт.Примеры зашифрования и расшифрования данных входят в комплект поставки программного обеспечения КриптоПро 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).
Использование криптопровайдера КриптоПро 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/
.