我想从第三方时间服务器添加时间戳到文件。当在acrobat或其他pdf查看器中打开pdf时,我想查看签名卡或任何其他文件中的时间戳信息。此外,我想可视化的时间戳图形作为图像或文本在pdf与时间戳。
我从时间服务器获取token:
import org.bouncycastle.tsp.TimeStampResponse;
import org.bouncycastle.tsp.TimeStampToken;
...
public TimeStampToken getTimeStampToken(){
...
return response.getTimeStampToken();
}现在如何使用pdf box将时间戳添加到pdf?
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
...
public static void addTimeStamp(final File pdfFile, final File signedPdfFile, TimeStampToken token) {
try (
FileInputStream fis1 = new FileInputStream(pdfFile);
FileOutputStream fos = new FileOutputStream(signedPdfFile);
FileInputStream fis = new FileInputStream(signedPdfFile);
PDDocument doc = PDDocument.load(pdfFile)) {
int readCount;
final byte[] buffer = new byte[8 * 1024];
while ((readCount = fis1.read(buffer)) != -1) {
fos.write(buffer, 0, readCount);
}
final PDSignature signature = new PDSignature();
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
signature.setName("NAME");
signature.setLocation("LOCATION");
signature.setReason("REASON");
signature.setSignDate(Calendar.getInstance());
doc.addSignature(signature);
doc.saveIncremental(fos);
} catch (final Exception e) {
e.printStackTrace();
}
}发布于 2017-01-19 16:35:38
因为您只提到了时间戳,而不是带有签名时间戳的签名,所以我假设您是指按照PDF或PAdES -2的文档时间戳。
PDFBox签名示例的实现考虑到了常规的数字签名,而不是裸露的数字时间戳。但您可以相当容易地对它们进行调整。CreateVisibleSignature和其他示例创建要嵌入在父类CreateSignatureBase中实现的SignatureInterface方法sign中的签名字节
/**
* SignatureInterface implementation.
*
* This method will be called from inside of the pdfbox and create the PKCS #7 signature.
* The given InputStream contains the bytes that are given by the byte range.
*
* This method is for internal use only.
*
* Use your favorite cryptographic library to implement PKCS #7 signature creation.
*/
@Override
public byte[] sign(InputStream content) throws IOException
{
//TODO this method should be private
try
{
List<Certificate> certList = new ArrayList<Certificate>();
certList.add(certificate);
Store certs = new JcaCertStore(certList);
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
org.bouncycastle.asn1.x509.Certificate cert = org.bouncycastle.asn1.x509.Certificate.getInstance(ASN1Primitive.fromByteArray(certificate.getEncoded()));
ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA256WithRSA").build(privateKey);
gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().build()).build(sha1Signer, new X509CertificateHolder(cert)));
gen.addCertificates(certs);
CMSProcessableInputStream msg = new CMSProcessableInputStream(content);
CMSSignedData signedData = gen.generate(msg, false);
if (tsaClient != null)
{
signedData = signTimeStamps(signedData);
}
return signedData.getEncoded();
}
catch (GeneralSecurityException e)
{
throw new IOException(e);
}
catch (CMSException e)
{
throw new IOException(e);
}
catch (TSPException e)
{
throw new IOException(e);
}
catch (OperatorCreationException e)
{
throw new IOException(e);
}
}()
(顺便说一句,我强烈反对TODO-comment。)
此外,CreateVisibleSignature在signPDF中设置签名的子过滤器
/**
* Sign pdf file and create new file that ends with "_signed.pdf".
*
* @param inputFile The source pdf document file.
* @param signedFile The file to be signed.
* @param tsaClient optional TSA client
* @param signatureFieldName optional name of an existing (unsigned) signature field
* @throws IOException
*/
public void signPDF(File inputFile, File signedFile, TSAClient tsaClient, String signatureFieldName) throws IOException
{
[...]
PDSignature signature;
// sign a PDF with an existing empty signature, as created by the CreateEmptySignatureForm example.
signature = findExistingSignature(doc, signatureFieldName);
if (signature == null)
{
// create signature dictionary
signature = new PDSignature();
}
// default filter
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
// subfilter for basic and PAdES Part 2 signatures
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
[...]
}要创建PAdES文档时间戳,只需创建CreateVisibleSignature示例的副本,用返回给定InputStream中数据的时间戳令牌的实现覆盖SignatureInterface方法sign,替换该行
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);在signPDF中使用
signature.setSubFilter(new COSName("ETSI.RFC3161"));并添加一行
signature.setType(new COSName("DocTimeStamp"));要将类型设置为时间戳,请执行以下操作。
https://stackoverflow.com/questions/41735485
复制相似问题