Jump to content
evgenyshevnin

Расшифрование данных. ГОСТ 28147-89.

Recommended Posts

Добрый день!

Пытаюсь расшифровать файл, который был зашифрован с помощью Vipnet CryptoFile по алгоритму "ГОСТ 28147-89", и имеющий контейнер закрытого ключа с алгоритмом "ГОСТ Р 34.10-2001 DH". Интересно что делаю не так? Может необходимо вызывать другие алгоритмы расшифрования или с другими параметрами?

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

"java.security.InvalidKeyException: Unsupported key!ru.infotecs.crypto.gost3410.GostR341001PrivateKey
    at ru.infotecs.crypto.gost28147.h.engineGetKeySize(Unknown Source)
    at javax.crypto.Cipher.passCryptoPermCheck(Cipher.java:1052)
    at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1023)
    at javax.crypto.Cipher.init(Cipher.java:1345)
    at javax.crypto.Cipher.init(Cipher.java:1282)
    at ru.it.npf.vipnet.utils.CipherUtil.decryptWithGOST28147_89_CFB(CipherUtil.java:117)
    at com.it.crypto.Test2.main(Test2.java:34)"

 

Метод которым извлекаю закрытый ключ:

public static GostR341001PrivateKey getSecretKeyFromKeyStore34(String folder, String keyAlias, String password) {
        KeyStore keyStore = KeyStoreUtil.getKeyStore();
        KeyStoreUtil.loadKeyStore(keyStore, folder);
        
        Key key;
        try {
            key = keyStore.getKey(keyAlias, password.toCharArray());
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        
        return (GostR341001PrivateKey)key;
        
    }

Метод

которым делаю расшифровку:

public static byte[] decryptWithGOST28147_89_CFB(
            Gost28147ParamSet inputParamSet, Key inputSecretKey,
            byte[] inputIV, byte[] inputData) throws Exception {
        // подготовка ключа расшифрования
        Key secretKey = inputSecretKey;

        // получение шифра ГОСТ 28147-89, работающего в режиме CFB без
        // дополнения
        Cipher cipherDriver = Cipher.getInstance("GOST28147-89/CFB/NoPadding", // строка
                                                                                // трансформации
                                                                                // шифра
                "ViPNet" // название провайдера
        );

        // подготовка параметров расшифрования
        // подготовка набора параметров работы алгоритма ГОСТ 28147-89
        Gost28147ParamSet paramSet = inputParamSet;
        // подготовка вектора инициализации (8 байт)
        byte[] iv = inputIV;
        // создание параметров расшифрования
        AlgorithmParameterSpec params = new Gost28147CipherParameterSpec(
                paramSet, iv);

        // инициализация шифра в режиме расшифрования данных
        cipherDriver.init(Cipher.DECRYPT_MODE, secretKey, params);

        // расшифрование данных
        byte[] nextEncodedChunk = inputData;
        byte[] nextPlainChunk = cipherDriver.update(nextEncodedChunk);

        // завершение операции расшифрования
        byte[] lastPlainChunk = cipherDriver.doFinal();

        byte[] outputData = new byte[nextPlainChunk.length
                + lastPlainChunk.length];
        System.arraycopy(nextPlainChunk, 0, outputData, 0,
                nextPlainChunk.length);
        System.arraycopy(lastPlainChunk, 0, outputData, nextPlainChunk.length,
                lastPlainChunk.length);
        return outputData;
    }

Вызов метода для расшифровки

byte[] decryptFile = CipherUtil.decryptWithGOST28147_89_CFB(Gost28147ParamSet.CryptoPro_A, secretKey,
                    inputIV, fileData);

 

Share this post


Link to post
Share on other sites

Евгений, добрый день.

Ошибка:

"java.security.InvalidKeyException: Unsupported key!ru.infotecs.crypto.gost3410.GostR341001PrivateKey

возникает из-за того, что в методе

public static byte[] decryptWithGOST28147_89_CFB(
            Gost28147ParamSet inputParamSet, Key inputSecretKey,
            byte[] inputIV, byte[] inputData)

параметр "Key inputSecretKey" у вас оказался закрытым асимметричным ключом, т. е. объектом типа GostR341001PrivateKey, в то время как JCrypto SDK ожидает объект типа "Gost28147SecretKey". 
Алгоритм ГОСТ 28147-89 работает только с симметричными ключами длиной 256 бит. Закрытые ключи можно использовать только для создания электронной подписи, генерации парного открытого ключа и выработки симметричных ключей по алгоритму Диффи-Хеллмана.


Что нужно сделать, чтобы расшифровать файл, созданный в ViPNet CryptoFile?
1) ViPNet CryptoFile создает зашифрованные сообщения в формате PKCS#7. Чтобы расшифровать такой файл, вам понадобятся 2 модуля из состава JCrypto SDK:
- jcrypto-jca-2.6.0-R******.jar
- jcrypto-pkcs-2.6.0-R******.jar
Убедитесь, что ваш проект использует эти модули.
2) Метод "getSecretKeyFromKeyStore34" вашей программы оставляем - закрытый ключ вам действительно понадобится. Для корректности метод лучше назвать "getPrivateKeyFromKeyStore34".

