Я подписываю файл.
Сначала я готовлю файл к подписи - вставляю пустой контейнер, вычисляю га 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 в результате с недопустимой подписью;
Что не так?