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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline PavelSimonov  
#1 Оставлено : 19 мая 2021 г. 11:43:03(UTC)
PavelSimonov

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

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

Сказал(а) «Спасибо»: 2 раз
Добрый день, помогите пожалуйста разобраться с интеграцией бэкенда (Java) и фронтенда (Browser Plugin).

Дано:

1. Секретный ключ генерируется на сервере при получении данных;
2. На сервере уже есть сертификат с публичным ключом клиента.

Требуется:

1. Зашифровать данные сгенерированным секретным ключом (здесь проблем нет);
2. Зашифровать секретный ключ публичным ключом пользователя и передать его вместе с зашифрованными данными клиенту (Browser Plugin).

Проблема возникла с импортом секретного ключа с помощью плагина для браузера. Плагин ожидает 3 составляющих:

1. Параметры шифрования ключа обмена. Компонент является результатом выполнения CryptGetKeyParam(KP_CIPHEROID).
2. Эфемерный открытый ключ, который использовался для выработки ключа обмена. Компонент является результатом выполнения CryptExportKey(PUBLICKEYBLOBEX).
3. Симметричный ключ, зашифрованный на ключе обмена. Компонент является результатом выполнения CryptExportKey(SIMPLEBLOB).

1 пункт в результате экспериментов найден в GostR3410_KeyTransport.transportParameters.encryptionParamSet

Но я не могу разобраться как вычислить 2 и 3 пункты

Примерный код с проблемой:

Код:

  Certificate certificate = ...;

  KeyGenerator generator = KeyGenerator.getInstance("GOST28147");
  SecretKey secretKey = generator.generateKey();

  Cipher cipher = Cipher.getInstance("GostTransport");
  cipher.init(Cipher.WRAP_MODE, certificate);
  byte[] wrappedSecretKey = cipher.wrap(secretKey);

  GostR3410_KeyTransport encrKey = new GostR3410_KeyTransport();
  Asn1BerDecodeBuffer dbuf = new Asn1BerDecodeBuffer(wrappedSecretKey);
  encrKey.decode(dbuf);
        
  // как из encrKey сделать формат, который поймет браузер?

Отредактировано пользователем 19 мая 2021 г. 11:52:10(UTC)  | Причина: Не указана

Offline two_oceans  
#2 Оставлено : 20 мая 2021 г. 6:44:17(UTC)
two_oceans

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

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

Сказал(а) «Спасибо»: 80 раз
Поблагодарили: 286 раз в 270 постах
Добрый день.
Для начала надо определиться все же по какой схеме Вы хотите шифровать - похоже что у вас вариант без эфемерного ключа, но и без сертификата отправителя? Используется Cipher XML?
Если кратко, то при шифровании с эфемерным ключом нужно для каждого сообщения сгенерировать ключевую информацию дважды - 1) эфемерная ключевая пара; 2) симметричный сессионный ключ. Из закрытой части 1 и сертификата получателя получают ключ согласования. Данные шифруются 2, 2 шифруется ключом согласования. При отправке открытая часть 1 (в PUBLICKEYBLOB) и зашифрованный сессионный ключ передаются получателю, например, объединяются в транспортный блоб (KeyTransport). Тогда при расшифровании надо их разъеденить обратно (похоже вопрос у Вас именно в этом, но тогда где генерация эфемерного ключа). Сертификат для шифрования ответа передается как-то еще.

Пример такого на Дельфи есть в этой теме. TCrypto.EncryptSOAPRequest (строка 675) есть пример как собирается транспортная структура. TCrypto.GetResponseKeysBlobs как транспортная структура разбирается обратно.
Код шифрования с эфемерным ключом на Джава был где-то в разделе Джава, попробуйте поискать по форуму или спросить там.

