日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

本文介紹了Java IText7 PDF簽名問題-文檔在簽名后已被更改或損壞的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

我嘗試對pdf文件進行簽名,但在Adobe中打開簽名的pdf文件時,遇到文檔自簽名以來已被更改或損壞的錯誤。

該錯誤不太具有描述性,我不確定要查看哪里,因為代碼對我來說似乎很好,但顯然并非如此。

我使用的代碼是:

public class SafeService_INPUT_Pdf {

    private static final String input = "";
    private static final String tmp = "";
    private static final String output =  "";
    private static final String token = "";

    public static void main(String[] args) throws Exception {

        BouncyCastleProvider providerBC = new BouncyCastleProvider();
        Security.addProvider(providerBC);

        CredentialsInfoResponseDto credentialsInfoResponseDto = SafeAmaHelper.getCredentialsInfo(token);

        String cert0 = "-----BEGIN CERTIFICATE-----
"+ credentialsInfoResponseDto.getCert().getCertificates().get(0) +"
-----END CERTIFICATE-----";
        String cert1 = "-----BEGIN CERTIFICATE-----
"+ credentialsInfoResponseDto.getCert().getCertificates().get(1) +"
-----END CERTIFICATE-----";
        String cert2 = "-----BEGIN CERTIFICATE-----
"+ credentialsInfoResponseDto.getCert().getCertificates().get(2) +"
-----END CERTIFICATE-----";

        Certificate[] chain = new Certificate[3];

        try {
            chain[0] = SafePdfHelper.convertStringCert(cert0);
            chain[1] = SafePdfHelper.convertStringCert(cert1);
            chain[2] = SafePdfHelper.convertStringCert(cert2);
        }catch (Exception e){
            System.out.println(e.getCause().getMessage());
        }

        byte[] hash4Sign = SafePdfHelper.emptySignature(input, tmp, "sig", chain);

        //concatenate sha_prefix with hash4Sign and convert to BASE64
        String **hashToSign** = SafePdfHelper.getHashtoSign(hash4Sign);
        
        //CALL AMA and gets 
        String amaSignature = SafeAmaHelper.getAssinat(token,**hashToSign**).getSignatures().get(0);

        byte[] signedFinallyHash = Base64.getDecoder().decode(String.valueOf(amaSignature.toCharArray()));

        //insert HASH (AMA) to PDF temp and creates a signed PDF
        SafePdfHelper.createSignature(signedFinallyHash, tmp, output, "sig", chain);
    }
public class SafePdfHelper {

    public static String getHashtoSign(byte[] hash4Sign) throws NoSuchAlgorithmException {

        byte[] sha256SigPrefix = { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, (byte) 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 };

        byte[] hash4SignWithPrefix = new byte[sha256SigPrefix.length + hash4Sign.length];
        System.arraycopy(sha256SigPrefix, 0, hash4SignWithPrefix, 0, sha256SigPrefix.length);
        System.arraycopy(hash4Sign, 0, hash4SignWithPrefix, sha256SigPrefix.length, hash4Sign.length);

        return Base64.getEncoder().encodeToString(hash4SignWithPrefix);
    }

    public static Certificate convertStringCert(String certificate) throws Exception{
        InputStream targetStream = new ByteArrayInputStream(certificate.getBytes());

        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        Certificate cert = cf.generateCertificate(targetStream);

        return cert;
    }

    public static byte[] emptySignature(String src, String dest, String fieldname, Certificate[] chain) throws IOException, GeneralSecurityException, IOException {

        PdfReader reader = new PdfReader(src);
        FileOutputStream os = new FileOutputStream(dest);
        PdfSigner signer = new PdfSigner(reader, os, new StampingProperties().useAppendMode());

        signer.setFieldName(fieldname);

        SafePdfHelper.MyExternalBlankSignatureContainer external = new SafePdfHelper.MyExternalBlankSignatureContainer(chain, PdfName.Adobe_PPKMS, PdfName.Adbe_pkcs7_detached);

        signer.signExternalContainer(external, 12000);
        byte[] hash4Sign = external.getHash4Sign();

        os.close();
        reader.close();

        return hash4Sign;
    }

