Статус: Новичок
Группы: Участники
Зарегистрирован: 15.09.2015(UTC) Сообщений: 2
|
Привет, пытаюсь подписать pdf-файл на клиенте. Сервер: Java 1.8, пропатченный iTextPdf 5.1.3, bouncycastle Клиент: Browser Plug-in 2.0, КриптоПро 3.9. Проверка: Adobe Reader 11.0.12, Крипто Про PDF 1.6.0405 С клиента получаю сертификат: Цитата: var CAPICOM_ENCODE_BASE64 = 0; return oCertificate.Export(CAPICOM_ENCODE_BASE64);
На сервере формирую хэш по алгоритму ГОСТ (GOST3411) Цитата: InputStream stream = new ByteArrayInputStream(Base64.decodeBase64(certificate));
CertificateFactory factory = CertificateFactory.getInstance("X.509"); Certificate[] chain = new Certificate[1]; chain[0] = factory.generateCertificate(stream);
// we create a reader and a stamper PdfReader reader = new PdfReader(fileName); ByteArrayOutputStream baos = new ByteArrayOutputStream(); PdfStamper stamper = PdfStamper.createSignature(reader, baos, '\0');
// we create the signature appearance PdfSignatureAppearance sap = stamper.getSignatureAppearance(); sap.setCrypto(null, chain, null, PdfSignatureAppearance.CRYPTOPRO_SIGNED); sap.setReason("Document Sign"); sap.setLocation("CryptoPro"); sap.setProvider(BouncyCastleProvider.PROVIDER_NAME);
// we create the signature infrastructure PdfSignature dic = new PdfSignature(PdfSignatureAppearance.CRYPTOPRO_SIGNED, PdfName.ADBE_PKCS7_DETACHED); dic.setReason(sap.getReason()); dic.setLocation(sap.getLocation()); dic.setContact(sap.getContact()); dic.setDate(new PdfDate(sap.getSignDate())); sap.setCryptoDictionary(dic);
HashMap<PdfName, Integer> exc = new HashMap<PdfName, Integer>(); exc.put(PdfName.CONTENTS, 8192 * 2 + 2); sap.preClose(exc);
InputStream data = sap.getRangeStream();
// получение хэша алгоритмом GOST3411 MessageDigest md = MessageDigest.getInstance("GOST3411", BouncyCastleProvider.PROVIDER_NAME); byte hash[] = md.digest(IOUtils.toByteArray(data)); return Hex.encodeHexString(hash);
На клиенте подписываю этот хэш Цитата: var CADESCOM_HASH_ALGORITHM_CP_GOST_3411 = 100; var hashAlg = CADESCOM_HASH_ALGORITHM_CP_GOST_3411; // ГОСТ Р 34.11-94 // Создаем объект CAdESCOM.HashedData var oHashedData = InitializeHashedData(hashAlg, pdfData); // Создаем подписанное сообщение // Такая подпись должна проверяться в КриптоАРМ и cryptcp.exe var sSignedMessage = CreateSignature(oCertificate, oHashedData);
function InitializeHashedData(hashAlg, sHashValue) { // Создаем объект CAdESCOM.HashedData var oHashedData = CreateObject("CAdESCOM.HashedData");
// Инициализируем объект заранее вычисленным хэш-значением // Алгоритм хэширования нужно указать до того, как будет передано хэш-значение oHashedData.Algorithm = hashAlg; oHashedData.SetHashValue(sHashValue);
return oHashedData; }
function CreateSignature(oCertificate, oHashedData) { // Создаем объект CAdESCOM.CPSigner var oSigner = CreateObject("CAdESCOM.CPSigner"); oSigner.Certificate = oCertificate;
// Создаем объект CAdESCOM.CadesSignedData var oSignedData = CreateObject("CAdESCOM.CadesSignedData");
var sSignedMessage = "";
// Вычисляем значение подписи try { sSignedMessage = oSignedData.SignHash(oHashedData, oSigner, CADESCOM_CADES_BES, CAPICOM_ENCODE_BASE64); } catch (err) { alert("Failed to create signature. Error: " + GetErrorMessage(err)); return; }
return sSignedMessage; }
Подписанный хэш передаю на сервер и прикрепляю к pdf: Цитата: String signedHash.. // подписанный хэш PdfSignatureAppearance sap = pdfHash.getSignatureAppearance(); // из сессии byte[] hash = pdfHash.getHash(); // вычисленный хэш, берем из сессии ByteArrayOutputStream boas = ... // из сессии
PdfPKCS7 sgn = new PdfPKCS7(null, chain, null, "GOST3411", BouncyCastleProvider.PROVIDER_NAME, false); Calendar cal = Calendar.getInstance();
// we complete the PDF signing process sgn.setExternalDigest(Base64.decodeBase64(signedHash), null, "RSA"); byte[] encodedSig = sgn.getEncodedPKCS7(hash, cal); byte[] paddedSig = new byte[8192]; System.arraycopy(encodedSig, 0, paddedSig, 0, encodedSig.length); PdfDictionary dic2 = new PdfDictionary(); dic2.put(PdfName.CONTENTS, new PdfString(paddedSig).setHexWriting(true)); sap.close(dic2);
// we write the signed document to the HttpResponse output stream byte[] pdf = boas.toByteArray(); OutputStream out = new FileOutputStream("C:/Temp/exampleWithSign.pdf"); out.write(pdf, 0, pdf.length); out.close();
В результате формируется подписанный документ, когда открываю через Acrobat Reader пишет: Подпись действительна. Документ был изменен или поврежден с момента подписания. Сертификат является доверенным...Ну и соответственно вопрос: где может быть ошибка? кто-нибудь делал похожее и чтобы работало? какие варианты еще есть для решения такой задачи? Спасибо
|