С другой стороны, есть шифрование без эфемерного ключа. В этом случае вместо закрытой части 1 используется "постоянный" закрытый ключ (1 не генерируется при каждом сообщении, а раз в год и может иметь сертификат "отправителя"; 2 все так же генерируется при каждом сообщении), а в сообщении передается либо сертификат отправителя (отдельно от транспортном блоба) либо открытый ключ отправителя (в транспортном блобе). В подавляющем большинстве случаев используется сертификат и в транспортном блобе только зашифрованный секретный ключ - блоб открытого ключа получают из сертификата. На этот же сертификат шифруется ответ.

Вот здесь есть небольшая подборка по теме шифрования для ФСС по предыдущей спецификации (без эфемерного ключа).

Отредактировано пользователем 20 мая 2021 г. 6:57:28(UTC)  | Причина: Не указана

thanks 1 пользователь поблагодарил two_oceans за этот пост.
PavelSimonov оставлено 20.06.2021(UTC)
Offline PavelSimonov  
#3 Оставлено : 21 мая 2021 г. 2:58:14(UTC)
PavelSimonov

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

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

Сказал(а) «Спасибо»: 2 раз
Спасибо за информацию!

У меня цель сделать серверное хранилище секретных данных без возможности расшифровать их средствами сервера. Т.е. при сохранении данных мы создаем симметричный ключ, шифруем им данные и после этого шифруем симметричный ключ N разными сертификатами для каждого из потенциальных получателей этой информации. После этогого (через день, месяц, год, ...) информация расшифровывается в браузере с использованием приватного ключа пользователя.

С работой эфемерного ключа поразбираюсь, но есть еще пара вопросов по блобам:

1. Я правильно понимаю, что штатных средств подготовить блобы для плагина (ISymmetricAlgorithm::ImportKey) нету и нужно писать свое решение?
2. Чем отличается PUBLICKEYBLOBEX от PUBLICKEYBLOBE ? Я нашел упоминание PUBLICKEYBLOBEX только здесь https://docs.microsoft.c...-wincrypt-publickeystruc и эксперименты с экспортом сгенерированного ключа в браузере показывают, что он начинается на 0xA, что соответствует как раз PUBLICKEYBLOBEX, но больше нигде не нашел информацию по этому типу. Или если корректно сформировать блоб с типом PUBLICKEYBLOBE, то плагин спокойно с ним будет работать и думать о PUBLICKEYBLOBEX нет необходимости?


Offline Евгений Афанасьев  
#4 Оставлено : 16 июня 2021 г. 14:17:22(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 19 раз
Поблагодарили: 568 раз в 542 постах
Здравствуйте.
Автор: PavelSimonov Перейти к цитате

1. Параметры шифрования ключа обмена. Компонент является результатом выполнения CryptGetKeyParam(KP_CIPHEROID).
2. Эфемерный открытый ключ, который использовался для выработки ключа обмена. Компонент является результатом выполнения CryptExportKey(PUBLICKEYBLOBEX).
3. Симметричный ключ, зашифрованный на ключе обмена. Компонент является результатом выполнения CryptExportKey(SIMPLEBLOB).

1 пункт в результате экспериментов найден в GostR3410_KeyTransport.transportParameters.encryptionParamSet

Но я не могу разобраться как вычислить 2 и 3 пункты

Примерный код с проблемой:

Код:

  Certificate certificate = ...;

  KeyGenerator generator = KeyGenerator.getInstance("GOST28147");
  SecretKey secretKey = generator.generateKey();

  Cipher cipher = Cipher.getInstance("GostTransport");
  cipher.init(Cipher.WRAP_MODE, certificate);
  byte[] wrappedSecretKey = cipher.wrap(secretKey);

  GostR3410_KeyTransport encrKey = new GostR3410_KeyTransport();
  Asn1BerDecodeBuffer dbuf = new Asn1BerDecodeBuffer(wrappedSecretKey);
  encrKey.decode(dbuf);
        
  // как из encrKey сделать формат, который поймет браузер?

1. Да, в GostR3410_KeyTransport - это GostR3410_KeyTransport.transportParameters.encryptionParamSet
2. Эфемерный открытый ключ:
Цитата:

GostR3410_TransportParameters params = GostR3410_KeyTransport.transportParameters;
SubjectPublicKeyInfo ephemeralPublicKey = params.ephemeralPublicKey; // это он