    static class MyExternalBlankSignatureContainer implements IExternalSignatureContainer {

        /* Signature dictionary. Filter and SubFilter.  */
        private final PdfDictionary sigDic;
        private byte[] hash4Sign = null;
        private Certificate[] chain = null;

        public MyExternalBlankSignatureContainer(Certificate[] _chain, PdfName filter, PdfName subFilter) {
            sigDic = new PdfDictionary();
            sigDic.put(PdfName.Filter, filter);
            sigDic.put(PdfName.SubFilter, subFilter);
            chain = _chain;
        }

        public byte[] getHash4Sign() {
            return hash4Sign;
        }

        @Override
        public byte[] sign(InputStream data) throws GeneralSecurityException {

            try {
                String hashAlgorithm = DigestAlgorithms.SHA256;//"SHA-256";
                BouncyCastleDigest digest = new BouncyCastleDigest();
                MessageDigest md = digest.getMessageDigest(hashAlgorithm);

                byte[] hash = DigestAlgorithms.digest(data, md);
                PdfPKCS7 sgn = new PdfPKCS7(null, chain, hashAlgorithm, null, digest, false);

                OcspClientBouncyCastle ocspClient = new OcspClientBouncyCastle(null);
                Collection<byte[]> ocsp = new ArrayList<>();
                for (var i = 0; i < chain.length - 1; i++) {
                    byte[] encoded = ocspClient.getEncoded((X509Certificate) chain[i], (X509Certificate) chain[i + 1], null);
                    if (encoded != null) ocsp.add(encoded);
                }

                byte[] attributeBytes = sgn.getAuthenticatedAttributeBytes(hash, PdfSigner.CryptoStandard.CMS, ocsp, null);

                //create sha256 message digest
                hash4Sign = MessageDigest.getInstance(hashAlgorithm).digest(attributeBytes);

                return new byte[0];
            } catch (IOException | GeneralSecurityException de) {
                de.printStackTrace();
                throw new GeneralSecurityException(de);
            }
        }

        @Override
        public void modifySigningDictionary(PdfDictionary signDic) {
            signDic.putAll(sigDic);
        }
    }


    public static void createSignature(byte[] hashSigned, String src, String dest, String fieldName, Certificate[] chain) throws IOException, GeneralSecurityException {

        PdfReader reader = new PdfReader(src);
        try (FileOutputStream os = new FileOutputStream(dest)) {
            PdfSigner signer = new PdfSigner(reader, os, new StampingProperties());

            IExternalSignatureContainer external = new SafePdfHelper.MyExternalSignatureContainer(hashSigned, chain, PdfName.Adobe_PPKMS, PdfName.Adbe_pkcs7_detached);

            // Signs a PDF where space was already reserved. The field must cover the whole document.
            signer.signDeferred(signer.getDocument(), fieldName, os, external);
        }
        reader.close();
    }

    static class MyExternalSignatureContainer implements IExternalSignatureContainer {

        /* Signature dictionary. Filter and SubFilter.  */
        private PdfDictionary sigDic;
        private byte[] signedHash = null;
        private Certificate[] chain = null;

        public MyExternalSignatureContainer(byte[] _signedHash, Certificate[] _chain, PdfName filter, PdfName subFilter) {
            sigDic = new PdfDictionary();
            sigDic.put(PdfName.Filter, filter);
            sigDic.put(PdfName.SubFilter, subFilter);
            signedHash = _signedHash;
            chain = _chain;
        }

