Я пытаюсь реализовать подпись PDF-документа с помощью HSM, но не могу получить действительную подпись и больше не могу ошибаться. Я искал различные проблемы, которые существуют по этому поводу, но я не вижу проблемы с моим кодом.
Я использую следующие версии
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.9</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.47</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcmail-jdk15on</artifactId>
<version>1.47</version>
</dependency>
И мой код:
public byte[] getHash() throws Exception {
reader = new PdfReader(new ByteArrayInputStream(content));
baos = new ByteArrayOutputStream();
stamper = PdfStamper.createSignature(reader, baos, '\0');
sap = stamper.getSignatureAppearance();
sap.setReason("Test");
sap.setLocation("On a server!");
sap.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");
sap.setCertificate(x509Certificate);
dic = new PdfSignature(PdfName.ADOBE_PPKLITE, 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);
exc = new HashMap<PdfName, Integer>();
exc.put(PdfName.CONTENTS, new Integer(8192 * 2 + 2));
sap.preClose(exc);
externalDigest = new ExternalDigest() {
@Override
public MessageDigest getMessageDigest(String hashAlgorithm)
throws GeneralSecurityException {
return DigestAlgorithms.getMessageDigest(hashAlgorithm, null);
}
};
chain = new X509Certificate[1];
chain[0] = x509Certificate;
sgn = new PdfPKCS7(null, chain, "SHA256", null, externalDigest, false);
data = sap.getRangeStream();
cal = Calendar.getInstance();
hash = DigestAlgorithms.digest(data, externalDigest.getMessageDigest("SHA256"));
sh = sgn.getAuthenticatedAttributeBytes(hash, cal, null, null, CryptoStandard.CMS);
sh = DigestAlgorithms.digest(new ByteArrayInputStream(sh), externalDigest.getMessageDigest("SHA256"));
return sh;
}
public void complateToSignature(byte[] signedHash) throws Exception {
sgn.setExternalDigest(Base64.decode(signedHash), null, "RSA");
encodedSig = sgn.getEncodedPKCS7(hash, cal, null, null, null, CryptoStandard.CMS);
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);
byte[] pdf = baos.toByteArray();
FileUtils.saveFileContent(pdf, Paths.get("pathFileDest.pdf"));
}
Наконец, мой тестовый код:
private void signPdf(X509Certificate certificate){
File pdf = new File("C:\\File8888.pdf");
FileInputStream is;
byte[] content = new byte[0];
try {
is = new FileInputStream(pdf);
content = new byte[is.available()];
is.read(content);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
PDFSignature1 operation = new PDFSignature1(content, certificate);
byte[] hash = new byte[0];
String encodeData = "";
try {
hash = operation.getHash();
//simule control for mobile signature.
encodeData = com.itextpdf.text.pdf.codec.Base64.encodeBytes(hash);
if (encodeData.length() != 44) {
throw new Exception("Sign to data must be 44 characters");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
final String hashHex = toHex(encodeData);
final String hashSignat = signExternalService(hashHex);
try {
operation.complateToSignature(hashSignat.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
}
Нам не удалось увидеть, что мы ошибаемся в этом процессе.
Мы будем очень признательны за любую помощь или альтернативный способ выполнения процесса.
Спасибо.
KeyStore
? Почему вы не используете PKCS#11? Вы вообще читали документацию? Это — это то, как должен выглядеть ваш код. - person Bruno Lowagie   schedule 29.06.2016signDeferred()
, как описано в этот ответ. Технически вы не можете подписать PDF-файл без общедоступного сертификата, но вы можете заранее составить хеш, который необходимо подписать, и отправить этот хэш в HSM для подписи. - person Bruno Lowagie   schedule 30.06.2016signDeferred()
вам не нуженPrivateKey
в приложении, которое подписывает PDF. Вам просто нужно реализоватьExternalSignatureContainer
. В вашем случае эта реализация также не нуждается вPrivateKey
: ей просто нужно установить соединение с приложением, работающим на HSM, которое подписывает байты и возвращает подписанные байты. Я не понимаю, почему вы пишете Я читал на тему, что вы со мной столкнулись, это PrivateKey. Я уважаю людей, для которых английский язык не является родным (я не являюсь носителем английского языка либо), но это предложение не имеет для меня никакого смысла. - person Bruno Lowagie   schedule 30.06.2016