И тут же еще UKM для расшифрования сессионного ключа:
Цитата:

Asn1OctetString ukm = GostR3410_KeyTransport.transportParameters.ukm;

3. Зашифрованный симметричный ключ:
Цитата:

Gost28147_89_EncryptedKey sessionEncryptedKey = GostR3410_KeyTransport.sessionEncryptedKey;
Gost28147_89_Key encryptedKey = sessionEncryptedKey.encryptedKey; // сессионный ключ
Gost28147_89_MAC macKey = sessionEncryptedKey.macKey; // ключ имитовставки

Далее можно, пожалуй, ориентироваться на https://cpdn.cryptopro.r...example_DecryptFile.html

Отредактировано пользователем 16 июня 2021 г. 14:18:54(UTC)  | Причина: Не указана

thanks 1 пользователь поблагодарил Евгений Афанасьев за этот пост.
PavelSimonov оставлено 20.06.2021(UTC)
Offline PavelSimonov  
#5 Оставлено : 20 июня 2021 г. 14:42:32(UTC)
PavelSimonov

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

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

Сказал(а) «Спасибо»: 2 раз
Добрый день.

Евгений Афанасьев, спасибо! Получилось сформировать необходимый ключ для браузера (код приложил ниже).
Буду рад услышать замечания или предложения по улучшению этого решения.

Может следует на что-то обратить особенное внимание при использовании подобного кода?

Код:

package ru.cipher.gost.test;

import JCSP.Encryption.Common;
import com.objsys.asn1j.runtime.Asn1BerDecodeBuffer;
import com.objsys.asn1j.runtime.Asn1DerEncodeBuffer;
import com.objsys.asn1j.runtime.Asn1ObjectIdentifier;
import com.objsys.asn1j.runtime.Asn1Tag;
import ru.CryptoPro.Crypto.CryptoProvider;
import ru.CryptoPro.JCP.ASN.Gost28147_89_EncryptionSyntax.Gost28147_89_EncryptedKey;
import ru.CryptoPro.JCP.JCP;
import ru.CryptoPro.JCP.params.CryptParamsInterface;
import ru.CryptoPro.JCP.params.CryptParamsSpec;
import ru.CryptoPro.JCP.params.OID;
import ru.CryptoPro.JCP.spec.X509PublicKeySpec;
import ru.CryptoPro.JCSP.JCSP;
import ru.CryptoPro.JCSP.Key.GostPrivateKey;
import ru.CryptoPro.JCSP.Key.GostPublicKey;
import ru.CryptoPro.JCSP.Key.PublicKeySpec;

import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.spec.X509EncodedKeySpec;

public class EncryptDataForRecipientsInBrowser extends Common {

    private static final String PROVIDER = JCSP.PROVIDER_NAME;
    private static final String DATA_CIPHER_ALG = CryptoProvider.GOST_CIPHER_NAME + "/CNT/NoPadding";
    private static final String WRAP_KEY_ALG = CryptoProvider.GOST_CIPHER_NAME + "/PRO12_EXPORT/NoPadding";
    private static final String EXCHANGE_KEY_ALG = JCP.GOST_DH_2012_512_NAME;
    private static final String SIGN_ALG = JCP.GOST_SIGN_2012_512_NAME;
    private static final String EPHEMERAL_KEY_ALG = JCP.GOST_EPH_DH_2012_512_NAME;

    public static void main(String... args) throws Exception {
        EncryptDataForRecipientsInBrowser encrypt = new EncryptDataForRecipientsInBrowser();
        encrypt.execute();
    }

