SIgn pdf с внешней подписью от клиента Itext - PullRequest
0 голосов
/ 18 марта 2020

Я подписываю файл.

Сначала я готовлю файл к подписи - вставляю пустой контейнер, вычисляю га sh, отправляю этот га sh клиенту, они подписывают его там и я получаю подпись в виде строки, которую затем нужно вставить в документ. Но при сохранении в подписи отображается ошибка, что при форматировании или сохранении информации для этой подписи произошла ошибка

Ха sh:

public class TestSignPDF {

@Autowired
private ResourceLoader resourceLoader;

private final Logger log = LoggerFactory.getLogger(TestSignPDF.class);

private static final String base64 =
        "MIIGKgYJKoZIhvcNAQcCoIIGGzCCBhcCAQExDjAMBggqhQMHAQECAgUAMAsGCSqGSIb3DQEHAaCC" +
                "A5swggOXMIIDRqADAgECAhMSAEHNA08eSyCIioAbAAEAQc0DMAgGBiqFAwICAzB/MSMwIQYJKoZI" +
                "hvcNAQkBFhRzdXBwb3J0QGNyeXB0b3Byby5ydTELMAkGA1UEBhMCUlUxDzANBgNVBAcTBk1vc2Nv" +
                "dzEXMBUGA1UEChMOQ1JZUFRPLVBSTyBMTEMxITAfBgNVBAMTGENSWVBUTy1QUk8gVGVzdCBDZW50" +
                "ZXIgMjAeFw0yMDAzMDUxMTU4MjFaFw0yMDA2MDUxMjA4MjFaMIGbMScwJQYJKoZIhvcNAQkBFhh6" +
                "YmV5YWRpdzUyNkB4bWFpbHNtZS5jb20xLzAtBgNVBAMMJtCY0LLQsNC90L7QsiDQmNCy0LDQvSDQ" +
                "mNCy0LDQvdC+0LLQuNGHMRswGQYDVQQKDBLQndC+0LLRgNC10LPQuNC+0L0xFTATBgNVBAcMDNCc" +
                "0L7RgdC60LLQsDELMAkGA1UEBhMCUlUwZjAfBggqhQMHAQEBATATBgcqhQMCAiQABggqhQMHAQEC" +
                "AgNDAARABcSDHxOPpd2ZTbv/jZNQoFkulrG+3MFRYpFTEA29W/wrIkpidYP3j35MzTvIf6J4Z22n" +
                "+8Dyu/SA5KPaUXg/R6OCAXcwggFzMA8GA1UdDwEB/wQFAwMH8AAwEwYDVR0lBAwwCgYIKwYBBQUH" +
                "AwIwHQYDVR0OBBYEFG5egByngO90EfBatmoTAdNRjoe2MB8GA1UdIwQYMBaAFE6DPhRp7+xdepUr" +
                "XxH+NzIWSVUrMFwGA1UdHwRVMFMwUaBPoE2GS2h0dHA6Ly90ZXN0Y2EuY3J5cHRvcHJvLnJ1L0Nl" +
                "cnRFbnJvbGwvQ1JZUFRPLVBSTyUyMFRlc3QlMjBDZW50ZXIlMjAyKDEpLmNybDCBrAYIKwYBBQUH" +
                "AQEEgZ8wgZwwZAYIKwYBBQUHMAKGWGh0dHA6Ly90ZXN0Y2EuY3J5cHRvcHJvLnJ1L0NlcnRFbnJv" +
                "bGwvdGVzdC1jYS0yMDE0X0NSWVBUTy1QUk8lMjBUZXN0JTIwQ2VudGVyJTIwMigxKS5jcnQwNAYI" +
                "KwYBBQUHMAGGKGh0dHA6Ly90ZXN0Y2EuY3J5cHRvcHJvLnJ1L29jc3Avb2NzcC5zcmYwCAYGKoUD" +
                "AgIDA0EAktvoNfNTRZ3rGqHm6R/uH5DloTgEzXiRCunoYYXNh1ku8EIEFf298vHdisvA2sa2/fWu" +
                "7PLytY/2i3EtGCKKVTGCAlQwggJQAgEBMIGWMH8xIzAhBgkqhkiG9w0BCQEWFHN1cHBvcnRAY3J5" +
                "cHRvcHJvLnJ1MQswCQYDVQQGEwJSVTEPMA0GA1UEBxMGTW9zY293MRcwFQYDVQQKEw5DUllQVE8t" +
                "UFJPIExMQzEhMB8GA1UEAxMYQ1JZUFRPLVBSTyBUZXN0IENlbnRlciAyAhMSAEHNA08eSyCIioAb" +
                "AAEAQc0DMAwGCCqFAwcBAQICBQCgggFSMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZI" +
                "hvcNAQkFMQ8XDTIwMDMxODEzNTM0N1owLwYJKoZIhvcNAQkEMSIEIEEWgMAXJ0dl4f4gm0PaQMtY" +
                "zzs6TvsJE0XB6Rb86aJYMIHmBgsqhkiG9w0BCRACLzGB1jCB0zCB0DCBzTAKBggqhQMHAQECAgQg" +
                "9896tvU4aXYE4ecAKTO/PXo3dP/CqFAZmc+RVCp7Ta0wgZwwgYSkgYEwfzEjMCEGCSqGSIb3DQEJ" +
                "ARYUc3VwcG9ydEBjcnlwdG9wcm8ucnUxCzAJBgNVBAYTAlJVMQ8wDQYDVQQHEwZNb3Njb3cxFzAV" +
                "BgNVBAoTDkNSWVBUTy1QUk8gTExDMSEwHwYDVQQDExhDUllQVE8tUFJPIFRlc3QgQ2VudGVyIDIC" +
                "ExIAQc0DTx5LIIiKgBsAAQBBzQMwDAYIKoUDBwEBAQEFAARAOFLJIbyLuNqPFuuAa43RnBhOgwjS" +
                "SBy0Sx/TxgwEO263ukc2kDY1TN9se1u1+389yuwBriTw88Wr6V2g+kTCcw==";

@Test
void geHashAndSaveFile() throws Exception {

    System.setProperty("com.ibm.security.enableCRLDP", "true");
    System.setProperty("com.sun.security.enableCRLDP", "true"); // для проверки по CRL DP
    System.setProperty("com.sun.security.enableAIAcaIssuers", "true"); // для загрузки сертификатов по AIA из сети
    System.setProperty("ru.CryptoPro.reprov.enableAIAcaIssuers", "true"); // для загрузки сертификатов по AIA из сети

    BouncyCastleProvider bcProvider = new BouncyCastleProvider();
    String name = bcProvider.getName();
    Security.removeProvider(name); // remove old instance
    Security.addProvider(bcProvider);

    String pathToFile = "hash/no-signed-file.pdf";
    byte[] content = resourceLoader.load(pathToFile);
    String hash = getHash(content);
    log.info("Hash : {}", hash);

}

@Test
void signFile() throws Exception {

    System.setProperty("com.ibm.security.enableCRLDP", "true");
    System.setProperty("com.sun.security.enableCRLDP", "true"); // для проверки по CRL DP
    System.setProperty("com.sun.security.enableAIAcaIssuers", "true"); // для загрузки сертификатов по AIA из сети
    System.setProperty("ru.CryptoPro.reprov.enableAIAcaIssuers", "true"); // для загрузки сертификатов по AIA из сети

    BouncyCastleProvider bcProvider = new BouncyCastleProvider();
    String name = bcProvider.getName();
    Security.removeProvider(name); // remove old instance
    Security.addProvider(bcProvider);

    String pathToFile = "real_file/SignedPdf2.pdf";
    byte[] content = resourceLoader.load(pathToFile);
    byte[] signed = sign(content, base64, false);

    try (FileOutputStream fos = new FileOutputStream(".../real_file/SignedPdf3.pdf")) {
        fos.write(signed);
        //fos.close(); There is no more need for this line since you had created the instance of "fos" inside the try. And this will automatically close the OutputStream
    }


}

public String getHash(byte[] content) throws Exception {
    try (ByteArrayOutputStream baos = new ByteArrayOutputStream();) {
        PdfReader reader = new PdfReader(content);
        PdfStamper stamper = PdfStamper.createSignature(reader, baos, '\0');

        PdfSignatureAppearance sap = stamper.getSignatureAppearance();
        sap.setReason("Document Sign");
        sap.setLocation("CryptoPro");
        sap.setReuseAppearance(false);

        ExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
        MakeSignature.signExternalContainer(sap, external, 8192);

        InputStream data = sap.getRangeStream();
        MessageDigest md = MessageDigest.getInstance("GOST3411-2012-256");
        byte hash[] = md.digest(IOUtils.toByteArray(data));

        try (FileOutputStream fos = new FileOutputStream(".../real_file/SignedPdf2.pdf")) {
            fos.write(baos.toByteArray());
        }
        return new String(new Base64().encode(hash));
    }
}


public byte[] sign(byte[] rawPdf,
                   String signature,
                   boolean append) {
    try (ByteArrayOutputStream fout = new ByteArrayOutputStream()) {
        byte[] decodeSignature = Base64.decodeBase64(signature);

        CAdESSignature cades = new CAdESSignature(decodeSignature, null, null);
        var certificate = cades.getCAdESSignerInfo(0).getSignerCertificate();
        var subject = new Subject(certificate.getSubjectX500Principal().getEncoded());

        Certificate[] certs = Arrays.stream(cades.getCAdESSignerInfos())
                .map(AdESSigner::getSignerCertificate)
                .collect(Collectors.toList()).toArray(Certificate[]::new);

        PdfReader reader = new PdfReader(rawPdf);

        ExternalSignatureContainer container = new BrowserSignatureContainer(Base64.decodeBase64(signature));
        MakeSignature.signDeferred(reader, "Signature1", fout, container);

        return fout.toByteArray();
    }
    catch (Exception e) {
        throw new InternalException("IO exception by insert signature to document:", e);
    }
}

class BrowserSignatureContainer implements ExternalSignatureContainer {
    private byte[] sinedData;

    public BrowserSignatureContainer(byte[] signature) {
        this.sinedData = signature;
    }

    public byte[] sign(InputStream is) {
        return sinedData;
    }

    public void modifySigningDictionary(PdfDictionary pdfDictionary) {
    }
}

}

1 - я выполняю geHashAndSaveFile (), получаю файл SignedPdf2.pdf и ха sh в результате

2 - сенг ха sh клиенту и получаю подписанный га sh как личное сообщение c final String base64

3 - выполнить signFile () и получить файл SignedPdf3.pdf в результате с недопустимой подписью;

Что не так?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...