Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

6 Страницы«<456
Опции
К последнему сообщению К первому непрочитанному
Online Евгений Афанасьев  
#51 Оставлено : 10 октября 2018 г. 12:31:22(UTC)
Евгений Афанасьев

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 06.12.2008(UTC)
Сообщений: 3,910
Российская Федерация
Откуда: Крипто-Про

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 685 раз в 646 постах
Здравствуйте.
Параметры шифрования - CryptParamsSpec.OID_Gost28147_89_Rosstandart_TC26_Z_ParamSet?
Приведите, пожалуйста, свой пример для анализа и, если не трудно, создайте с помощью тестового ключевого контейнера (выпустить его можно тут - http://cryptopro.ru/certsrv/) сообщение и прикрепите архив с ним и ключевым контейнером для расшифровки, для воспроизведения проблемы.
Схожие проблемы:
https://www.cryptopro.ru...aspx?g=posts&t=13422
https://www.cryptopro.ru...aspx?g=posts&t=13409

Отредактировано пользователем 10 октября 2018 г. 12:32:40(UTC)  | Причина: Не указана

Offline BaalPr  
#52 Оставлено : 12 октября 2018 г. 15:13:00(UTC)
BaalPr

Статус: Новичок

Группы: Участники
Зарегистрирован: 03.10.2018(UTC)
Сообщений: 8
Российская Федерация

Добрый день
Действительно помогло.
В примерах samples-sources\CMS_samples\PKCS7EnvEphTransport.java есть метод wrap
там строки:

IvParameterSpec iv = new IvParameterSpec(syncro);
OID oid = CryptParamsSpec.OID_Crypt_VerbaO;

// Выработка ключа согласования.

Мы заменили этот параметр на OID oid = CryptParamsSpec.OID_Gost28147_89_Rosstandart_TC26_Z_ParamSet;

И все заработало.
Спасибо!
Offline Denis1499  
#53 Оставлено : 29 октября 2018 г. 15:42:15(UTC)
Denis1499

Статус: Участник

Группы: Участники
Зарегистрирован: 03.07.2018(UTC)
Сообщений: 17
Российская Федерация
Откуда: Москва

Автор: BaalPr Перейти к цитате
Добрый день
Действительно помогло.
В примерах samples-sources\CMS_samples\PKCS7EnvEphTransport.java есть метод wrap
там строки:

IvParameterSpec iv = new IvParameterSpec(syncro);
OID oid = CryptParamsSpec.OID_Crypt_VerbaO;

// Выработка ключа согласования.

Мы заменили этот параметр на OID oid = CryptParamsSpec.OID_Gost28147_89_Rosstandart_TC26_Z_ParamSet;

И все заработало.
Спасибо!


Спасибо за совет!
Решил попробовать еще раз.

Установка данного параметра помогла только для сертификата 2001 г., для 2012 так и не заработало.

Поменял

Цитата:

// Генерация эфемерной пары.
final String keyAlgName = recipientKey.getAlgorithm();
System.out.println(keyAlgName);

KeyPairGenerator kgp = KeyPairGenerator.getInstance(
JCP.GOST_EPH_DH_2012_256_NAME,
CryptoProvider.PROVIDER_NAME
);


тк вижу что keyAlgName == GOST3410_2012_256

Пока не заработало, буду смотреть и далее,
версия jcp 2.0.39893
Online Евгений Афанасьев  
#54 Оставлено : 9 ноября 2018 г. 9:41:05(UTC)
Евгений Афанасьев

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 06.12.2008(UTC)
Сообщений: 3,910
Российская Федерация
Откуда: Крипто-Про

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 685 раз в 646 постах
Здравствуйте.
Согласно используемому примеру, попробуйте так (настройки из этого примера остаются практически прежними, некоторые методы изменились):
Код:

public class PKCS7EnvEphTransport {

    /**
     * Подписываемые/шифруемые данные.
     */
    private static final byte[] DATA = ...

    /**
     * Контейнер получателя.
     */
    private final static ISignatureContainer RECIPIENT = new EnvContainer2012_256(); // из samples

    /**
     * Извлечение параметров сертификата. Параметры шифрования
     * обычно null, поэтому будут получены параметры шифрования
     * по умолчанию.
     * У AlgIdSpec есть несколько конструкторов (с использованием
     * OID и др.).
     *
     * @param cert Сертификат.
     * @return параметры сертификата.
     * @throws Exception
     */
    private static AlgIdSpec getAlgIdSpec(X509Certificate cert)
        throws Exception {

        byte[] encoded = cert.getPublicKey().getEncoded();
        Asn1BerDecodeBuffer buf = new Asn1BerDecodeBuffer(encoded);
        SubjectPublicKeyInfo keyInfo = new SubjectPublicKeyInfo();

        try {
            keyInfo.decode(buf);
        } catch (Asn1Exception e) {
            IOException ex = new IOException("Not GOST DH public key");
            ex.initCause(e);
            throw ex;
        }

        buf.reset();
        return new AlgIdSpec(keyInfo.algorithm);

    }

    /**
     * Зашифрование сообщения (enveloped).
     *
     * @param recipientCert - сертификат получателя.
     * @param data - исходное сообщение (PKCS7).
     * @return зашифрованное сообщение (enveloped).
     * @throws Exception
    */
    public static byte[] EncryptPKCS7(X509Certificate recipientCert,
        byte[] data) throws Exception {

	final PublicKey recipientPublic = recipientCert.getPublicKey();

	// Генерирование симметричного ключа с параметрами
	// шифрования из контрольной панели.

	final KeyGenerator kg = KeyGenerator.getInstance(
            CMStools.SEC_KEY_ALG_NAME, CRYPT_PROVIDER_NAME);

        // Параметры шифрования симметричного ключа (по умолчанию)
        // и параметры шифрования данных (по умолчанию).

        final AlgIdSpec algIdSpec = getAlgIdSpec(recipientCert);

        final ParamsInterface recipientTransportParameters = algIdSpec.getCryptParams(); // из открытого ключа
	final ParamsInterface contentEncryptionParameters  = algIdSpec.getCryptParams(); // могут быть другие

        // Инициализация генератора.

        kg.init(contentEncryptionParameters);

        // Симметричный ключ.

	final SecretKey symmetricKey = kg.generateKey();
	    
	// Зашифрование текста на симметричном ключе.

	Cipher cipher = Cipher.getInstance(CIPHER_MODE, CRYPT_PROVIDER_NAME);
	cipher.init(Cipher.ENCRYPT_MODE, symmetricKey, (SecureRandom) null);

	final byte[] iv = cipher.getIV();
	final byte[] text = cipher.doFinal(data, 0, data.length);

	// Зашифрование симметричного ключа.

	final byte[] keyTransport = wrap(symmetricKey, recipientPublic,
            recipientTransportParameters);

	// Формирование CMS-сообщения.

	final ContentInfo all = new ContentInfo();
	all.contentType = new Asn1ObjectIdentifier(new OID(CMStools.STR_CMS_OID_ENVELOPED).value);

	final EnvelopedData cms = new EnvelopedData();

	all.content = cms;
	cms.version = new CMSVersion(0);

	cms.recipientInfos = new RecipientInfos(1);
	cms.recipientInfos.elements = new RecipientInfo[1];
	cms.recipientInfos.elements[0] = new RecipientInfo();

	final KeyTransRecipientInfo key_trans = new KeyTransRecipientInfo();
        key_trans.version = new CMSVersion(0);

	final Asn1BerEncodeBuffer ebuf = new Asn1BerEncodeBuffer();

	final AlgorithmIdentifier id = (AlgorithmIdentifier) algIdSpec.getDecoded();
	id.encode(ebuf);

	Asn1BerDecodeBuffer dbuf = new Asn1BerDecodeBuffer(ebuf.getMsgCopy());
        key_trans.keyEncryptionAlgorithm = new KeyEncryptionAlgorithmIdentifier();
        key_trans.keyEncryptionAlgorithm.decode(dbuf);

	ebuf.reset();
	dbuf.reset();

        key_trans.rid = new RecipientIdentifier();
	final IssuerAndSerialNumber issuer = new IssuerAndSerialNumber();

	final X500Principal issuerName = recipientCert.getIssuerX500Principal();
	dbuf = new Asn1BerDecodeBuffer(issuerName.getEncoded());
	    
	issuer.issuer = new Name();
	final RDNSequence rnd = new RDNSequence();
	rnd.decode(dbuf);
	    
	issuer.issuer.set_rdnSequence(rnd);
	issuer.serialNumber = new CertificateSerialNumber(recipientCert.getSerialNumber());

        key_trans.rid.set_issuerAndSerialNumber(issuer);
	dbuf.reset();

        key_trans.encryptedKey = new EncryptedKey(keyTransport);
	ebuf.reset();
	    
	cms.recipientInfos.elements[0].set_ktri(key_trans);
	cms.encryptedContentInfo = new EncryptedContentInfo();

	final OID contentType = new OID(CMStools.STR_CMS_OID_DATA);
	cms.encryptedContentInfo.contentType = new ContentType(contentType.value);

	final Gost28147_89_Parameters parameters = new Gost28147_89_Parameters();
        parameters.iv = new Gost28147_89_IV(iv);

        parameters.encryptionParamSet = new Gost28147_89_ParamSet(contentEncryptionParameters.getOID().value); // параметры шифрования данных
	cms.encryptedContentInfo.contentEncryptionAlgorithm = new ContentEncryptionAlgorithmIdentifier(
	    _Gost28147_89_EncryptionSyntaxValues.id_Gost28147_89, parameters);

	cms.encryptedContentInfo.encryptedContent = new EncryptedContent(text);
	all.encode(ebuf);

	return ebuf.getMsgCopy();

    }
		
    /**
     * Расшифрование PKCS7 (Enveloped).
     *
     * @param recipientAlias - алиас получателя.
     * @param recipientPassword - пароль получателя.
     * @param enveloped - зашифрованное сообщение (Enveloped).
     * @param data - исходные данные (нужны при проверке detached CMS подписи).
     * @param detached - флаг detached подписи.
     * @return результат проверки.
     * @throws Exception
    */
    public static boolean DecryptPKCS7(String recipientAlias, char[]
        recipientPassword, byte[] enveloped, byte[] data, boolean
        detached) throws Exception {

	// Разбор CMS-сообщения.

	Asn1BerDecodeBuffer dbuf = new Asn1BerDecodeBuffer(enveloped);
	final ContentInfo all = new ContentInfo();

	all.decode(dbuf);
	dbuf.reset();
		
	final EnvelopedData cms = (EnvelopedData) all.content;
	KeyTransRecipientInfo key_trans;

        // Только key_trans.

	if (cms.recipientInfos.elements[0].getChoiceID() == RecipientInfo._KTRI) {
            key_trans = (KeyTransRecipientInfo) (cms.recipientInfos.elements[0].getElement());
	}
	else {
	    throw new Exception("Unknown recipient info");
	}

	final byte[] wrapKey = key_trans.encryptedKey.value;
	final Gost28147_89_Parameters params = (Gost28147_89_Parameters)
            cms.encryptedContentInfo.contentEncryptionAlgorithm.parameters;

	final byte[] iv = params.iv.value;
	final OID cipherOID = new OID(params.encryptionParamSet.value); // параметры шифрования данных
	final byte[] text = cms.encryptedContentInfo.encryptedContent.value;

	// Получатель - закрытый ключ.

        final JCPProtectionParameter protectionParameter =
            new JCPProtectionParameter(recipientPassword);

        final JCPPrivateKeyEntry recipientEntry = (JCPPrivateKeyEntry) keyStore
            .getEntry(recipientAlias, protectionParameter);

	// Выработка ключа согласования получателем и
	// расшифрование симметричного ключа.

	final SecretKey symmetricKey = unwrap(wrapKey,
            recipientEntry.getPrivateKey());

	// Расшифрование текста на симметричном ключе.

	final GostCipherSpec spec = new GostCipherSpec(iv, cipherOID);
	Cipher cipher = Cipher.getInstance(CIPHER_MODE, CRYPT_PROVIDER_NAME);

	cipher.init(Cipher.DECRYPT_MODE, symmetricKey, spec, null);
	final byte[] result = cipher.doFinal(text, 0, text.length);

	Array.writeFile(TEST_DIR + "cms_cms.bin", result);
	// checkPKCS7(result, detached, data, TEST_DIR + "cms_cms_data.txt");

	return true;

    }

    /**
     * Зашифрование сессионного ключа.
     *
     * @param secretKey Сессионный ключ.
     * @param recipientKey Открытый ключ получателя.
     * @return транспортная структура GostR3410_KeyTransport.
     * @throws Exception
    */
    private static byte[] wrap(SecretKey secretKey, PublicKey
        recipientKey, ParamsInterface recipientTransportParameters)
        throws Exception {

        // Определение алгоритма эфемерного ключа.

        String keyAlgorithm = recipientKey.getAlgorithm();
        String ephKeyAlgorithm = JCP.GOST_EL_DH_EPH_NAME;

        if (keyAlgorithm.equalsIgnoreCase(JCP.GOST_EL_2012_256_NAME)) {
            ephKeyAlgorithm = JCP.GOST_EPH_DH_2012_256_NAME;
        } // if
        else if (keyAlgorithm.equalsIgnoreCase(JCP.GOST_EL_2012_512_NAME)) {
            ephKeyAlgorithm = JCP.GOST_EPH_DH_2012_512_NAME;
        } // else

	// Генерация эфемерной пары.

	KeyPairGenerator kgp = KeyPairGenerator.getInstance(
            ephKeyAlgorithm, CRYPT_PROVIDER_NAME);

	// Устанавливаем нужные параметры, как у
	// получателя.

        AlgorithmParameterSpec spec = new X509PublicKeySpec(recipientKey.getEncoded());
        kgp.initialize(spec);

	// Генерируем эфемерную пару. Ключи получат
	// параметры recipientKey, а у него параметры
	// - recipientTransportParameters.

	KeyPair ephPair = kgp.generateKeyPair();

	PrivateKey privateKey = ephPair.getPrivate();
	PublicKey publicKey = ephPair.getPublic();

	byte[] syncro = new byte[8];
	SecureRandom random = SecureRandom.getInstance(JCP.CP_RANDOM, PROVIDER_NAME);
	random.nextBytes(syncro);

	IvParameterSpec iv = new IvParameterSpec(syncro);

	// Выработка ключа согласования.

	KeyAgreement ka = KeyAgreement.getInstance(privateKey.getAlgorithm(), CRYPT_PROVIDER_NAME);
	ka.init(privateKey, iv);

	ka.doPhase(recipientKey, true);
	Key dh = ka.generateSecret(CIPHER); // dh получит параметры из privateKey, т.е. recipientTransportParameters

	// Зашифрование симметричного ключа на ключе согласования
	// отправителя. Передаются параметры шифрования ключа, если
        // отличаются от тех, что у dh.

	final Cipher cipher = Cipher.getInstance(CIPHER, CRYPT_PROVIDER_NAME);
	cipher.init(Cipher.WRAP_MODE, dh, recipientTransportParameters, (SecureRandom) null);

	final byte[] wrappedKey = cipher.wrap(secretKey);

	// Упаковка параметров и ключа.

	Gost28147_89_EncryptedKey encryptedKey = new Gost28147_89_EncryptedKey();
	Asn1BerDecodeBuffer decoder = new Asn1BerDecodeBuffer(wrappedKey);
	encryptedKey.decode(decoder);

	byte[] imita = encryptedKey.macKey.value;
	byte[] wrapperKeyBytes = encryptedKey.encryptedKey.value;

	// Кодирование открытого ключа в SubjectPublicKeyInfo.

	byte[] publicKeyBytes = publicKey.getEncoded();
	SubjectPublicKeyInfo publicKeyInfo = new SubjectPublicKeyInfo();

	decoder = new Asn1BerDecodeBuffer(publicKeyBytes);
	publicKeyInfo.decode(decoder);

	// Кодирование GostR3410_KeyTransport.

	GostR3410_KeyTransport keyTransport = new GostR3410_KeyTransport();
	Asn1BerEncodeBuffer encoder = new Asn1BerEncodeBuffer();

	keyTransport.sessionEncryptedKey = new Gost28147_89_EncryptedKey(wrapperKeyBytes, imita);
	keyTransport.transportParameters = new GostR3410_TransportParameters(
	    new Gost28147_89_ParamSet(recipientTransportParameters.getOID().value), // параметры шифрования ключа
		publicKeyInfo,
		new Asn1OctetString(iv.getIV()));

	keyTransport.encode(encoder);
	return encoder.getMsgCopy();

    }

    /**
     * Зашифрование сессионного ключа.
     *
     * @param wrappedKey Зашифрованный сессионный ключ (транспортная
     * структура GostR3410_KeyTransport).
     * @param recipientKey Закрытый ключ получателя.
     * @return сессионный ключ.
     * @throws Exception
     */
    private static SecretKey unwrap(byte[] wrappedKey, Key
        recipientKey) throws Exception {

	// Декодирование GostR3410_KeyTransport.

	GostR3410_KeyTransport keyTransport = new GostR3410_KeyTransport();
	Asn1BerDecodeBuffer decoder = new Asn1BerDecodeBuffer(wrappedKey);
	keyTransport.decode(decoder);

	// EncryptedKey в правильном формате для шифратора.

	byte[] wrappedKeyBytes = keyTransport.sessionEncryptedKey.encryptedKey.value;
	byte[] imita = keyTransport.sessionEncryptedKey.macKey.value;

	Asn1BerEncodeBuffer encoder = new Asn1BerEncodeBuffer();
	Gost28147_89_EncryptedKey encryptedKey = new Gost28147_89_EncryptedKey(
	    new Gost28147_89_Key(wrappedKeyBytes), null, new Gost28147_89_MAC(imita));

	encryptedKey.encode(encoder);
	byte[] wrapped = encoder.getMsgCopy();

	// Декодирование открытого ключа.

	encoder.reset();
	keyTransport.transportParameters.ephemeralPublicKey.encode(encoder);

	byte[] encodedPublic = encoder.getMsgCopy();
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedPublic);

        KeyFactory kf = KeyFactory.getInstance(recipientKey.getAlgorithm(), PROVIDER_NAME);
	PublicKey publicKey = kf.generatePublic(keySpec);

	// Параметры шифрования.

	IvParameterSpec iv = new IvParameterSpec(keyTransport.transportParameters.ukm.value);
	OID transportParametersOid = new OID(keyTransport.transportParameters.encryptionParamSet.value); // параметры шифрования ключа

	CryptParamsSpec uz = CryptParamsSpec.getInstance(transportParametersOid);
	GostCipherSpec params = new GostCipherSpec(iv, uz);

	// Выработка ключа согласования.

	KeyAgreement ka = KeyAgreement.getInstance(recipientKey.getAlgorithm(), CRYPT_PROVIDER_NAME);
	ka.init(recipientKey, iv);

	ka.doPhase(publicKey, true);
	Key dh = ka.generateSecret(CIPHER); // dh получит параметры из recipientKey, т.е., по идее, transportParametersOid

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

	Cipher cipher = Cipher.getInstance(CIPHER, CRYPT_PROVIDER_NAME);
	cipher.init(Cipher.UNWRAP_MODE, dh, params);

	return (SecretKey) cipher.unwrap(wrapped, null, Cipher.SECRET_KEY);

    }

...

    public static void main(String[] args) throws Exception {
        byte[] enveloped =  EncryptPKCS7(RECIPIENT.getAlias(), DATA);
        DecryptPKCS7(RECIPIENT.getAlias(), RECIPIENT.getPassword(), enveloped, null, false);
        // "C:\Program Files\Crypto Pro\CSP\csptest" -lowenc -decrypt -in "jcp_enveloped_cms.bin" -out "decrypted.txt" -my <installed_recipient_RECIPIENT>
    }



Вообще, часть wrap/unwrap можно заменить с помощью алгоритма Cipher - "GostTransport": он также генерирует эфемерный ключ, экспортирует/импортирует его и т.д.

Отредактировано пользователем 9 ноября 2018 г. 9:43:59(UTC)  | Причина: Не указана

Offline Denis1499  
#55 Оставлено : 15 ноября 2018 г. 16:10:31(UTC)
Denis1499

Статус: Участник

Группы: Участники
Зарегистрирован: 03.07.2018(UTC)
Сообщений: 17
Российская Федерация
Откуда: Москва

Добрый день!

В конечном счете я понял, что наша проблема в создании файла подписи.

Помогло, что вывели oids алгоритмов, которые использовались в ключе:

Код:

System.out.println(((GostExchPrivateKey) senderPrivateKey).getSpec().getParams());


Потом подобрали параметры, для создания конверта.
Нам помогли следующие константы (CMStools, CMSSign взяты из примеров JCP):

Код:

CMSSign.createCMSEx(data, keys, certs, null, true, 
        		CMStools.DIGEST_OID_2012_256, CMStools.SIGN_OID_2012_256,
			JCP.GOST_DHEL_SIGN_NAME, JCP.PROVIDER_NAME);


вместо

Код:

CMSSign.createCMSEx(data, keys, certs, null, true, 
        		CMStools.DIGEST_OID, CMStools.SIGN_OID,
        		JCP.GOST_DHEL_SIGN_NAME, JCP.PROVIDER_NAME);


Возможно кому-то константы 512 требуется указать.

Всем спасибо за помощь, что не бросали нас, все работает. Тему можно закрывать.
Online Евгений Афанасьев  
#56 Оставлено : 15 ноября 2018 г. 16:13:59(UTC)
Евгений Афанасьев

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 06.12.2008(UTC)
Сообщений: 3,910
Российская Федерация
Откуда: Крипто-Про

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 685 раз в 646 постах
Тогда, по идее, и JCP.GOST_DHEL_SIGN_NAME надо заменить на JCP.GOST_SIGN_2012_256_NAME.
Online Евгений Афанасьев  
#57 Оставлено : 15 ноября 2018 г. 19:24:31(UTC)
Евгений Афанасьев

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 06.12.2008(UTC)
Сообщений: 3,910
Российская Федерация
Откуда: Крипто-Про

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 685 раз в 646 постах
Хотя да, в новой версии алгоритм не важен.
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
6 Страницы«<456
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.