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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline rmussalimov  
#1 Оставлено : 13 октября 2019 г. 15:24:31(UTC)
rmussalimov

Статус: Активный участник

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

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

Имеется PDF документ из которого необходимо собрать открепленную PKCS7 подпись.

Как это можно сделать при помощи JCP?

Прошу не предлагать лезть в samples.jar, т.к. это все-таки слишком тяжело.

Например, у BC все просто и понятно, кода буквально менее 10 строк

Цитата:
List certList = new ArrayList();
CMSTypedData msg = new CMSProcessableByteArray("Hello world!".getBytes());

certList.add(signCert);

Store certs = new JcaCertStore(certList);

CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").build(signKP.getPrivate());

gen.addSignerInfoGenerator(
new JcaSignerInfoGeneratorBuilder(
new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
.build(sha1Signer, signCert));

gen.addCertificates(certs);

CMSSignedData sigData = gen.generate(msg, false);


Есть ли какой-нибудь аналог того же самого, но только на JCP?

Или, на худой конец, возможно ли использовать KeyStore от JCP (главным образом взять PrivateKey при помощи JCP) и подписать с помощью него, используя BC, если сам процесс очень сложный на JCP?

Спасибо.

Отредактировано пользователем 13 октября 2019 г. 15:28:01(UTC)  | Причина: Не указана

Offline rmussalimov  
#2 Оставлено : 14 октября 2019 г. 9:05:52(UTC)
rmussalimov

Статус: Активный участник

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

Сказал(а) «Спасибо»: 4 раз
Нашел следующий метод для подписания

Цитата:
public static byte[] createPKCS7(byte[] data, PrivateKey privateKey,
X509Certificate certificate) throws Exception
{

// Получаем бинарную подпись длиной 64 байта.

final Signature signature = Signature.getInstance(AlgorithmUtils.getSignatureInstanceForJCP(certificate)); //hardcoded JCP.GOST_DHEL_SIGN_NAME
signature.initSign(privateKey);
signature.update(data);

final byte[] sign = signature.sign();

// Формируем контекст подписи формата PKCS7.

final ContentInfo all = new ContentInfo();
all.contentType = new Asn1ObjectIdentifier(
new OID(CMStools.STR_CMS_OID_SIGNED).value);

final SignedData cms = new SignedData();
all.content = cms;
cms.version = new CMSVersion(1);

// Идентификатор алгоритма хеширования.

String [] digestAndSignatureAlgorithms = AlgorithmUtils.getDigestSignatureAlgorithmOIDs(certificate);

cms.digestAlgorithms = new DigestAlgorithmIdentifiers(1);
final DigestAlgorithmIdentifier a = new DigestAlgorithmIdentifier(
new OID(digestAndSignatureAlgorithms[0]).value); //hardcoded CMStools.DIGEST_OID
a.parameters = new Asn1Null();
cms.digestAlgorithms.elements[0] = a;

// Т.к. подпись отсоединенная, то содержимое отсутствует.

cms.encapContentInfo = new EncapsulatedContentInfo(
new Asn1ObjectIdentifier(new OID(CMStools.STR_CMS_OID_DATA).value), null);

// Добавляем сертификат подписи.

cms.certificates = new CertificateSet(1);
final ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Certificate asnCertificate =
new ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Certificate();

final Asn1BerDecodeBuffer decodeBuffer =
new Asn1BerDecodeBuffer(certificate.getEncoded());
asnCertificate.decode(decodeBuffer);

cms.certificates.elements = new CertificateChoices[1];
cms.certificates.elements[0] = new CertificateChoices();
cms.certificates.elements[0].set_certificate(asnCertificate);

// Добавялем информацию о подписанте.

cms.signerInfos = new SignerInfos(1);
cms.signerInfos.elements[0] = new SignerInfo();
cms.signerInfos.elements[0].version = new CMSVersion(1);
cms.signerInfos.elements[0].sid = new SignerIdentifier();

final byte[] encodedName = certificate.getIssuerX500Principal().getEncoded();
final Asn1BerDecodeBuffer nameBuf = new Asn1BerDecodeBuffer(encodedName);
final Name name = new Name();
name.decode(nameBuf);

final CertificateSerialNumber num = new CertificateSerialNumber(
certificate.getSerialNumber());

cms.signerInfos.elements[0].sid.set_issuerAndSerialNumber(
new IssuerAndSerialNumber(name, num));
cms.signerInfos.elements[0].digestAlgorithm =
new DigestAlgorithmIdentifier(new OID(digestAndSignatureAlgorithms[0]).value); // hardcoded CMStools.DIGEST_OID
cms.signerInfos.elements[0].digestAlgorithm.parameters = new Asn1Null();
cms.signerInfos.elements[0].signatureAlgorithm =
new SignatureAlgorithmIdentifier(new OID(digestAndSignatureAlgorithms[1]).value); //hardcoded CMStools.SIGN_OID
cms.signerInfos.elements[0].signatureAlgorithm.parameters = new Asn1Null();
cms.signerInfos.elements[0].signature = new SignatureValue(sign);

// Получаем закодированную подпись.

final Asn1BerEncodeBuffer asnBuf = new Asn1BerEncodeBuffer();
all.encode(asnBuf, true);

return asnBuf.getMsgCopy();
}


Но что-то всегда пишет, что подпись невалидна

На вход подается следующее

Цитата:
createPKCS7(IOUtils.toByteArray(sap.getRangeStream()), key, signerCert);


sap.getRangeStream() - массив байт, подписанной PDFки. В чем может быть проблема?
Offline Санчир Момолдаев  
#3 Оставлено : 14 октября 2019 г. 19:31:28(UTC)
Санчир Момолдаев

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

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

Сказал(а) «Спасибо»: 88 раз
Поблагодарили: 223 раз в 211 постах
//hardcoded CMStools.DIGEST_OID
и т.д. по тексту. используются старые оиды.т.к. примеры старые. сама ключевая пара у вас скорее всего 2012-256.
необходимо поправить оиды
Техническую поддержку оказываем тут
Наша база знаний
Offline rmussalimov  
#4 Оставлено : 15 октября 2019 г. 9:32:19(UTC)
rmussalimov

Статус: Активный участник

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

Сказал(а) «Спасибо»: 4 раз
Автор: Санчир Момолдаев Перейти к цитате
//hardcoded CMStools.DIGEST_OID
и т.д. по тексту. используются старые оиды.т.к. примеры старые. сама ключевая пара у вас скорее всего 2012-256.
необходимо поправить оиды


Здравствуйте!

Проблема, вроде как, решилась частично.

В нашем проекте идет как и встроенная, так и открепленная подпись PDF документа.

Сначала PDF подписывается встроенной, а потом открепленной. Почему так было сделано, не очень понятно.

Тем не менее, если выбрать рандомный файл, получить из него массив байт - JCP без проблем его подписывает.

Думаю, тут больше вопрос к itext и их утилитам, а не к криптопро. (непонятно как получить массив байт из созданного и уже подписанного PDFника).

Хотя не исключаю ошибки в коде:

Цитата:
public void signPdf(InputStream is, String folder, String fileNameWoExtension) throws Exception
{
PrivateKey key = keyStore.getPrivateKey();
Certificate[] chain = new Certificate[1];
chain[0] = keyStore.getCertificate();

X509Certificate cert = (X509Certificate)chain[0];
Date notBefore = cert.getNotBefore();
Date notAfter = cert.getNotAfter();
String serial = cert.getSerialNumber().toString(16).toUpperCase();
String subject = PdfPKCS7.getSubjectFields(cert).getField("CN");
String number = fileNameWoExtension.replace("doc_", "");
// reader and stamper
PdfReader reader = new PdfReader(is);
FileOutputStream fout = new FileOutputStream(folder + File.separator + fileNameWoExtension + ".pdf");
PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0');

StampsCreator.createEdsStamp(folder, serial, subject, notBefore, notAfter);
StampsCreator.createRegisterStamp(folder, new Date(), number);

PdfContentByte pcb = stp.getOverContent(1);
Image imageEds = Image.getInstance(folder + File.separator + StampsCreator.EDS_STAMP);
imageEds.scaleAbsolute(200, 87);
imageEds.setAbsolutePosition(75, 80);
imageEds.setAnnotation(new Annotation(0, 0, 0, 0, 3));
pcb.addImage(imageEds);

Image imageReg = Image.getInstance(folder + File.separator + StampsCreator.REGNUMBER_STAMP);
imageReg.scaleAbsolute(207, 20);
int height = (int) Math.floor(reader.getPageSize(1).getHeight());
imageReg.setAbsolutePosition(70, height - 130);
imageReg.setAnnotation(new Annotation(0, 0, 0, 0, 3));
pcb.addImage(imageReg);

PdfSignatureAppearance sap = stp.getSignatureAppearance();
sap.setSignDate(new GregorianCalendar());
sap.setCrypto(null, chain, null, null);
sap.setAcro6Layers(true);
sap.setRenderingMode(PdfSignatureAppearance.RenderingMode.DESCRIPTION);
PdfSignature dic;
dic = new PdfSignature(PdfName.ADOBE_CryptoProPDF, PdfName.ADBE_PKCS7_DETACHED);
dic.setDate(new PdfDate(sap.getSignDate()));

dic.setName(subject);
dic.setReason("Signed with CryptoPro");
sap.setCryptoDictionary(dic);
int csize = 4000;
HashMap<PdfName,Integer> exc = new HashMap<PdfName,Integer>();
exc.put(PdfName.CONTENTS, new Integer(csize * 2 + 2));
sap.preClose(exc);
System.out.println("preclosed " + key.getClass().getName() + " " + key.getAlgorithm());

X509Certificate signerCert = (X509Certificate)chain[0];

byte [] pk = createPKCS7(IOUtils.toByteArray(sap.getRangeStream()), key, signerCert);
System.out.println("p7s data ready.");
byte[] outc = new byte[csize];
PdfDictionary dic2 = new PdfDictionary();
System.arraycopy(pk, 0, outc, 0, pk.length);
dic2.put(PdfName.CONTENTS, new PdfString(outc).setHexWriting(true));
System.out.println("signed ready.");
sap.close(dic2);
FileOutputStream fos = new FileOutputStream(folder + File.separator + fileNameWoExtension + ".p7s");
fos.write(pk);
fos.close();
}


По коду видно, что открепленная подпись кладется в оригинальный PDF файл. Не думаю, что это правильно.

Хотя опять же, вопрос не совсем к вам, но если знаете или можете помочь - буду благодарен!

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