    public void execute() throws Exception {

        final boolean createKeys = false;
        final boolean deleteKeys = false;

        try {

            // Чтение пользовательский ключей и сертификаторв открытых ключей

            prepare(PROVIDER, EXCHANGE_KEY_ALG, SIGN_ALG, createKeys, createKeys);

            // Шифрование данных на новом сессионном ключе

            EncryptedData encryptedData = encryptData("Данные для шифрования");

            // Шифрование сессионного ключа для двух получателей

            SecretKeyForRecipient alicaKey = prepareSecretKeyForRecipient(encryptedData.sessionKey, alicaCert);
            SecretKeyForRecipient bobKey = prepareSecretKeyForRecipient(encryptedData.sessionKey, bobCert);

            // вывод результата для подстановки в браузере

            System.out.println("{\n" +
                "  \"exportedKey\": {\n" +
                "    \"alica\": {\"dn\":\"" + alicaKey.certDn + "\",\"key\":\"" + formatSecretKeyForBrowser(alicaKey) + "\"},\n" +
                "    \"bob\": {\"dn\":\"" + bobKey.certDn + "\",\"key\":\"" + formatSecretKeyForBrowser(bobKey) + "\"}\n" +
                "  },\n" +
                "  \"encryptedData\": \"" + toHexBytesStr(encryptedData.encryptedData, "") + "\",\n" +
                "  \"oSesKeyIV\": \"" + toHexBytesStr(encryptedData.iv) + "\"\n" +
            "}");

        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (alicaPrivate != null) {
                ((GostPrivateKey) alicaPrivate).clear();
            }
            if (bobPrivate != null) {
                ((GostPrivateKey) bobPrivate).clear();
            }
            // Удаление контейнеров.
            clear(deleteKeys);
        }
    }

    private String formatSecretKeyForBrowser(SecretKeyForRecipient keyForRecipient) throws Exception {

        StringBuilder resultKey = new StringBuilder();

        // Первая часть ключа

        char[] firstKeyPartChars = CryptParamsSpec.OID_Gost28147_89_Rosstandart_TC26_Z_ParamSet.toString().toCharArray();
        byte[] firstKeyPartBytes = new byte[firstKeyPartChars.length];
        for (int i = 0; i < firstKeyPartBytes.length; i++) {
            firstKeyPartBytes[i] = (byte) firstKeyPartChars[i];
        }

        resultKey.append(toHexBytesStr(firstKeyPartBytes));
        resultKey.append(':');

        // Вторая часть ключа. Публичный эфемерный ключ

        byte[] ephPublicBlob = ((PublicKeySpec)(((GostPublicKey) keyForRecipient.ephPublicKey)).getSpec()).getBlob();
        resultKey.append(toHexBytesStr(ephPublicBlob));
        resultKey.append(':');

        // Третья часть ключа. Секретный сессионный ключ

        resultKey.append(toHexBytesStr(new int[] {
            0x01, // bType = SIMPLEBLOB
            0x20, // bVersion = 0x20
            0x00, 0x00, // reserved
            0x1E, 0x66, 0x00, 0x00, // KeyAlg = CALG_G28147
            0xFD, 0x51, 0x4A, 0x37, // Magic = GR3410_1_MAGIC
            0x1E, 0x66, 0x00, 0x00 // EncryptKeyAlgId = CALG_G28147
        })).append(" ");

        Asn1BerDecodeBuffer wrappedSessionKeyBuf = new Asn1BerDecodeBuffer(keyForRecipient.wrappedKey);
        Gost28147_89_EncryptedKey gostEncryptedKey = new Gost28147_89_EncryptedKey();
        gostEncryptedKey.decode(wrappedSessionKeyBuf);

        resultKey.append(toHexBytesStr(keyForRecipient.ukm)).append(" ");
        resultKey.append(toHexBytesStr(gostEncryptedKey.encryptedKey.value)).append(" ");
        resultKey.append(toHexBytesStr(gostEncryptedKey.macKey.value)).append(" ");
        resultKey.append(toHexBytesStr(oidToAsn1SeqBytes(CryptParamsSpec.OID_Gost28147_89_Rosstandart_TC26_Z_ParamSet)));

        return resultKey.toString();
    }

