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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline Nobert  
#1 Оставлено : 2 июня 2020 г. 16:18:47(UTC)
Nobert

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

Группы: Участники
Зарегистрирован: 02.06.2020(UTC)
Сообщений: 3

Товарищи, от заказчика поступает файл, в котором base64 с зашифрованным текстовым содержимым, проблема возникает после расшифровки, получается вот такой текст

Цитата:
u~+OC ¹8~Wq_Ӄ^S)RC/a;wƱHZ^osevOB#j̎&xȢ2£
j2C e-E@t:s0oukMwOk̞|
$9]VZ 6@"P&wKß0T!Cޒ&k)Ob:.s;Uwh@I%E.-]c3;5'()cep-T$m&R xn
h_qUs]\Ja&Űht
n*S>0*`8XzEBAz
0YP


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

Цитата:


IvParameterSpec sv = new IvParameterSpec(ivKey); // ivKey вычитывается из присылаемого файла
IvParameterSpec iv = new IvParameterSpec(ivData); // ivDataвычитывается из присылаемого файла
KeyAgreement keyAgree = KeyAgreement.getInstance("GOST3410DHEL");
keyAgree.init(privateKey, CryptParamsSpec.getInstance(CryptParamsSpec.Rosstandart_TC26_Z)); // privateKey приватный ключ, полученный из моего крипто контейнера HDImage
keyAgree.doPhase(publicKey, true); // publicKey - сертификат заказчика
SecretKey secretKey = keyAgree.generateSecret("GOST28147");
Cipher cipher = Cipher.getInstance("GOST28147/PRO_EXPORT/NoPadding");
Gost28147_89_EncryptedKey ek = new Gost28147_89_EncryptedKey();
ek.encryptedKey = new Gost28147_89_Key(encryptSymKey); // encryptSymKey вычитывается из присылаемого файла
ek.macKey = new Gost28147_89_MAC(macSymKey); // macSymKeyвычитывается из присылаемого файла
Asn1BerEncodeBuffer ebuf = new Asn1BerEncodeBuffer();
ek.encode(ebuf);
byte[] wrap = ebuf.getMsgCopy();
cipher.init(4, secretKey, sv);
SecretKey key_ = (SecretKey) cipher.unwrap(wrap, null, 3);
cipher = Cipher.getInstance("GOST28147");
cipher.init(2, key_, iv);
return String.valueOf(cipher.doFinal(data)); // data - раскодированное содержимое из base64


1) Правильный ли приватный ключ используется? Или надо использовать ключ со стороны заказчика?
2) Правильный ли публичный ключ используется или надо брать свой сертификат из своего крипто контейнера?
3) Какие симптомы кривоты после расшифровки? В какую сторону копать? Не исключена ошибка при шифровании на стороне заказчика
Offline Евгений Афанасьев  
#2 Оставлено : 2 июня 2020 г. 18:34:35(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 690 раз в 651 постах
Здравствуйте.
Не уверен, что publicKey правильно описан "publicKey - сертификат заказчика", скорее всего, publicKey - открытый ключ из сообщения?
Если wrap импортирован на указанном secretKey в key_, то сессионный ключ валиден.

Вы уверены, что расшифрованное сообщение не должно быть таким?
Исходное сообщение имеется, сравнивали?

String.valueOf(cipher.doFinal(data)) из байтов сделает строку, а не base64.
Если все-таки не сходится, то остаются iv для cipher (если iv неверный) или режим шифрования (нужен не GOST28147, а, допустим, GOST28147/CFB/NoPadding и т.п.) или идентификатор параметров шифрования (узел земены).

Отредактировано пользователем 3 июня 2020 г. 11:08:21(UTC)  | Причина: Не указана

Offline Nobert  
#3 Оставлено : 2 июня 2020 г. 18:45:16(UTC)
Nobert

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

Группы: Участники
Зарегистрирован: 02.06.2020(UTC)
Сообщений: 3

Автор: Евгений Афанасьев Перейти к цитате
Здравствуйте.
Не уверен, что publicKey правильно описан "publicKey - сертификат заказчика", скорее всего, publicKey - открытый ключ из сообщения?
Если wrap импортирован на указанном secretKey в key_, то сессионный ключ валиден.

Вы уверены, что расшифрованное сообщение не должно быть таким?
Исходное сообщение имеется, сравнивали?

String.valueOf(cipher.doFinal(data)) из байтов сделает строку, а не base64.
Если все-таки не сходится, то остаются iv для cipher (если iv неверный) или режим шифрования (нужен не GOST28147, а, допустим, GOST28147/CFB/NoPadding и т.п.).




publicKey получается таким образом

Цитата:

KeyStore trustStore = KeyStore.getInstance("CertStore");
trustStore.load(new FileInputStream(pathToTrustStore), password);

return (X509Certificate) trustStore.getCertificate(alias);


То есть это сертификат, который передал заказчик и он был импортирован в созданный truststore JCP

Можете уточнить, что значит импортирован на указанном secretKey в key_

Вот пример кода, которым заказчик на своей стороне шифрует

Цитата:

KeyGenerator kg = KeyGenerator.getInstance("GOST28147");
SecretKey key = kg.generateKey();
KeyAgreement keyAgree = KeyAgreement.getInstance("GOST3410_2012_256");
keyAgree.init(senderPrivateKey, sv, (SecureRandom) null);
keyAgree.doPhase(receiverPublicKey, true);
SecretKey secretKey = keyAgree.generateSecret("GOST28147");
Cipher cipher = Cipher.getInstance("GOST28147/PRO_EXPORT/NoPadding");
cipher.init(javax.crypto.Cipher.WRAP_MODE, secretKey, sv);
byte[] wrap = cipher.wrap(key);
Asn1BerDecodeBuffer buf = new Asn1BerDecodeBuffer(wrap);
Gost28147_89_EncryptedKey ek = new Gost28147_89_EncryptedKey();
ek.decode(buf);
Gost28147_89_Key enk = ek.encryptedKey;
Gost28147_89_MAC mac = ek.macKey;
cipher = Cipher.getInstance("GOST28147");
cipher.init(1, key, iv);
byte[] encr = cipher.doFinal(data);


В своем примере не правильно указал гост, используется GOST3410_2012_256 а не GOST3410DHEL

Больше всего подозреваю, что неправильно беру privateKey и publicKey. Можете прояснить на уровне контейнеров HDImage в крипто про, какой приватный и какой публичный ключ надо использовать?

Отредактировано пользователем 2 июня 2020 г. 18:50:10(UTC)  | Причина: Не указана

Offline Евгений Афанасьев  
#4 Оставлено : 3 июня 2020 г. 11:30:02(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 690 раз в 651 постах
Есть отправитель сообщения (S) и получатель сообщения (R). S обладает сертификатом R. S шифрует в адрес R таким образом: создает эфемерный ключ EK, делает согласование закрытым ключом EK с открытым ключом из сертификата R и получает ключ согласования AK. Создает сессионный секретный ключ SK, шифрует исходные данные, экспортирует SK на ключе AK во wrap. Отдает R набор: wrap, зашифрованные данные, IV, открытый ключ EK и т.п. На своей стороне R читает свой закрытый ключ K, вырабатывает с K и открытым ключом EK тот же ключ AK. Затем импортирует на нем wrap, получает SK. Расшифровывает зашифрованный текст.
Низкоуровневый пример: PKCS7EnvEphTransport в samples-sources.jar/CMS_samples
Высокоуровневые примеры (Enveloped CMS): EnvelopedDataAsByteArrayExample или EnvelopedCMSAsByteArrayExample в samples-sources.jar/CAdES/enveloped

В вашей схеме, видимо, не используется эфемерный ключ.
publicKey - сертификат заказчика. То есть заказчик тогда шифровал в ваш адрес аналогичным образом.
Если сессионный ключ импортировался, значит, он корректен.
Проблема, видимо, при расшифровании:

  • убедитесь, что расшифрованные данные должны быть иными (предполагается base64, но байты выводятся, как String)
  • iv для cipher - если iv неверный
  • режим шифрования - может, нужен не GOST28147, а, допустим, GOST28147/<тут_режим>/<тут_выравнивание>
  • идентификатор параметров шифрования (узел замены)


Попробуйте передать узел замены такой:
Код:

...
OID cipherOID = CryptParamsSpec.OID_Gost28147_89_Rosstandart_TC26_Z_ParamSet; // попробовать другой OID
GostCipherSpec spec = new GostCipherSpec(iv, cipherOID);
cipher.init(2, key_, spec, null);
byte[] decrypted = cipher.doFinal(data);
...

Вообще, лучше использовать что-то из предложенных выше примеров.

Отредактировано пользователем 3 июня 2020 г. 15:32:02(UTC)  | Причина: Не указана

thanks 1 пользователь поблагодарил Евгений Афанасьев за этот пост.
Санчир Момолдаев оставлено 08.06.2020(UTC)
Offline Nobert  
#5 Оставлено : 8 июня 2020 г. 17:57:34(UTC)
Nobert

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

Группы: Участники
Зарегистрирован: 02.06.2020(UTC)
Сообщений: 3

Автор: Евгений Афанасьев Перейти к цитате
Есть отправитель сообщения (S) и получатель сообщения (R). S обладает сертификатом R. S шифрует в адрес R таким образом: создает эфемерный ключ EK, делает согласование закрытым ключом EK с открытым ключом из сертификата R и получает ключ согласования AK. Создает сессионный секретный ключ SK, шифрует исходные данные, экспортирует SK на ключе AK во wrap. Отдает R набор: wrap, зашифрованные данные, IV, открытый ключ EK и т.п. На своей стороне R читает свой закрытый ключ K, вырабатывает с K и открытым ключом EK тот же ключ AK. Затем импортирует на нем wrap, получает SK. Расшифровывает зашифрованный текст.
Низкоуровневый пример: PKCS7EnvEphTransport в samples-sources.jar/CMS_samples
Высокоуровневые примеры (Enveloped CMS): EnvelopedDataAsByteArrayExample или EnvelopedCMSAsByteArrayExample в samples-sources.jar/CAdES/enveloped

В вашей схеме, видимо, не используется эфемерный ключ.
publicKey - сертификат заказчика. То есть заказчик тогда шифровал в ваш адрес аналогичным образом.
Если сессионный ключ импортировался, значит, он корректен.
Проблема, видимо, при расшифровании:

  • убедитесь, что расшифрованные данные должны быть иными (предполагается base64, но байты выводятся, как String)
  • iv для cipher - если iv неверный
  • режим шифрования - может, нужен не GOST28147, а, допустим, GOST28147/<тут_режим>/<тут_выравнивание>
  • идентификатор параметров шифрования (узел замены)


Попробуйте передать узел замены такой:
Код:

...
OID cipherOID = CryptParamsSpec.OID_Gost28147_89_Rosstandart_TC26_Z_ParamSet; // попробовать другой OID
GostCipherSpec spec = new GostCipherSpec(iv, cipherOID);
cipher.init(2, key_, spec, null);
byte[] decrypted = cipher.doFinal(data);
...

Вообще, лучше использовать что-то из предложенных выше примеров.


понял что вы имеете ввиду, прислал не актуальный блок кода, вот актуальный (отметил исправления)

Цитата:

IvParameterSpec sv = new IvParameterSpec(ivKey); // ivKey вычитывается из присылаемого файла
IvParameterSpec iv = new IvParameterSpec(ivData); // ivData вычитывается из присылаемого файла
KeyAgreement keyAgree = KeyAgreement.getInstance("GOST3410_2012_256");
keyAgree.init(privateKey, sv, null);
keyAgree.doPhase(publicKey, true); // publicKey - сертификат заказчика
SecretKey secretKey = keyAgree.generateSecret("GOST28147");
Cipher cipher = Cipher.getInstance("GOST28147/PRO_EXPORT/NoPadding");
Gost28147_89_EncryptedKey ek = new Gost28147_89_EncryptedKey();
ek.encryptedKey = new Gost28147_89_Key(encryptSymKey); // encryptSymKey вычитывается из присылаемого файла
ek.macKey = new Gost28147_89_MAC(macSymKey); // macSymKeyвычитывается из присылаемого файла
Asn1BerEncodeBuffer ebuf = new Asn1BerEncodeBuffer();
ek.encode(ebuf);
byte[] wrap = ebuf.getMsgCopy();
cipher.init(4, secretKey, sv);
SecretKey key_ = (SecretKey) cipher.unwrap(wrap, null, 3);
cipher = Cipher.getInstance("GOST28147");
cipher.init(2, key_, iv);
return new String(cipher.doFinal(envelop.getEncryptData())); // data - раскодированное содержимое из base64


Заметил, что при использовании неверного сертификата может выскакивать ошибка. Но в этом случае расшифровывается без ошибок, но с кривыми символами.
Режим шифрования точно GOST3410_2012_256.
Точно должно расшифровываться в читаемый текст.
Может ли быть проблема, что используется GOST3410_2012_256, а заказчик шифрует GOST3410DH_2012_256?
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.