Статус: Новичок
Группы: Участники
Зарегистрирован: 26.03.2020(UTC) Сообщений: 5 
|
Здравствуйте! Пытаюсь подписать, зашифровать отчет по Форме 4 через CryptoPro JCP и отправить в ФСС через их веб-сервис. Тестовый шлюз ФСС - http://docs-test.fss.ru/Тестовую ЭЦП получил здесь https://www.cryptopro.ru/certsrv/Сертификат ФСС, которым шифрую подписанный отчет:  fss2012Test.zip (2kb) загружен 3 раз(а).Когда подписываю и шифрую через их программу https://fss.ru/ru/fund/download/55833/index.shtml, потом полученный файл  Zashifrovannyjj cherez FSS.zip (4kb) загружен 2 раз(а). загружаю вручную через http://docs-test.fss.ru/home/upload, то выдает ошибку "-41. Нет доверия к издателю сертификата". То есть файл расшифровывается, а ЭЦП проверку не проходит. Вроде логично. Теперь пытаюсь подписать и зашифровать файл через JCP следующим образом: подпись файла тестовой ЭЦП Код:private byte[] signDoc(String keyPairAlgorithm, String keyProvider,
String signAlgorithm, String signProvider, String certName,
String signMethod, String digestMethod, File testDoc, String signDoc)
throws Exception {
// инициализация объекта чтения XML-документа
final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// установка флага, определяющего игнорирование пробелов в содержимом элементов при обработке XML-документа
dbf.setIgnoringElementContentWhitespace(true);
// установка флага, определяющего преобразование узлов CDATA в текстовые узлы при обработке XML-документа
dbf.setCoalescing(true);
// установка флага, определяющего поддержку пространств имен при обработке XML-документа
dbf.setNamespaceAware(true);
// загрузка содержимого подписываемого документа на основе установленных флагами правил
final DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
final Document doc;
doc = documentBuilder.parse(getClass()
.getResourceAsStream("/5205022875_2019_12.xml"));
/* Добавление узла подписи <ds:Signature> в загруженный XML-документ */
// инициализация объекта формирования ЭЦП в соответствии с алгоритмом ГОСТ Р 34.10-2001
final XMLSignature sig = new XMLSignature(doc, "", signMethod);
// получение корневого узла XML-документа
final Element anElement = doc.getDocumentElement();
// добавление в корневой узел XML-документа узла подписи
anElement.appendChild(sig.getElement());
/* Определение правил работы с XML-документом и добавление в узел подписи этих правил */
// создание узла преобразований <ds:Transforms> обрабатываемого XML-документа
final Transforms transforms = new Transforms(doc);
// добавление в узел преобразований правил работы с документом
transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE);
transforms.addTransform(Transforms.TRANSFORM_C14N_WITH_COMMENTS);
// добавление в узел подписи ссылок (узла <ds:Reference>), определяющих правила работы с
// XML-документом (обрабатывается текущий документ с заданными в узле <ds:Transforms> правилами
// и заданным алгоритмом хеширования)
sig.addDocument("", transforms, digestMethod);
/* Создание подписи всего содержимого XML-документа на основе закрытого ключа, заданных правил и алгоритмов */
KeyStore keyStore = KeyStore.getInstance(JCP.HD_STORE_NAME, JCP.PROVIDER_NAME);
keyStore.load(null, null);
PrivateKey key = (PrivateKey)keyStore.getKey(containerName, containerPass == null ? null : containerPass.toCharArray());
Certificate[] chain = keyStore.getCertificateChain(containerName);
// создание внутри узла подписи узла <ds:KeyInfo> информации об открытом ключе на основе
// сертификата
sig.addKeyInfo((X509Certificate)chain[0]);
// создание подписи XML-документа
sig.sign(key);
/* Сохранение подписанного XML-документа в файл */
// определение потока, в который осуществляется запись подписанного XML-документа
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// инициализация объекта копирования содержимого XML-документа в поток
final TransformerFactory tf = TransformerFactory.newInstance();
// создание объекта копирования содержимого XML-документа в поток
final Transformer trans = tf.newTransformer();
// копирование содержимого XML-документа в поток
trans.transform(new DOMSource(doc), new StreamResult(baos));
byte[] signedBytes = baos.toByteArray();
baos.close();
// шифрование ключом ФСС
CertificateFactory cf = CertificateFactory.getInstance("X509");
Certificate cer = cf.generateCertificate(getClass()
.getResourceAsStream("/fss2012Test.cer"));
return PKCS7EnvEphTransport.encryptPKCS7((X509Certificate) cer, signedBytes);
}
шифрование подписанного файла ключом ФСС: Код:public static byte[] encryptPKCS7(X509Certificate recipientCert, byte[] pkcs7) throws Exception {
final PublicKey recipientPublic = recipientCert.getPublicKey();
// Генерирование симметричного ключа с параметрами
// шифрования из контрольной панели.
final KeyGenerator kg = KeyGenerator.getInstance(CMStools.SEC_KEY_ALG_NAME, CRYPT_PROVIDER_NAME);
final ParamsInterface paramss = AlgIdSpec.getDefaultCryptParams();
kg.init(CryptParamsSpec.getInstance(CryptParamsSpec.Rosstandart_TC26_Z));
final SecretKey simm = kg.generateKey();
// Зашифрование текста на симметричном ключе.
Cipher cipher = Cipher.getInstance(CIPHER_MODE, CRYPT_PROVIDER_NAME);
cipher.init(Cipher.ENCRYPT_MODE, simm, (SecureRandom) null);
final byte[] iv = cipher.getIV();
final byte[] text = cipher.doFinal(pkcs7, 0, pkcs7.length);
// Зашифрование симметричного ключа.
final byte[] keyTransport = wrap(simm, recipientPublic);
// Формирование CMS-сообщения.
final ContentInfo all = new ContentInfo();
all.contentType = new Asn1ObjectIdentifier(new OID(CMStools.STR_CMS_OID_SIGNED).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 AlgIdInterface algid = new AlgIdSpec(JCP.GOST_EL_KEY_OID);
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 = 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());
keytrans.rid.set_issuerAndSerialNumber(issuer);
dbuf.reset();
keytrans.encryptedKey = new EncryptedKey(keyTransport);
ebuf.reset();
cms.recipientInfos.elements[0].set_ktri(keytrans);
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 params = new Gost28147_89_Parameters();
params.iv = new Gost28147_89_IV(iv);
params.encryptionParamSet = new Gost28147_89_ParamSet(paramss.getOID().value);
cms.encryptedContentInfo.contentEncryptionAlgorithm = new ContentEncryptionAlgorithmIdentifier(
_Gost28147_89_EncryptionSyntaxValues.id_Gost28147_89, params);
cms.encryptedContentInfo.encryptedContent = new EncryptedContent(text);
all.encode(ebuf);
return ebuf.getMsgCopy();
}
Потом полученный массив байтов отправляю через веб-сервис в ФСС, т.е. SOAP конверт сам не формирую: Код:GatewayService gatewayService = new GatewayService();
IGatewayService service = gatewayService.getBasicHttpBindingIGatewayService();
UploadResult result = service.sendFile(encryptedBytes, "E_" + fileName + ".ef4");
В результате возвращается ошибка "-10. He удалось расшифровать". Т.е. до проверки ЭЦП даже не доходит. Если таким же образом отправляю файл, полученный через программу ФСС, выдает ошибку -41 также, как и через веб-интерфейс. Файл, который получается после шифрования в JCP:  Posle shifrovanija v JCP.zip (5kb) загружен 4 раз(а).Подскажите, как правильно зашифровать ключом ФСС подписанный файл?
|