    private SecretKeyForRecipient prepareSecretKeyForRecipient(SecretKey sessionKey, Certificate recipientCert) throws Exception {

        PublicKey recipientPublicKey = jspToJcspKey(recipientCert.getPublicKey());

        SecureRandom random = SecureRandom.getInstance(JCP.CP_RANDOM, PROVIDER);

        // Создание эфемерного ключа нужного типа
        // Инициализируется параметрами открытого ключа получателя

        KeyPairGenerator kpg = KeyPairGenerator.getInstance(EPHEMERAL_KEY_ALG, PROVIDER);
        kpg.initialize(X509PublicKeySpec.fromKey(recipientPublicKey));
        KeyPair ephPair = kpg.generateKeyPair();

        // Создается UKM

        byte[] ukm = new byte[8];
        random.nextBytes(ukm);

        // Согласование ключей

        KeyAgreement keyAgreement = KeyAgreement.getInstance(EXCHANGE_KEY_ALG, PROVIDER);

        keyAgreement.init(ephPair.getPrivate(), new IvParameterSpec(ukm), null);
        keyAgreement.doPhase(recipientPublicKey, true);

        SecretKey agreeKey = keyAgreement.generateSecret(CryptoProvider.GOST_CIPHER_NAME);

        // Экспорт сессионного ключа.

        Cipher keyCipher = Cipher.getInstance(WRAP_KEY_ALG, PROVIDER);
        keyCipher.init(Cipher.WRAP_MODE, agreeKey);

        byte[] wrappedSessionKey = keyCipher.wrap(sessionKey);

        X509Certificate cert509 = (X509Certificate) recipientCert;
        return new SecretKeyForRecipient(wrappedSessionKey, ukm, ephPair.getPublic(), cert509.getSubjectDN().getName());
    }

    private static class SecretKeyForRecipient {

        final byte[] wrappedKey;
        final byte[] ukm;
        final PublicKey ephPublicKey;
        final String certDn;

        public SecretKeyForRecipient(byte[] wrappedKey, byte[] ukm, PublicKey ephPublicKey, String certDn) {
            this.wrappedKey = wrappedKey;
            this.ukm = ukm;
            this.ephPublicKey = ephPublicKey;
            this.certDn = certDn;
        }
    }

