我正在将项目从iText 5迁移到iText 2 /或DSS(https://ec.europa.eu/cefdigital/wiki/display/CEFDIGITAL/eSignature。)
由于iText版本之间存在差异(DSS使用iText 2.17),因此无法获得正确的带符号哈希。
此处是从itex 5迁移的代码:
// We get the self-signed certificate from the client
CertificateFactory factory = CertificateFactory.getInstance("X.509");
Certificate[] chain = new Certificate[1];
chain[0] = factory.generateCertificate(new ByteArrayInputStream(decoded));
// we create a reader and a stamper
PdfReader reader = new PdfReader(hash.getInputFile());
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
PdfStamper stamper = PdfStamper.createSignature(reader,
byteArrayOutputStream,
'\0',
null,
true);
// HERE WE HAD SOME DIFFERENCE
PdfSignatureAppearance sap = stamper.getSignatureAppearance();
sap.setVisibleSignature(new Rectangle(36, 748, 36, 748), 1, signField); //invisible
// iText 5:
//sap.setCertificate(chain[0]);
// iText 2.1.7:
sap.setCrypto(null,chain,null,PdfSignatureAppearance.SELF_SIGNED);
PdfSignature 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);
HashMap<PdfName,Integer> exc = new HashMap<>();
exc.put(PdfName.CONTENTS, 8192 * 2 + 2);
sap.preClose(exc);
// iText 5:
/*
ExternalDigest externalDigest = hashAlgorithm ->
DigestAlgorithms.getMessageDigest(hashAlgorithm, null);
ExternalDigest externalDigest = new ExternalDigest() {
public MessageDigest getMessageDigest(String hashAlgorithm)
throws GeneralSecurityException {
return DigestAlgorithms.getMessageDigest(hashAlgorithm, null);
}
};
PdfPKCS7 sgn = new PdfPKCS7(null,
chain,
"SHA256",
null,
externalDigest,
false);
*/
// iText 2.1.7:
PdfPKCS7 sgn = new PdfPKCS7(null,chain,null, "SHA256",null,false);
// WARNING SAP.getRange different response content!!!
InputStream data = sap.getRangeStream();
// iText 5:
//byte[] hashArray = DigestAlgorithms.digest(data, externalDigest.getMessageDigest("SHA256"));
//iText 2
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hashArray = md.digest(IOUtils.toByteArray(data));
byte[] ocsp = null;
// iText 5:
//byte[] sh = sgn.getAuthenticatedAttributeBytes(hashArray,
// null,
// null,
// MakeSignature.CryptoStandard.CMS);
// iText 2:
Calendar cal = Calendar.getInstance();
byte[] sh = sgn.getAuthenticatedAttributeBytes(hashArray,cal,null);
InputStream shInputStream = new ByteArrayInputStream(sh);
// iText 5:
//byte[] signedAttributesHash = DigestAlgorithms.digest(shInputStream,externalDigest.getMessageDigest("SHA256"));
// iText 2:
byte[] signedAttributesHash = md.digest(IOUtils.toByteArray(shInputStream));
hash.setOcsp(ocsp);
hash.setSgn(sgn);
hash.setFilehash(hashArray);
hash.setSap(sap);
hash.setBaos(byteArrayOutputStream);
hash.setSignedAttributesHashB64(new String(
org.bouncycastle.util.encoders.Base64.encode(signedAttributesHash),
Charsets.UTF_8)
);
问题始于sap.getRangeStream();
,输出却不同。
以下变量sh
和signedAttributesHash
的内容有误。
有人成功做到了吗?任何帮助将不胜感激。
答案 0 :(得分:0)
使用pdfbox的临时方法。
我不知道如何在空签名中插入公共证书:/就像iText一样!我不知道是否可能。
public abstract class testtwostep
{
private static final String ID_PKCS7_DATA = "1.2.840.113549.1.7.1";
private static final String ID_PKCS7_SIGNED_DATA = "1.2.840.113549.1.7.2";
private static final String ID_MD5 = "1.2.840.113549.2.5";
private static final String ID_MD2 = "1.2.840.113549.2.2";
private static final String ID_SHA1 = "1.3.14.3.2.26";
private static final String ID_RSA = "1.2.840.113549.1.1.1";
private static final String ID_DSA = "1.2.840.10040.4.1";
private static final String ID_CONTENT_TYPE = "1.2.840.113549.1.9.3";
private static final String ID_MESSAGE_DIGEST = "1.2.840.113549.1.9.4";
private static final String ID_SIGNING_TIME = "1.2.840.113549.1.9.5";
private static final String ID_MD2RSA = "1.2.840.113549.1.1.2";
private static final String ID_MD5RSA = "1.2.840.113549.1.1.4";
private static final String ID_SHA1RSA = "1.2.840.113549.1.1.5";
public byte[] getAuthenticatedAttributeBytes(byte secondDigest[],Calendar signingTime) throws IOException {
ASN1EncodableVector attribute = new ASN1EncodableVector();
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(new DERObjectIdentifier(ID_CONTENT_TYPE));
v.add(new DERSet(new DERObjectIdentifier(ID_PKCS7_DATA)));
attribute.add(new DERSequence(v));
v = new ASN1EncodableVector();
v.add(new DERObjectIdentifier(ID_SIGNING_TIME));
v.add(new DERSet(new DERUTCTime(signingTime.getTime())));
attribute.add(new DERSequence(v));
v = new ASN1EncodableVector();
v.add(new DERObjectIdentifier(ID_MESSAGE_DIGEST));
v.add(new DERSet(new DEROctetString(secondDigest)));
attribute.add(new DERSequence(v));
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
ASN1OutputStream dout = new ASN1OutputStream(bOut);
dout.writeObject(new DERSet(attribute));
dout.close();
return bOut.toByteArray();
}
public byte[] getHash() throws IOException, NoSuchAlgorithmException, CertificateException {
String documentFile = "/home/gigio2k/dev/swap/tmp.pdf";
String documentFileSigned = "/home/gigio2k/dev/swap/tmp_pdfbox.pdf";
String certStr = "MII....GsNw==";
byte[] certByte = org.apache.commons.codec.binary.Base64.decodeBase64(certStr.getBytes());
PDDocument document = PDDocument.load(new File(documentFile));
Calendar date = Calendar.getInstance();
long SeedTS = date.getTimeInMillis();
document.setDocumentId(SeedTS);
PDSignature signature = new PDSignature();
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
//signature.setName("Example User");
signature.setLocation("Los Angeles, CA");
signature.setReason("Testing");
signature.setSignDate(date);
SignatureOptions opt = new SignatureOptions();
opt.setPreferredSignatureSize(8192);
document.addSignature(signature,opt);
ExternalSigningSupport externalSigningSupport = document.saveIncrementalForExternalSigning(null);
byte[] content = IOUtils.toByteArray(externalSigningSupport.getContent());
MessageDigest md = MessageDigest.getInstance("SHA256", new BouncyCastleProvider());
byte[] digest = md.digest(content); // this is sent to client
//byte[] sh = sgn.getAuthenticatedAttributeBytes(hashArray,null,null,MakeSignature.CryptoStandard.CMS);
byte[] sh = getAuthenticatedAttributeBytes(digest,date);
InputStream shInputStream = new ByteArrayInputStream(sh);
//byte[] signedAttributesHash = DigestAlgorithms.digest(shInputStream, externalDigest.getMessageDigest("SHA256"));
byte[] signedAttributesHash = md.digest(sh);
System.out.println("--------------------");
System.out.println(new String(org.bouncycastle.util.encoders.Base64.encode(signedAttributesHash),Charsets.UTF_8));
System.out.println(date.getTimeInMillis());
System.out.println("--------------------");
System.out.println("Enter b64 signed:");
System.out.println("--------------------");
Scanner in = new Scanner(System.in);
String signedHashB64 = in.nextLine();
byte[] encodedSignature = org.apache.commons.codec.binary.Base64.decodeBase64(signedHashB64.getBytes());
PDDocument document2 = PDDocument.load(new File(documentFile));
Calendar date2 = date;
document2.setDocumentId(SeedTS);
PDSignature signature2 = new PDSignature();
signature2.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
signature2.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
//signature2.setName("Example User");
signature2.setLocation("Los Angeles, CA");
signature2.setReason("Testing");
signature2.setSignDate(date2);
SignatureOptions opt2 = new SignatureOptions();
opt2.setPreferredSignatureSize(8192);
document2.addSignature(signature2,opt2);
File file = new File(documentFileSigned);
FileOutputStream fos = new FileOutputStream(file);
ExternalSigningSupport externalSigning = document2.saveIncrementalForExternalSigning(fos);
externalSigning.setSignature(encodedSignature);
System.out.println("--------------------");
System.out.println("saved to: " + documentFileSigned);
System.out.println("--------------------");
return digest;
}
public static void main(String[] args) throws IOException, GeneralSecurityException
{
testtwostep t2s = new testtwostep();
t2s.getHash();
}
}
请注意:我没有编辑第一个问题,因为我会尝试更多方法,最后我会编辑原始问题