        @Override
        public byte[] sign(InputStream data) throws GeneralSecurityException {
            try {
                String hashAlgorithm = DigestAlgorithms.SHA256;//"SHA-256";
                BouncyCastleDigest digest = new BouncyCastleDigest();
                MessageDigest md = digest.getMessageDigest(hashAlgorithm);

                byte[] hash = DigestAlgorithms.digest(data, md);
                PdfPKCS7 sgn = new PdfPKCS7(null, chain, hashAlgorithm, null, digest, false);

                OcspClientBouncyCastle ocspClient = new OcspClientBouncyCastle(null);
                Collection<byte[]> ocsp = new ArrayList<>();
                for (var i = 0; i < chain.length - 1; i++) {
                    byte[] encoded = ocspClient.getEncoded((X509Certificate) chain[i], (X509Certificate) chain[i + 1], null);
                    if (encoded != null) ocsp.add(encoded);
                }

                sgn.setExternalDigest(signedHash, null, "RSA");

                ITSAClient tsaClient = null;//new GSTSAClient(access);
                return sgn.getEncodedPKCS7(hash, PdfSigner.CryptoStandard.CMS, tsaClient, ocsp, null);
            } catch (IOException | GeneralSecurityException de) {
                de.printStackTrace();
                throw new GeneralSecurityException(de);
            }
        }

        @Override
        public void modifySigningDictionary(PdfDictionary signDic) {
            signDic.putAll(sigDic);
        }
    }

簽名的哈希的Base64格式為(臨時文件+SHA_前綴):

MDEwDQYJYIZIAWUDBAIBBQAEIKCZG8Xc6M2de3fuj8CMHLhW8XvMArW6Smy75TgABlGQ

簽名(AMA)的Base64格式為:

X5vg7qXJNsiB8hYtauih/wMFNf9uLAnT8h4M7DvHyw0bLdM03BJc7Ar1yGIoA0MTXaEdq85DP6JJFeMJZBRRc/NTA1C4IpjBN5N5Fpaa7HFnNxORQBc00d/bXuSzV1DNwCdIfcDYSUjh5Z3OWFdWzqmDhmAWRK/Hudf90m34B1mpfTtvtRAzrgn79fIBUd9D09iXpnClqTVYIzWcJ+Dz6yU75a0gvR79wNLCpUYNw2kxdmp/odAMm5cn10x9hLB+UhaNSUsnYyQUZtFsSkIE+oPXFqZc9ky4j5ha9Xfz8GGcLPEkAupyxOb5f9/NGicOeegX793swY09O4NxDW9RVtMtmdKt8kZAxB70PG1r18Ui2gheY4yuMg2aqpkcw5vgBO1GYe2DwDp99Qs4xHJjhbiUZOKT0moU+tDb3EySHZkkkci/GQTUg8IYHU8umv9TyuD7A3NRBQTyQud6j9H6bG3zQE+V4T8N2fnUPmoFEfDWyIvxvV+7YL+BymeZX4A0

有人能幫忙嗎?

推薦答案

這是我們在評論中討論的摘要。

問題是您在MyExternalBlankSignatureContainer.signMyExternalSignatureContainer.sign中檢索OCSP響應,這兩個方法都是

OcspClientBouncyCastle ocspClient = new OcspClientBouncyCastle(null);
Collection<byte[]> ocsp = new ArrayList<>();
for (var i = 0; i < chain.length - 1; i++) {
    byte[] encoded = ocspClient.getEncoded((X509Certificate) chain[i], (X509Certificate) chain[i + 1], null);
    if (encoded != null) ocsp.add(encoded);
}

PdfPKCS7一起使用該列表。

當您使用MyExternalBlankSignatureContainer計算要簽名的屬性的摘要,并使用MyExternalSignatureContainer基于該摘要的簽名值構建簽名容器時,這兩種情況下的屬性必須相同。由于OCSP響應包含在其中一個屬性中,這意味著您必須在兩種情況下使用相同的OCSP響應。

但OCSP響應通常會為每個請求重新創建(或最多緩存很短的時間),但對于同一證書的不同請求,您通常會得到不同的OCSP響應。

因此,不能在MyExternalSignatureContainer.sign中重新檢索,而必須重新使用MyExternalBlankSignatureContainer.sign中檢索到的。

根據您的最后評論,這樣做對您有效。

這篇關于Java IText7 PDF簽名問題-文檔在簽名后已被更改或損壞的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,

分享到:
標簽:IText7 Java 已被 損壞 文檔 更改 簽名
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定