    private EncryptedData encryptData(String data) throws Exception {

        KeyGenerator kg = KeyGenerator.getInstance(JCSP.GOST_CIPHER_NAME, PROVIDER);
        kg.init(CryptParamsSpec.getInstance(CryptParamsSpec.Rosstandart_TC26_Z));

        SecretKey sessionKey = kg.generateKey();
        SecureRandom random = SecureRandom.getInstance(JCP.CP_RANDOM, PROVIDER);
        byte[] cipherIv = new byte[8];
        random.nextBytes(cipherIv);

        Cipher cipher = Cipher.getInstance(DATA_CIPHER_ALG, PROVIDER);
        cipher.init(Cipher.ENCRYPT_MODE, sessionKey, new IvParameterSpec(cipherIv));

        byte[] encryptedData = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));

        return new EncryptedData(encryptedData, sessionKey, cipherIv);
    }

    private static class EncryptedData {

        final byte[] encryptedData;
        final SecretKey sessionKey;
        final byte[] iv;

        public EncryptedData(byte[] encryptedData, SecretKey sessionKey, byte[] iv) {
            this.encryptedData = encryptedData;
            this.sessionKey = sessionKey;
            this.iv = iv;
        }
    }

    // utils

    private String toHexBytesStr(int[] bytes) {
        byte[] byteBytes = new byte[bytes.length];
        for (int i = 0; i < bytes.length; i++) {
            byteBytes[i] = (byte)(bytes[i] & 0xFF);
        }
        return toHexBytesStr(byteBytes);
    }

    private String toHexBytesStr(byte[] bytes) {
        return toHexBytesStr(bytes, " ");
    }

    private String toHexBytesStr(byte[] bytes, String delim) {

        StringBuilder str = new StringBuilder();
        for (byte b : bytes) {
            String hexByteStr = Integer.toHexString(((int) b) & 0xFF);
            str.append(hexByteStr.length() == 1 ? "0" + hexByteStr : hexByteStr);
            str.append(delim);
        }
        if (str.length() > 0) {
            str.setLength(str.length() - delim.length());
        }
        return str.toString().toUpperCase();
    }

    private byte[] oidToAsn1SeqBytes(OID oid) throws Exception {

        Asn1ObjectIdentifier asn1ObjId = new Asn1ObjectIdentifier(oid.value);
        Asn1DerEncodeBuffer encodeBuffer = new Asn1DerEncodeBuffer();

        asn1ObjId.encode(encodeBuffer);
        byte[] mainBytes = encodeBuffer.getMsgCopy();
        encodeBuffer.reset();

        encodeBuffer.encodeTagAndLength(Asn1Tag.SEQUENCE, mainBytes.length);
        byte[] headerBytes = encodeBuffer.getMsgCopy();

        byte[] result = new byte[headerBytes.length + mainBytes.length];

        System.arraycopy(headerBytes, 0, result, 0, headerBytes.length);
        System.arraycopy(mainBytes, 0, result, headerBytes.length , mainBytes.length);

        return result;
    }

    private PublicKey jspToJcspKey(PublicKey key) throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance(key.getAlgorithm(), PROVIDER);
        X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(key.getEncoded());
        return keyFactory.generatePublic(pubKeySpec);
    }

    // certificates and private keys params

    @Override
    protected String getAlicaAlias() {
        return "ce_alica";
    }

    @Override
    protected char[] getAlicaPassword() {
        return "ce_alica".toCharArray();
    }

    @Override
    protected String getBobAlias() {
        return "ce_bob";
    }

    @Override
    protected char[] getBobPassword() {
        return "ce_bob".toCharArray();
    }

    @Override
    public void execute(String pairProvider,
                        String agreeProvider,
                        String simProvider,
                        CryptParamsInterface simParams,
                        String exchKeyAlgorithm,
                        String wrapAlgorithm,
                        String signAlgorithm,
                        boolean create,
                        boolean delete) {
    }
}


Код:

var CAPICOM_CURRENT_USER_STORE = 2;
var CAPICOM_MY_STORE = "My";
var CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED = 2;

var RECIPIENT_USERNAME = "alica"; // alica или bob

