我正在尝试使用移动签名服务提供商(MSSP)对pdf文件进行签名。
我用下面的一些代码来做。但是签名无效,并显示消息“自应用签名以来,文档已被更改或损坏。”
在“ APWebService.sign(phoneNumber,messageDisplay,encode)”中进行编码只能接受44个字符。
有人可以帮助我吗?
public class MyExternalSignatureContainer implements ExternalSignatureContainer {
protected byte[] sig;
protected Certificate[] chain;
public static final String SRC = "/media/thanhpx1/MEDIA/FileCongVan.pdf";
public static final String TEMP = "/media/thanhpx1/MEDIA/hello_changed.pdf";
public static final String DEST_SIGN = "/media/thanhpx1/MEDIA/signed.pdf";
public MyExternalSignatureContainer(byte[] sig, Certificate[] chain) {
this.sig = sig;
this.chain = chain;
}
public MyExternalSignatureContainer(Certificate[] chain) {
this.chain = chain;
}
public byte[] sign(InputStream is) throws GeneralSecurityException {
return sig;
}
public byte[] emptySignature_hash(String src, String dest, String fieldname, Certificate[] chain)
throws IOException, DocumentException, GeneralSecurityException, java.io.IOException {
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, fieldname);
appearance.setCertificate(chain[0]);
ExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
MakeSignature.signExternalContainer(appearance, external, 8192);
InputStream inp = appearance.getRangeStream();
BouncyCastleDigest digest = new BouncyCastleDigest();
byte[] hash = DigestAlgorithms.digest(inp, digest.getMessageDigest("SHA256"));
return hash;
}
public byte[] signed_hash(byte[] hash, Certificate[] chain) throws GeneralSecurityException, MalformedURLException, java.io.IOException {
BouncyCastleDigest digest = new BouncyCastleDigest();
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
PdfPKCS7 sgn = new PdfPKCS7(null, chain, "SHA256", null, digest, false);
//hash.length=32
byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, null, null, CryptoStandard.CMS);
//sh.length=77
InputStream shInputStream = new ByteArrayInputStream(sh);
byte[] signedAttributesHash = DigestAlgorithms.digest(shInputStream, digest.getMessageDigest("SHA256"));
//signedAttributesHash.length=32
String encode = com.itextpdf.io.codec.Base64.encodeBytes(signedAttributesHash);
//encode have 44 characters
String phoneNumber = "xxxxxxxxx";
String messageDisplay = "Please sign this document";
//Send to Application Provider WS
String resultSign = APWebService.sign(phoneNumber, messageDisplay, encode);
//resultSign = W5srXKNmRdXNd7uX/QsYhBPet8DOdO9A6F/Ku5ey5JoTatYEJVaEvXB7MjZ3w2W2tEetpZVfc0eFSmMwp/z3TZVX7JvjiN0uCjXgFtCCRr7ffm+jcbp2MEK4hJCCNoHawpjvVV1Qykcg1gerHQDaSSQhtrfJsxOVd0KUIgfIJeBmGMZMGerdz+snH9pe74fMlX+IuEp5Hhk0R6xuwL9vKFxvCVPyv/U6eRmlQmG/wIzr6IBIWET0JDNNgWjmq+jKL70hxZLakZU9Hqu1zKzpkS5jB+0UXMayjBldBuPF1rofgRJKsT8BJttQ8a/YYZr6Sw0X8m8Ah+yPCGTWunRUhA==
byte[] signedHashValue = com.itextpdf.io.codec.Base64.decode(resultSign);
sgn.setExternalDigest(signedHashValue, null, "RSA");
return sgn.getEncodedPKCS7(hash, null, null, null, CryptoStandard.CMS);
}
public void createSignature(String src, String dest, String fieldname, byte[] hash,
Certificate[] chain) throws IOException, DocumentException, GeneralSecurityException, java.io.IOException {
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
ExternalSignatureContainer external = new MyExternalSignatureContainer(hash, chain);
MakeSignature.signDeferred(reader, fieldname, os, external);
}
public static void main(String[] args) throws IOException, GeneralSecurityException, DocumentException, java.io.IOException {
String phoneNumber = "xxxxxxxx";
//Call from Application Provider WS to get certificate
GetCertDto certDto = APWebService.getCertInfo(phoneNumber);
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
ByteArrayInputStream bytes = new ByteArrayInputStream(Base64.decodeBase64(certDto.getValue()));
X509Certificate cert = (X509Certificate)certFactory.generateCertificate(bytes);
X509Certificate[] certArr = new X509Certificate[1];
certArr[0] = cert;
MyExternalSignatureContainer app = new MyExternalSignatureContainer(certArr);
byte[] hh = app.emptySignature_hash(SRC, TEMP, "sig1", certArr);
byte[] hh_sign = (app.signed_hash(hh, certArr));
app.createSignature(TEMP, DEST_SIGN, "sig1", hh_sign, certArr);
System.out.println("done");
}
@Override
public void modifySigningDictionary(PdfDictionary signDic) {
}
}