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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline Donhuan  
#1 Оставлено : 6 декабря 2019 г. 7:29:28(UTC)
Donhuan

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

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

Добрый день!

Пытаюсь создать CMS-сообщение с зашифрованными данными (без подписи). Взял из примера CMSSignAndEncrypt. Убрал часть, отвечающую за подпись.
Все работает, но не могу избавиться от зависимости от своих приватных ключей и сертификатов (senderKey / publicSenderCert).
Хотя, для шифрования, должно быть достаточно иметь сертификат получателя.
Подскажите, что можно сделать?

Код:

public static void encode(String senderAlias, char[] senderPassword,
                               String agreeAlgorithm, ParamsInterface crp_params,
                               String outFileName) throws Exception {

        final String SEC_KEY_ALG_NAME = "GOST28147";
        final String STR_CMS_OID_ENVELOPED = "1.2.840.113549.1.7.3";
        final String STR_CMS_OID_DATA = "1.2.840.113549.1.7.1";

        final byte[] buffer = Array.readFile("C:\\cryptcp\\testdata.txt");

        //Загрузка хранилища
        final KeyStore hdImageStore = KeyStore.getInstance(JCP.HD_STORE_NAME);
        hdImageStore.load(null, null);

        //ключ отправителя - как убрать зависимость от senderKey / publicSenderCert ?
        final PrivateKey senderKey =
                (PrivateKey) hdImageStore.getKey(senderAlias, senderPassword);
        final X509Certificate publicSenderCert =
                (X509Certificate) hdImageStore.getCertificate(senderAlias);


        // Загрузка сертификата из файла
        CertificateFactory fact = CertificateFactory.getInstance("X.509");
        FileInputStream is = new FileInputStream("C:\\cryptcp\\poluchatel.cer");
        X509Certificate publicCert = (X509Certificate) fact.generateCertificate(is);
        is.close();


        final PublicKey responderPublic = publicCert.getPublicKey();

        // выработка ключа согласования отправителем
        final KeyAgreement senderKeyAgree =
                KeyAgreement.getInstance(agreeAlgorithm);
        senderKeyAgree.init(senderKey, new IvParameterSpec(sv), null);
        senderKeyAgree.doPhase(responderPublic, true);
        final SecretKey alisaSecret =
                senderKeyAgree.generateSecret(SEC_KEY_ALG_NAME);

        // Генерирование симметричного ключа с параметрами шифрования из контрольной панели.
        final KeyGenerator kg = KeyGenerator.getInstance(SEC_KEY_ALG_NAME);
        //final ParamsInterface paramss = AlgIdSpec.getDefaultCryptParams();
        kg.init(/*paramss*/ crp_params);
        final SecretKey simm = kg.generateKey();

        // Зашифрование текста на симметричном ключе.
        final Cipher cipher = Cipher.getInstance(CIPHER_MODE);
        cipher.init(Cipher.ENCRYPT_MODE, simm, (SecureRandom) null);
        final byte[] iv = cipher.getIV();
        final byte[] text = cipher.doFinal(buffer, 0, buffer.length);

        //Зашифрование симметричного ключа на ключе согласования отправителя
        cipher.init(Cipher.WRAP_MODE, alisaSecret, (SecureRandom) null);
        final byte[] key = cipher.wrap(simm);

        //формирование CMS-сообщения
        final ContentInfo all = new ContentInfo();
        all.contentType =
                new Asn1ObjectIdentifier(
                        new OID(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 keytrans = new KeyTransRecipientInfo();

        keytrans.version = new CMSVersion(0);

        final Asn1BerEncodeBuffer ebuf = new Asn1BerEncodeBuffer();
        final SubjectPublicKeyInfo spki = new SubjectPublicKeyInfo();
        final Asn1BerDecodeBuffer dbuff = new Asn1BerDecodeBuffer(
                publicSenderCert.getPublicKey().getEncoded());
        spki.decode(dbuff);
        dbuff.reset();
        final AlgIdInterface algid = new AlgIdSpec(spki.algorithm);
        final AlgorithmIdentifier id = (AlgorithmIdentifier) algid.getDecoded();
        id.encode(ebuf);
        Asn1BerDecodeBuffer dbuf = new Asn1BerDecodeBuffer(ebuf.getMsgCopy());
        keytrans.keyEncryptionAlgorithm = new KeyEncryptionAlgorithmIdentifier();
        keytrans.keyEncryptionAlgorithm.decode(dbuf);
        ebuf.reset();
        dbuf.reset();
        keytrans.rid = new RecipientIdentifier();
        final IssuerAndSerialNumber issuer = new IssuerAndSerialNumber();
        final X500Principal issuerName = publicCert.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(
                publicCert.getSerialNumber());
        keytrans.rid.set_issuerAndSerialNumber(issuer);
        dbuf.reset();
        final GostR3410_KeyTransport encrKey = new GostR3410_KeyTransport();
        dbuf = new Asn1BerDecodeBuffer(key);
        encrKey.sessionEncryptedKey = new Gost28147_89_EncryptedKey();
        encrKey.sessionEncryptedKey.decode(dbuf);
        dbuf.reset();
        encrKey.transportParameters = new GostR3410_TransportParameters();
        encrKey.transportParameters.encryptionParamSet =
                new Gost28147_89_ParamSet(algid.getCryptParams()
                        .getOID().value);
        encrKey.transportParameters.ephemeralPublicKey = new SubjectPublicKeyInfo();
        dbuf = new Asn1BerDecodeBuffer(
                publicSenderCert.getPublicKey().getEncoded());
        encrKey.transportParameters.ephemeralPublicKey.decode(dbuf);
        dbuf.reset();
        encrKey.transportParameters.ukm = new Asn1OctetString(sv);
        encrKey.encode(ebuf);
        keytrans.encryptedKey = new EncryptedKey(ebuf.getMsgCopy());
        ebuf.reset();
        cms.recipientInfos.elements[0].set_ktri(keytrans);

        cms.encryptedContentInfo = new EncryptedContentInfo();
        final OID contentType = new OID(STR_CMS_OID_DATA);
        cms.encryptedContentInfo.contentType = new ContentType(contentType.value);
        final Gost28147_89_Parameters params = new Gost28147_89_Parameters();
        params.iv = new Gost28147_89_IV(iv);
        params.encryptionParamSet =
                new Gost28147_89_ParamSet(/*paramss*/crp_params.getOID().value);
        cms.encryptedContentInfo.contentEncryptionAlgorithm =
                new ContentEncryptionAlgorithmIdentifier(
                        _Gost28147_89_EncryptionSyntaxValues.id_Gost28147_89,
                        params);
        cms.encryptedContentInfo.encryptedContent = new EncryptedContent(text);

        all.encode(ebuf);

        String path = "C:\\cryptcp\\testdata.enc";
        Files.write(Paths.get(path), ebuf.getMsgCopy());
    }

Offline two_oceans  
#2 Оставлено : 6 декабря 2019 г. 8:12:21(UTC)
two_oceans

Статус: Эксперт

Группы: Участники
Зарегистрирован: 05.03.2015(UTC)
Сообщений: 1,005
Российская Федерация
Откуда: Иркутская область

Сказал(а) «Спасибо»: 63 раз
Поблагодарили: 228 раз в 214 постах
Добрый день. Могу ошибаться, но, насколько понимаю, без своего закрытого ключа не сможете получить ключ согласования с получателем. Поэтому из именно такой схемы исключить свой закрытый ключ не получится.
Offline Donhuan  
#3 Оставлено : 6 декабря 2019 г. 8:21:15(UTC)
Donhuan

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

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

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


У cryptcp.win32.exe под Windows это как-то получается сделать. (контейнеры пустые)

Код:
cryptcp.win32.exe -encr -f "polucatel.cer" file.rnd file.rnd.enc


Offline Евгений Афанасьев  
#4 Оставлено : 6 декабря 2019 г. 14:23:57(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 14 раз
Поблагодарили: 491 раз в 473 постах
Добрый день.
Лучше использовать:
1) высокоуровневый EnvelopedSignature из CAdES.jar для зашифрования в адрес получателя (примеры - samples-sources.jar, пакет CAdES/enveloped, а также в javadoc/CAdES-javadoc.jar);
2) утилиту cmsutil.jar из дистрибутива или, например, ее код в составе samples-sources.jar, пакет cmsutil;
3) низкоуровневый пример PKCS7EnvEphTransport (примеры - samples-sources.jar, пакет CMS_samples).
Правильная схема - использовать эфемерный ключ для согласования с открытым ключом получателя.
Offline Donhuan  
#5 Оставлено : 9 декабря 2019 г. 9:15:05(UTC)
Donhuan

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

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

Спасибо, Евгений! Через CAdES все получилось.
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.