Статус: Новичок
Группы: Участники
Зарегистрирован: 22.02.2018(UTC) Сообщений: 3 ![Российская Федерация Российская Федерация](/forum2/Content/images/flags/RU.png)
|
Добрый день! В реализации КриптоПро JCP 2.0.39014 и 2.0.39442 имеется расхождение с документацией в инициализации шифратора GOST28147. В соответствии с документацией КриптоПро "ЖТЯИ.00091-01 33 02. Руководство программиста (модули шифрования)", раздел "4.2. Инициализация шифратора и определение его параметров": Цитата:во втором способе вызова функции init(int opmode, Key key, AlgorithmParameterSpec params) передаются параметры params, определяющие работу шифратора. В качестве таких параметров в криптопровайдере «КриптоПро JCP» версия 2.0 (модули шифрования) допускается передавать объекты следующих типов: ...GostCipherSpec - этот класс представляет собой набор параметров алгоритма ГОСТ 28147-89, а также вектор инициализации шифратора... Таким образом, объект типа GostCipherSpec, передаваемый в качестве параметров params определяет параметры шифрования (узел замены) и вектор инициализации. ...если параметры алгоритма шифрования (узел замены) заданы (в случае передачи в качестве параметров params объекта интерфейса параметров шифрования ParamsInterface или класса GostCipherSpec), то они и будут использованы в процессе выполнения операции шифрования. В противном случае, параметры шифрования определяются в соответствии с параметрами шифрования передаваемого ключа key; В действительности, вопреки документации, параметры алгоритма шифрования (узел замены), передаваемые в метод Cipher.init в GostCipherSpec, игнорируются, и вместо них используются параметры алгоритма шифрования (узел замены), заданные в ключе (параметр key метода init). Где имеет место ошибка - в документации или в реализации? Исходный код, демонстрирующий описанное поведение: Цитата: import java.util.Arrays;
import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec;
import ru.CryptoPro.Crypto.Key.GostSecretKey; import ru.CryptoPro.JCP.params.CryptParamsSpec; import ru.CryptoPro.JCP.params.ParamsInterface; import ru.CryptoPro.JCP.spec.GostCipherSpec;
public class CipherInitBug {
public static void main(String[] args) throws Exception { KeyGenerator keyGenerator = KeyGenerator.getInstance ("GOST28147", "Crypto"); ParamsInterface encryptKeyParams = CryptParamsSpec.getInstance(CryptParamsSpec.TC26_A);
keyGenerator.init (encryptKeyParams);
// Для шифрования данных используем ключ с параметрами алгоритма шифрования (узлом замены) TC26_A. SecretKey encryptKey = keyGenerator.generateKey ();
// Выводит: ru.CryptoPro.JCP.params.CryptParamsSpec: 1.2.643.2.2.31.12 System.out.println("Encryption key params: " + ((GostSecretKey) encryptKey).getSpec().getParams());
byte[] clearText = new byte[2048]; for (int i = 0; i < clearText.length; i++) { clearText[i] = (byte) (i % 256); }
Cipher encryptCipher = Cipher.getInstance ("GOST28147/CFB/NoPadding", "Crypto"); encryptCipher.init (Cipher.ENCRYPT_MODE, encryptKey);
byte[] textIV = encryptCipher.getIV (); byte[] cipherText = encryptCipher.doFinal (clearText, 0, clearText.length);
// Для шифрования ключа используем параметры алгоритма шифрования (узел замены), // отличные от параметров для шифрования данных, чтобы они были установлены по умолчанию // в расшифровавнном ключе шифрования данных. ParamsInterface wrapKeyParams = CryptParamsSpec.getInstance(CryptParamsSpec.TC26_B);
keyGenerator.init (wrapKeyParams);
SecretKey wrapKey = keyGenerator.generateKey ();
Cipher wrapCipher = Cipher.getInstance ("GOST28147/CFB/NoPadding", "Crypto"); wrapCipher.init (Cipher.WRAP_MODE, wrapKey);
byte[] keyIV = wrapCipher.getIV(); byte[] wrappedKey = wrapCipher.wrap(encryptKey);
Cipher unwrapCipher = Cipher.getInstance ("GOST28147/CFB/NoPadding", "Crypto"); unwrapCipher.init (Cipher.UNWRAP_MODE, wrapKey, new IvParameterSpec(keyIV));
// В расшифрованном ключе установлены параметры алгоритма шифрвоания (узел замены) TC26_B. SecretKey decryptKey = (SecretKey) unwrapCipher.unwrap(wrappedKey, "GOST28147", Cipher.SECRET_KEY);
// Выводит: 1.2.643.2.2.31.13 System.out.println("Unwrapped key params: " + ((GostSecretKey) decryptKey).getSpec().getParams());
// Данные были зашифрованы с параметрами TC26_A, с этими же параметрами будем инициализировать шифратор для дешифровки. GostCipherSpec decryptSpec = new GostCipherSpec(textIV, encryptKeyParams);
Cipher decryptCipher = Cipher.getInstance ("GOST28147/CFB/NoPadding", "Crypto");
// Вопреки документации "ЖТЯИ.00091-01 33 02. Руководство программиста (модули шифрования)", // раздел "4.2. Инициализация шифратора и определение его параметров", // Cipher.init игнорирует параметры алгоритма шифрования (узел замены), передаваемые в GostCipherSpec (TC26_A). // Вместо них используются параметры алгоритма шифрования из ключа decryptKey (TC26_B). decryptCipher.init (Cipher.DECRYPT_MODE, decryptKey, decryptSpec);
byte[] decryptedText = decryptCipher.doFinal (cipherText, 0, cipherText.length);
// Выводит: false. Расшифрованные данные не совпадают с зашифрованными, // т.к. при расшифровке использовался некорректный узел замены. System.out.println("Are decrypted data the same as the original one? " + Arrays.equals(clearText, decryptedText));
// В качестве обходного решения проблемы зададим нужные параметры алгоритма шифрования непосредственно на ключе. ((GostSecretKey) decryptKey).getSpec().setParams(encryptKeyParams);
// Выводит: ru.CryptoPro.JCP.params.CryptParamsSpec: 1.2.643.2.2.31.12 System.out.println("Adjusted key params: " + ((GostSecretKey) decryptKey).getSpec().getParams());
decryptCipher.init (Cipher.DECRYPT_MODE, decryptKey, decryptSpec);
byte[] decryptedText2 = decryptCipher.doFinal (cipherText, 0, cipherText.length);
// Выводит: true. После задания нужных параметров алгоритма шифрования непосредственно на ключе // данные расшифровались корректно. System.out.println("Are decrypted data the same as the original one? " + Arrays.equals(clearText, decryptedText2)); }
}
|