(function Decrypt() {

    cadesplugin.async_spawn(function* () {

        const data = {
          "exportedKey": {
            "alica":{"dn":"CN=ce_alica, O=CryptoPro, C=RU","key":"31 2E 32 2E 36 34 33 2E 37 2E 31 2E 32 2E 35 2E 31 2E 31:06 20 00 00 3D 2E 00 00 4D 41 47 31 00 04 00 00 30 15 06 09 2A 85 03 07 01 02 01 02 01 06 08 2A 85 03 07 01 01 02 03 F7 73 5F BF 44 51 E8 61 4A F2 6F F6 BA 12 11 C8 81 B7 DD E9 BC 72 28 03 5F 52 92 A8 DC E9 E5 08 DD 54 FE FA 91 60 34 18 0D 6B FA 5D 3F 01 8F 81 C0 6B 30 C0 D8 0B D3 19 D8 3C 64 CA 8F FE 67 8B 55 0C 1E 34 18 55 2A EC F3 5E 94 2F 1F CC A4 CC EB D3 32 72 23 19 76 B7 1F 21 1A 6F 6D D1 AD 80 A6 01 2C 3E 66 ED 36 73 7F DB A3 97 06 C3 74 67 E2 AD FD 82 D5 DB 00 6A 3F 8D 4E ED CC 64 0D C3:01 20 00 00 1E 66 00 00 FD 51 4A 37 1E 66 00 00 CA 82 F4 5C 67 8B E4 8E 32 40 91 C3 E6 2B 19 BD 59 82 81 CC 2C 7B A1 63 D5 1D 5A 5E FE 28 5F 57 E2 87 50 94 CD E6 BC 7E B9 1B 61 1C 30 0B 06 09 2A 85 03 07 01 02 05 01 01"},
            "bob":{"dn":"CN=ce_bob, O=CryptoPro, C=RU","key":"31 2E 32 2E 36 34 33 2E 37 2E 31 2E 32 2E 35 2E 31 2E 31:06 20 00 00 3D 2E 00 00 4D 41 47 31 00 04 00 00 30 15 06 09 2A 85 03 07 01 02 01 02 01 06 08 2A 85 03 07 01 01 02 03 3B 30 90 3D C9 A0 7C 61 D6 33 C9 0E 7D B0 1D 61 3B 18 20 FA 8D 71 36 19 75 BE 23 28 4A 61 DF 0F E0 83 61 F9 BC B6 A4 F1 B1 FF C7 20 7D F4 B6 D9 C4 47 73 0E FD 1F DF BA A8 CB C8 B6 40 3A 60 E4 1E CA 43 5A 05 CD 97 AC 19 B3 18 80 5E B7 D2 8C D1 4D 25 17 95 E6 52 02 FC 21 74 4C 11 0F 4D 1B 14 A6 F4 59 7B F4 AD 34 75 11 5D FD 44 6D EC 37 AC 6F E8 41 3F 52 36 0C 2D CF F4 CC 9E 02 98 FF:01 20 00 00 1E 66 00 00 FD 51 4A 37 1E 66 00 00 07 14 18 83 E1 88 85 34 DF 92 E7 C8 D0 E9 6C 19 25 29 12 E0 E6 16 E0 DF 12 34 C7 02 E2 87 C8 42 4E 54 1F DB D6 3D 7A 04 A3 85 70 2B 30 0B 06 09 2A 85 03 07 01 02 05 01 01"}
          },
          "encryptedData":"78962F709E1E05BB0D43ADDAC82317B813BBEC7D4F83F86705F25402026BA1AB3EF63DF683FF3D93",
          "oSesKeyIV":"A2 93 76 E1 F6 82 CF 6A"
        };

        const keyData = data.exportedKey[RECIPIENT_USERNAME];
        if (!keyData) {
            alert("Ключ для пользователя " + RECIPIENT_USERNAME + " не найден");
            return;
        }

        const oStore = yield cadesplugin.CreateObjectAsync("CAdESCOM.Store");
        yield oStore.Open(CAPICOM_CURRENT_USER_STORE, CAPICOM_MY_STORE, CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED);

        const allCertificates = yield oStore.Certificates;
        const allCertificatesCount = yield allCertificates.Count;

        console.log("Ищем сертификат с DN: '" + keyData.dn + "'");

        let certificate = null;
        for (let certIdx = 0; certIdx < allCertificatesCount; certIdx++) {
            const cert = yield allCertificates.Item(certIdx + 1);
            const subjectName = yield cert.SubjectName;
            if (subjectName === keyData.dn) {
                certificate = cert;
                break;
            }
        }

        if (certificate == null) {
            alert("Сертификат не найден " + keyData.dn);
            return;
        }

        const oSymAlgo = yield cadesplugin.CreateObjectAsync("CAdESCOM.SymmetricAlgorithm");
        yield oSymAlgo.ImportKey(keyData.key, certificate);
        yield oSymAlgo.propset_IV(data.oSesKeyIV);

        const resultBase64 = yield oSymAlgo.Decrypt(data.encryptedData, 1);
        console.log(Base64.decode(resultBase64));
    });
})()
Offline PavelSimonov  
#6 Оставлено : 6 июля 2021 г. 13:04:20(UTC)
PavelSimonov

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

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

Сказал(а) «Спасибо»: 2 раз
Всем Добрый день!

Подскажите пожалуйста ответ на еще один вопрос об обмене симметричными ключами между сервером и клиентом:

Возможна ли отправка симметричного ключа получателю с КриптоПро ЭЦП Browser plug-in используя сертификат с RSA ключом?

Шифрование с RSA ключом на тестовой странице показывает "Ошибка при шифровании данных:[object Object]" и пустое поле "Зашифрованный ключ для получателя"

https://www.cryptopro.ru...page/symalgo_sample.html
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.