3) Кроме метода "getPrivateKeyFromKeyStore34" вам также понадобится метод, возвращающий сертификат:

public static X509Certificate getCertificateFromKeyStore34(String folder, String keyAlias, String password) throws Exception {
    KeyStore keyStore = KeyStoreUtil.getKeyStore();
    KeyStoreUtil.loadKeyStore(keyStore, folder);
    return keyStore.getCertificate(keyAlias);
}

4) Метод "decryptWithGOST28147_89_CFB" нужно полностью переписать. Найдите в комплекте JCrypto SDK документ "ViPNet JCrypto SDK. Руководство программиста". В руководстве есть небольшой раздел "Расшифрование CMS-сообщений". В этом разделе есть пример кода, который расшифровывает сообщение в формате PKCS#7.
Обратите внимание, что в методе CMSEnvelopedDataStream.init(privateKey, certificate) вам необходимо передать не только закрытый ключ, но и сертификат, который у вас хранится в хранилище (смотрите код метода getCertificateFromKeyStore34).

Share this post


Link to post
Share on other sites

спасибо большое за объяснение, но при попытке инициализировать объект CMSEnvelopedDataInputStream выходит ошибка.

Как инициализирую:

 

           InputStream inputStream = new FileInputStream(new File(FILE_ENC));
            CMSEnvelopedDataInputStream encryptedStream = new CMSEnvelopedDataInputStream(inputStream);

Текст ошибки:

Exception in thread "main" java.lang.NoSuchMethodError: ru.infotecs.cms.input.CMSEnvelopedDataInputStream.<init>(Ljava/io/InputStream;)V
    at com.it.crypto.Test2.decrypte(Test2.java:60)
    at com.it.crypto.Test2.main(Test2.java:45)

полный код метода расшифровки:

private static void decrypte(X509Certificate certificat, PrivateKey privateKey) throws Exception {
        // регистрируем провайдер
        Security.addProvider(new ViPNetProvider());
        try (InputStream inputStream = new FileInputStream(new File(FILE_ENC));
                CMSEnvelopedDataInputStream encryptedStream = new CMSEnvelopedDataInputStream(inputStream);
                OutputStream outputStream = new FileOutputStream(new File(FILE_ENC.replace(".enc", "")));) {

            // инициализируем закрытый ключ
            encryptedStream.init(privateKey, certificat);
            // считываем расшифрованное сообщение
            byte[] buffer = new byte[1024];
            int len;
            while ((len = encryptedStream.read(buffer)) >= 0) {
                outputStream.write(buffer, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(e);
        }
    }

 

Share this post


Link to post
Share on other sites

Приветствую!

Вышел новый релиз ViPNet CryptoFile.

Скоро появится на нашем сайте.

Предлагаю дождаться его, попробовать Вам обновиться и воспроизвести ситуацию. Возможно, всё заработает.

 

Share this post


Link to post
Share on other sites
5 часов назад, Petrenko Sergey сказал:

Приветствую!

Вышел новый релиз ViPNet CryptoFile.

Скоро появится на нашем сайте.

Предлагаю дождаться его, попробовать Вам обновиться и воспроизвести ситуацию. Возможно, всё заработает.

 

Добрый день! 

Вы наверное имели в виду про новую версию ViPNet Java Crypto SDK?

Share this post


Link to post
Share on other sites
В 27.02.2017в13:50, evgenyshevnin сказал:

Вопрос ещё актуален, есть какие-нибудь предположения что делаю не так?

Евгений, попробовал у себя похожий код расшифрования - все работает. Ошибка:

Exception in thread "main" java.lang.NoSuchMethodError: ru.infotecs.cms.input.CMSEnvelopedDataInputStream.<init>(Ljava/io/InputStream;)V
    at com.it.crypto.Test2.decrypte(Test2.java:60)
    at com.it.crypto.Test2.main(Test2.java:45)

возможно, связана с тем, что у вас модуль "jcrypto-pkcs7-2.6.1-R******.jar" используется при компиляции, но не во время выполнения программы. Нужно проверить, что модуль "jcrypto-pkcs7-2.6.1-R******.jar" попадает в CLASSPATH во время запуска вашего теста.

Хотелось также уточнить, в какой IDE вы запускаете прогрмму и какую версию JCrypto SDK вы используете?
 

 

Share this post


Link to post
Share on other sites

Такая же проблема - использую android studio, compile project(':jcrypto-pkcs7-android-2.6.1-R363770')
Unable to find class:ru.infotecs.cms.output.CMSEnvelopedDataOutputStream

 

моя тема 

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×

Important Information

By using this site, you agree to our Terms of Use.