Статус: Новичок
Группы: Участники
Зарегистрирован: 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?
|