- Подготовить PDF-файл к подписи: создать видимое поле подписи и сгенерировать хеш содержимого PDF-файла. Этот хэш будет отправлен в облачную службу подписи.
- Получить данные подписи: служба возвращает JSON, содержащий подписанный хеш (signedContent). , сертификат (кодированныйX509) и другую информацию.
- Финализация подписи: введите данные подписи в созданное ранее поле.
Код: Выделить всё
private static byte[] emptySignature(String src, String dest, String fieldname, Certificate[] chain)
throws IOException, GeneralSecurityException
{
PdfReader reader = new PdfReader(src);
PdfSigner signer = new PdfSigner(reader, new FileOutputStream(dest), new StampingProperties());
PdfSignatureAppearance appearance = signer.getSignatureAppearance();
appearance.setPageRect(new Rectangle(100, 500, 200, 100));
appearance.setPageNumber(1);
appearance.setCertificate(chain[0]);
appearance.setReason("For test");
appearance.setLocation("HKSAR");
signer.setFieldName(fieldname);
PreSignatureContainer external = new PreSignatureContainer(PdfName.Adobe_PPKLite, PdfName.Adbe_pkcs7_detached);
signer.signExternalContainer(external, 8192);
return external.getHash();
}
public static class PreSignatureContainer implements IExternalSignatureContainer {
private final PdfDictionary sigDic;
private byte[] hash;
public PreSignatureContainer(PdfName filter, PdfName subFilter) {
sigDic = new PdfDictionary();
sigDic.put(PdfName.Filter, filter);
sigDic.put(PdfName.SubFilter, subFilter);
}
@Override
public byte[] sign(InputStream data) throws GeneralSecurityException {
String hashAlgorithm = "SHA256";
BouncyCastleDigest digest = new BouncyCastleDigest();
X509Certificate certificate = null;
Certificate[] certs = null;
try{
certificate = getCertificate("cert");
certs = new Certificate[]{certificate};
} catch (Exception ex){
ex.printStackTrace();
}
try {
byte[] hash = DigestAlgorithms.digest(data, digest.getMessageDigest(hashAlgorithm));
PdfPKCS7 pkcs7 = new PdfPKCS7(null,certs , "SHA-256", null, digest, false);
byte[] sh = pkcs7.getAuthenticatedAttributeBytes(hash,PdfSigner.CryptoStandard.CMS, null, null);
this.hash = sh;
} catch (IOException e) {
throw new GeneralSecurityException("PreSignatureContainer signing exception", e);
}
return new byte[0];
}
@Override
public void modifySigningDictionary(PdfDictionary signDic) {
signDic.putAll(sigDic);
}
public byte[] getHash() {
return hash;
}
byte[] signatureBytes = THE_RETRIEVED_SIGNATURE_BYTES;
byte[] certificateBytes = THE_RETRIEVED_CERTIFICATE_BYTES;
Код: Выделить всё
{ "data": { "requestId": "01JEE2TDRMZAV8GZTMQPHGTMKJ", "executionStatus": { "currentStatus": "COMPLETED-WITH-SIGNATURE", "requestTimestamp": "2024-12-06T13:33:49.204Z", "executionTimestamp": "2024-12-06T13:33:49.369Z" }, "subjectIdentification": { "identificationKey": "104699xxx", "identificationType": "CPF" }, "certificateInformation": { "serialNumber": "1AADB23286C489B4", "issuerName": "C=BR\nO=ICP-Brasil\nOU=Secretaria da Receita Federal do Brasil - RFB\nCN=AC VALID RFB v5", "validity": { "notBefore": "Oct 28 21:23:44 2023 GMT", "notAfter": "Oct 26 21:23:44 2028 GMT" }, "subjectName": "C=BR\nO=ICP-Brasil\nOU=Secretaria da Receita Federal do Brasil - RFB\nOU=RFB e-CPF A3\nOU=AC VALID RFB V5\nOU=AR CFM\nOU=Presencial\nOU=33583550000130\nCN=GESxxxxx:1046998xxx", "encodedX509": "-----BEGIN CERTIFICATE-----\nMIIHuzCCBaOgAwIBAgIIGq2yMobEibQwDQYJKoZIhvcNAQELBQAwdDELMAkGA1UE\nBhMCQlIxEzARBgNVBAoTCklDUC1CcmFzaWwxNjA0BgNVBAsTLVNlY3JldGFyaWEg\nZGEgUmVjZWl0YSBGZWRlcmFsIGRvIEJyYXNpbCAtIFJGQjEYMBYGA1UEAxMPQUMg\nVkFMSUQgUkZCIHY1MB4XDTIzMTAyODIxMjM0NFoXDTI4MTAyNjIxMjM0NFowgfkx\nCzAJBgNVBAYTAkJSMRMwEQYDVQQKEwpJQ1AtQnJhc2lsMTYwNAYDVQQLEy1TZWNy\nZXRhcmlhIGRhIFJlY2VpdGEgRmVkZXJhbCBkbyBCcmFzaWwgLSBSRkIxFTATBgNV\nBAsTDFJGQiBlLUNQRiBBMzEYMBYGA1UECxMPQUMgVkFMSUQgUkZCIFY1MQ8wDQYD\nVQQLEwZBUiBDRk0xEzARBgNVBAsTClByZXNlbmNpYWwxFzAVBgNVBAsTDjMzNTgz\nNTUwMDAwMTMwMS0wKwYDVQQDEyRHRVNJQU5FIERBIFNJTFZBIExPVVJFRE86MTA0\nNjk5ODE3MDkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDdHA8yOrnU\n39JvVhJyw9HYtBPwEGFUsUEIMfYRi9inBWDD5KDVu43LXQQy0iliwr4ov2qHy66y\nMAFaH/jqLbqIfXYDlM7IJOMUnoRgYaO7yFpjnJKmje7yTLORYA+ZE7cdwb8RfpcE\n+CtNtmEhzoabP1bUNQUISujL/3KXDSYx7AJxHWoH9ms+RBHmUOH/qFggPK6EYA6o\nylQFxseDAsZM2bM8dyP+b3us0REOZMSkV+3yCeP8QsFlmg117Gq8Sva2pW7MeNGf\ndMYOButXqzYMPnHKI7BeZpEUvtnWpIcnxECsYr6yooWsTSi8KK5Jw+eETj7RXPJj\nbijoxfvKyqyHAgMBAAGjggLJMIICxTCBnAYIKwYBBQUHAQEEgY8wgYwwVQYIKwYB\nBQUHMAKGSWh0dHA6Ly9pY3AtYnJhc2lsLnZhbGlkY2VydGlmaWNhZG9yYS5jb20u\nYnIvYWMtdmFsaWRyZmIvYWMtdmFsaWRyZmJ2NS5wN2IwMwYIKwYBBQUHMAGGJ2h0\ndHA6Ly9vY3NwdjUudmFsaWRjZXJ0aWZpY2Fkb3JhLmNvbS5icjAJBgNVHRMEAjAA\nMB8GA1UdIwQYMBaAFFPLpeR1UJlALL5bFUXJvsswqonFMHAGA1UdIARpMGcwZQYG\nYEwBAgMkMFswWQYIKwYBBQUHAgEWTWh0dHA6Ly9pY3AtYnJhc2lsLnZhbGlkY2Vy\ndGlmaWNhZG9yYS5jb20uYnIvYWMtdmFsaWRyZmIvZHBjLWFjLXZhbGlkcmZidjUu\ncGRmMIG2BgNVHR8Ega4wgaswU6BRoE+GTWh0dHA6Ly9pY3AtYnJhc2lsLnZhbGlk\nY2VydGlmaWNhZG9yYS5jb20uYnIvYWMtdmFsaWRyZmIvbGNyLWFjLXZhbGlkcmZi\ndjUuY3JsMFSgUqBQhk5odHRwOi8vaWNwLWJyYXNpbDIudmFsaWRjZXJ0aWZpY2Fk\nb3JhLmNvbS5ici9hYy12YWxpZHJmYi9sY3ItYWMtdmFsaWRyZmJ2NS5jcmwwDgYD\nVR0PAQH/BAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDCBnQYD\nVR0RBIGVMIGSgR1nZXNpYW5lQGdlc2lhbmVsb3VyZWRvLmNvbS5icqA4BgVgTAED\nAaAvBC0wMjAxMTk4NDEwNDY5OTgxNzA5MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw\nMDCgFwYFYEwBAwagDgQMMDAwMDAwMDAwMDAwoB4GBWBMAQMFoBUEEzAwMDAwMDAw\nMDAwMDAwMDAwMDAwDQYJKoZIhvcNAQELBQADggIBADZj9JIDrq62FpHCF6pE/up9\nWtNrFJysiRfR7IUJKsj2EzL+HpDRA+Dr0T7rI7VDksKwBr1m/mVxKtC7H/AUa6t+\n3zXfH1Ryj1HoPBYNNt2KPFcfTHjPo9ah/bmDv3aA5pfpRAZrMomfD5qzQujbIH0U\nbH+Z5PNmC4vuZhU3aI334u1ztuhiwMNpBnRvtQOwD+/dQACiTktE2xj667c09KRZ\neNxT1ByAMib1JJt175ovF+l1MT3FA4h0PSiK7iNyFbhewExu9CmU2ixi7mk00qUC\nxSjNvLJuHayelxfpeOGkJ+Q2Zg7HRfu7zvD1F+6WbJmGzPiS8/5xB6ivpHD9C4Vv\nkq5hKIiGiJBbGiNZGfNBUzHocKHxYN9Qxgj/XLzjJEkSBhhPESVVuTBqkAYISuwv\nsyqZe1H+mM14ifvsdqq8IJzTl9Ii6JvvbZBFXLelu2xXlas00yE4muZV/nnFOnNR\nFjPbscq+fHOREPbZIALeT0EVUjDnID1325kLGQx9cRE2j3GswBRvuQpbZZLqfcpc\nh7miq/rQFaav3t1tQjEQ2g/atqgSBHqmQZnh4msIHqrW5WFM9rE/6tanDWQ5Vd5H\nEuykLJm7AvXKQnNhZhO6kQ49SFN1+/AXxhdqeCdzBWpg/SiELAdtYheXJLDC0gZW\n41LnKzM8WzI3NPwXC9Nq\n-----END CERTIFICATE-----\n", "fingerprint256": "EE:9E:F4:78:9D:93:4D:2B:77:AC:08:FE:5D:36:C4:27:6A:EB:73:C1:C2:C0:69:FA:BA:94:7D:51:CA:5F:B5:54", "subjectAlternatives": "email:gexxx@gesxnxxxxx.com.br" }, "signatures": [ { "signatureId": "01JEE2TDRMBVMPHKM8S2AWQ2S0", "contentId": "1", "contentDigest": "NgiGYmzUlAf0xLNDTdQQGP7XdPzrNDjgClsgA3fcpVA=", "contentDescription": "DOCUMENTO_PDF", "signedContent": "vyBnlyq4Plv4lUkaSwpUUmIjGXKZaY6yYnjUmiZA4UH0ypTLF7zgoi+O2i87kVyjMiO/mZ1JcOxIQpepD8dgFyWBA8Sn8g4IrTFfIe8dYQPy8v6zqZyYTXg+Rywupd6Qqo4wWEyay0p/7tnTVSCTA1YJLsVuvOAWc291gG6jdy0w39H+3dBYl1dAhtz6qExXXX/1eAgVDBw65UfvVzAU6YTM08G6+SrrUdTJgwToILACtW8aFZrIzK4kvXqhHBrF1+hL/85lFstEoNEeXISwR11WBc2Ek9f/YV4yPu9JVmHCUd/QpTyWJ5avnIzMuYR+UJlRNfxZaTYbKAEYlnGeiw==", "signatureTimestamp": "2024-12-06T13:33:49.369Z", "extended": {} } ] }}
Я ценю любую помощь.
Я ценю любую помощь.
Я ценю любую помощь. p>
Обновление 1
Сразу после того, как я опубликовал вопрос, я смог его подписать.
Код выглядел так.
Подготовка контейнера
Код: Выделить всё
private static String emptySignature(String src, String dest, String fieldname)
throws IOException, GeneralSecurityException {
PdfReader reader = new PdfReader(src);
PdfSigner signer = new PdfSigner(reader, new FileOutputStream(dest), new StampingProperties());
com.itextpdf.signatures.PdfSignatureAppearance appearance = signer.getSignatureAppearance();
appearance.setPageRect(new Rectangle(0, 0, 0, 0));
appearance.setPageNumber(1);
appearance.setReason("For test");
appearance.setLocation("HKSAR");
signer.setFieldName(fieldname);
PreSignatureContainer external = new PreSignatureContainer(PdfName.Adobe_PPKLite, PdfName.Adbe_pkcs7_detached);
signer.signExternalContainer(external, 8192);
return Base64.getEncoder().encodeToString(external.getHash());
}
public static class PreSignatureContainer implements IExternalSignatureContainer {
private final PdfDictionary sigDic;
private byte[] hash;
public PreSignatureContainer(PdfName filter, PdfName subFilter) {
sigDic = new PdfDictionary();
sigDic.put(PdfName.Filter, filter);
sigDic.put(PdfName.SubFilter, subFilter);
}
@Override
public byte[] sign(InputStream data) throws GeneralSecurityException {
String hashAlgorithm = "SHA256";
BouncyCastleDigest digest = new BouncyCastleDigest();
try {
byte[] hash = DigestAlgorithms.digest(data, digest.getMessageDigest(hashAlgorithm));
this.hash = hash;
} catch (IOException e) {
throw new GeneralSecurityException("PreSignatureContainer signing exception", e);
}
return new byte[0];
}
@Override
public void modifySigningDictionary(PdfDictionary signDic) {
signDic.putAll(sigDic);
}
public byte[] getHash() {
return hash;
}
}
Код: Выделить всё
public String getSignedContent(String tempPdfPath, JSONObject jsonObject) throws IOException {
PdfReader reader = null;
try {
// Obtém o valor de "signedContent" diretamente do JSON
String signedContentBase64 = jsonObject
.getJSONObject("data")
.getJSONArray("signatures")
.getJSONObject(0) // Primeiro (e único) objeto
.getString("signedContent");
// Decodificar o conteúdo assinado de Base64
byte[] signedContent = Base64.getDecoder().decode(signedContentBase64);
// Certificado do JSON para validar a assinatura
String encodedCertificate = jsonObject
.getJSONObject("data")
.getJSONObject("certificateInformation")
.getString("encodedX509");
byte[] certificateBytes = Base64.getDecoder().decode(
encodedCertificate.replace("-----BEGIN CERTIFICATE-----", "")
.replace("-----END CERTIFICATE-----", "")
.replace("\n", "")
);
// Criar um objeto X509Certificate a partir dos dados do certificado
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
X509Certificate certificate;
try (ByteArrayInputStream certInputStream = new ByteArrayInputStream(certificateBytes)) {
certificate = (X509Certificate) certFactory.generateCertificate(certInputStream);
}
reader = new PdfReader(tempPdfPath);
byte[] signedPdfBytes;
try (ByteArrayOutputStream signedPdfOutputStream = new ByteArrayOutputStream()) {
// Criar um PdfSigner para o PDF assinado
PdfSigner signer = new PdfSigner(reader, signedPdfOutputStream, new StampingProperties());
// Criar um contêiner PKCS7
PdfPKCS7 pkcs7 = new PdfPKCS7(null, new X509Certificate[]{certificate}, "SHA256", null, new BouncyCastleDigest(), false);
pkcs7.setExternalDigest(signedContent, null, "RSA");
// Obter o pacote PKCS7
byte[] pkcs7Bytes = pkcs7.getEncodedPKCS7(null, PdfSigner.CryptoStandard.CMS, null, null, null);
// Usar signDeferred para assinar o campo de assinatura existente
// Criar um contêiner de assinatura que implemente IExternalSignatureContainer
IExternalSignatureContainer external = new MyExternalSignatureContainer(pkcs7Bytes);
String fieldName = "Signature1"; // Nome do campo de assinatura existente
PdfSigner.signDeferred(signer.getDocument(), fieldName, signedPdfOutputStream, external);
// Obter os bytes do PDF assinado
signedPdfBytes = signedPdfOutputStream.toByteArray();
}
// Codificar o PDF assinado em Base64 e retornar
return Base64.getEncoder().encodeToString(signedPdfBytes);
} catch (Exception e) {
System.err.println("Erro ao processar o JSON ou assinar o PDF: " + e.getMessage());
return null; // Retorna nulo em caso de erro
} finally {
if (reader != null) {
reader.close();
}
// Apagar o arquivo temporário
File tempFile = new File(tempPdfPath);
if (tempFile.exists()) {
tempFile.delete();
}
}
}
private static class MyExternalSignatureContainer implements IExternalSignatureContainer {
private final byte[] pkcs7Bytes;
public MyExternalSignatureContainer(byte[] pkcs7Bytes) {
this.pkcs7Bytes = pkcs7Bytes;
}
@Override
public byte[] sign(InputStream data) {
return pkcs7Bytes;
}
@Override
public void modifySigningDictionary(PdfDictionary signDic) {
// Implementação do método de modificação do dicionário de assinatura
}
}
Код: Выделить всё
{
"data": {
"credentialId": "string",
"executionStatus": {
"currentStatus": "PENDING_SIGNATURE",
"requestTimestamp": "2019-08-24T14:15:22Z",
"executionTimestamp": "2019-08-24T14:15:22Z"
},
"subjectIdentification": {
"identificationKey": "string",
"identificationType": "CPF"
},
"certificateInformation": {
"serialNumber": "string",
"issuerName": "string",
"validity": {
"notBefore": "1977-01-01T00:00:00Z",
"notAfter": "1977-01-01T00:00:00Z"
},
"subjectName": "string",
"encodedX509": "string",
"fingerprint256": "string"
}
}
}
На некоторых машинах при открытии PDF-файла отображается это предупреждение.
"Личность подписавшего неизвестна, поскольку она не была включена в ваш список доверенных лиц, и ни один из родительских сертификатов не является доверенным сертификатом"
здесь — это вывод PDFSIG PDF-файла, который отображается без какого-либо предупреждения.
Код: Выделить всё
NSS_Init failed: security library: bad database.
Подпись №1:
- Имя поля подписи: 25e8a269 -03a8-4685-ae26-3e746805c0f3@validpsc
- Общее имя сертификата подписавшего: GESIANE DA SILVA LOUREDO:10469981709
- Полное отличительное имя подписавшего: CN=GESIANE DA SILVA LOUREDO:10469981709,OU=33583550000130,OU=Presencial,OU=AR CFM,OU=AC VALID RFB V5,OU= RFB e-CPF A3,OU=Secretaria da Receita Federal do Brasil - RFB,O=ICP-Brasil,C=BR
- Время подписания: 14 ноября 2023 г., 06:03:11
- Алгоритм хеширования подписи: SHA-256
- Тип подписи: ETSI.CAdES.detached
- Диапазоны подписей: [0–1223818], [1327786–1329701]
- Всего подписанных документов
- Проверка подписи: подпись действительна .
- Проверка сертификата: эмитент сертификата не является доверенным.
Код: Выделить всё
NSS_Init failed: security library: bad database.
Подпись №1:
- Имя поля подписи: Signature1
- Общее имя сертификата подписавшего: GESIANE DA SILVA LOUREDO: 10469981709
- Полное отличительное имя подписавшего: CN=GESIANE DA SILVA LOUREDO:10469981709,OU=33583550000130,OU=Presencial,OU=AR CFM,OU=AC VALID RFB V5,OU=RFB e-CPF A3,OU=Secretaria da Receita Federal do Brasil - RFB,O= МСП-Бразилия, C=BR
- Время подписания: 9 декабря 2024 г., 10:34:35
- Хеш-алгоритм подписи: SHA-256
- Тип подписи: adbe. pkcs7.detached
- Диапазоны знаков: [0–141], [16527–73936]
- Всего подписанных документов
- Проверка подписи: подпись действительна.
- Проверка сертификата: издатель сертификата неизвестен.
PDF создан с использованием кода обновления 1
Нет Предупреждение PDF
Обновить 2
Это будет полный json при вызове для получения учетных данных пользователя. Этот вызов можно сделать перед подписанием, чтобы мы могли получить доступ к сертификату. Как можно было бы включить всю цепочку сертификатов, чтобы сделать сертификат полностью действительным?
Код: Выделить всё
{
"credentialId": "01JERJKX21PRNP0VN8VVV1C6WC",
"currentTimestamp": "2024-12-10T15: 23: 41.101Z",< "expireTimestamp": "2024-12-11T03:23: 40.979Z",
"executionsStatus": {
"currentStatus": "PENDING_SIGNATURE",
"requestTimestamp": "2024-12-10T15: 23: 40.979Z"
} ,
"subjectIdentification": {
"identificationKey": "xxxxxxxxxxxxx",
"identificationType": "CPF"
},
"certificateInformation": {
"serialNumber": "51AD3A27FFEA6DB6",
"issuerName": "C=BR\nO =ICP-Бразилия\nOU=Секретариат федеральных доходов Бразилии - RFB\nCN=AC VALID RFB v5",
"validity": {
"notBefore": "10 декабря 12:49:47 2024 по Гринвичу",
"notAfter": "10 декабря 12:49:47 2028 по Гринвичу"
},
"subjectName" : "C=BR\nO=ICP-Brasil\nOU=Секретариат федеральных доходов Бразилии - RFB\nOU=RFB e-CPF A3\nOU=AC VALID RFB V5\nOU=AR VALID CD\nOU=Видеоконференция\nOU=14121957000109\nCN=: ",
"encodedX509": "-----НАЧАТЬ СЕРТИФИКАТ----- \ nMIIH3zCCBcegAwIBAgIIUa06J //qbbYwDQYJKoZIhvcNAQELBQAwdDELMAkGA1UE\nBhMCQlIxEzARBgNVBAoTCklDUC1CcmFzaWwxNjA0BgNVB AsTLVNlY3JldGFyaWEg\nZGEgUmVjZWl0YSBGZWRlcmFsIGRvIEJyYXNpbCAtIFJGQjEYMBYGA1UEAxMPQUMg\ nVkFMSUQgUkZCIHY1MB4XDTI0MTIxMDEyNDk0N1oXDTI4MTIxMDEyNDk0N1owggEO\nMQswCQYDVQQGEwJCUjE TMBEGA1UEChMKSUNQLUJyYXNpbDE2MDQGA1UECxMtU2Vj\ncmV0YXJpYSBkYSBSZWNlaXRhIEZlZGVyYWwgZG8g QnJhc2lsIC0gUkZCMRUwEwYD\nVQQLEwxSRkIgZS1DUEYgQTMxGDAWBgNVBAsTD0FDIFZBTelEIFJGQiBWNTEU MBIG\nA1UECxMLQVIgVkFMSUQgQ0QxGTAXBgNVBAsTEFZpZGVvY29uZmVyZW5jaWExFzAV\nBgNVBAsTDjE0MT IxOTU3MDAwMTA5MTcwNQYDVQQDEy5HQUJSSUVMIFJFR0lOQVRU\nTyBERSBTT1VaQSBNRU5FWkVTOjE0NTM1MT g1NzYwMIIBijANBgkqhkiG9w0BAQEF\nAAOCAQ8AMIIBCgKCAQEAulPYtW3LdO36C7Y+DEJR60YjqK1gP71Mpy5 rm2nf3iAN\nMJNjHi+qXCJOflz4fRrbpUvBUbScf72a+/z9BtfpI7Gkj4E4xaRPU49oJ4aKhIBH\nVCoTBRnw2 LNINKkGvZRuoetZK/Chqd3THbr5tXifWuakqY08JgN1C3X06FrvE3HW\ngegWi2Q7usWrC8M3nYpE/ENVX6Nh1 1+7eHT80FSCzRJQF6902hnTGGyrWFmfeCsC\n5jZS4HgroqbPAOHJ0PLxUYweW+hUxbMIjGneBI38cLEhiX3KP sAyRTpI2Rykhnr6\nTNM91BmnXrtMDutkeBou4GXmo1xOglxRmlUIJbOfKQIDAQABo4IC1zCCATMwgZwG\nCCsG AQUFBwEBBIGPMIGMMFUGCCsGAQUFBzAChklodHRwOi8vaWNwLWJyYXNpbC52\nYWxpZGNlcnRpZmljYWRvcmEu Y29tLmJyL2FjLXZhbGlkcmZiL2FjLXZhbGlkcmZi\ndjUucDdiMDMGCCsGAQUFBzABhidodHRwOi8vb2NzcHY1 LnZhbGlkY2VydGlmaWNh\nZG9yYS5jb20uYnIwCQYDVR0TBAIwADafBgNVHSMEGDAWgBRTy6XkdVCZQCy+WxVF \nyb7LMKqJxTBwBgNVHSAEaTBnMGUGBmBMAQIDJDBbMFkGCCsGAQUFBwIBFk1odHRw\nOi8vaWNwLWJyYXNpbC5 2YWxpZGNlcnRpZmljYWRvcmEuY29tLmJyL2FjLXZhbGlk\ncmZiL2RwYy1hYy12YWxpZHJmYnY1LnBkZjCBtgY DVR0fBIGuMIGrMFOgUaBPhk1o\ndHRwOi8vaWNwLWJyYXNpbC52YWxpZGNlcnRpZmljYWRvcmEuY29tLmJyL2F jLXZh\nbGlkcmZiL2xjci1hYy12YWxpZHJmYnY1LmNybDBUoFKgUIZOaHR0cDovL2ljcC1i\ncmFzaWwyLnZhb GlkY2VydGlmaWNhZG9yYS5jb20uYnIvYWMtdmFsaWRyZmIvbGNy\nLWFjLXZhbGlkcmZidjUuY3JsMA4GA1UdDw EB/wQEAwIF4DAdBgNVHSUEFjAUBggr\nBgEFBQcDAgYIKwYBBQUHAwQwgasGA1UdEQSBozCBoIEmZ2FicmllbC 5tZW5lemVz\nQG1lZGlsYWJzaXN0ZW1hcy5jb20uYnKgPQYFYEwBAwGgNAQyMTcwMzE5OTcxNDUz\nNTE4NTc2 MDAwMDAwMDAwMDAwMDAwMDAwMjc2Mzc2NjU0U1NQUkqgFwYFYEwBAwag\nDgQMMDAwMDAwMDAwMDAwoB4GBWBM AQMFoBUEEzAwMDAwMDAwMDAwMDAwMDAwMDAw\nDQYJKoZIhvcNAQELBQADggIBABn/VN6HAsGmWTSKAesgr1xXQ jfmxi4aLhIs+24K\nNsBTqQv4XfUg7Rjq52SIcz9gSYcISLUACo0bz1HcR3hfEu8UA0aiEROHba6tLemc\nyZA KXyCtskzD4cWoP3pGxXDFINpwCiCK54yGUki6T5PPOIgVZkJDxYevEW4aU4YB\nkYPXNa6ub+HSuiZkGa4A4PL xcZfkL7GGJ3WpOzT8i6mSas3XLbybtLsG6BbiHiGE\nVXxNwTpMPEeDMev2eSYJLoa0Amrkd9yQ9kCli3Vvjgh mYyIk4tStDjjXrP2XMOCY\nNfNqTU10H5Yofz82AIRqMFiHswhp6m6W1nJn1V+nSlocX7NpIXWhdXJsZTq6s1kG \nDZUsR36b7a6/VC7k9fs2lbAs7hmqxL1ASUqfzN90RQ8NhFD6qS/UDAUNz1txMCuT\nAwmZKtx1PjxVypGh+6 b5zOjdaS1V6wXyQvPKcogk7DoKyMBkGjkbWTRZaPIgqNVM\nV8/BeijdPq1H/VvQzJXWUAk6S0MkX1puDjiZ+VR BTLTxpXmkyggV6Wy+EUL43obN\nsD3YvCsXldlnx5TZyz6lyqOAFG+1VDqO/6lju0kZ/d/CHJLBFg76YwFEuPP qr2O6\nJ4wx2ROymyn0pyXrxx6aEKmgpQu5HCk8f80zB26mftFUnPdq/8qAtMv6QGk4cv34\nd9IK\n-----END СЕРТИФИКАТ-----\n",
"fingerprint256": "36:F6:BA:18:88:CF:58:18:51:F6:21:DF:67:B4:A8:8A :E5:E5:69:FA:88:18:04:FB:3D:CA:8E:38:BA:31:DA:C8",
"subjectAlternatives": "электронная почта: xxx@yyy.com.br"
}
}
Обновление 3:< /strong>
Мне удалось реализовать включение цепочки сертификатов согласно вашему предложению. Вот код, который я использовал для создания цепочки сертификатов из расширения AIA и включения ее в подпись PDF.
Создание цепочки сертификатов:
Код: Выделить всё
// Method to build the certificate chain
private static List buildCertificateChain(X509Certificate certificate) throws Exception {
List chain;
X509Certificate currentCert = certificate;
// Extract the AIA extension
byte[] aiaExtension = currentCert.getExtensionValue("1.3.6.1.5.5.7.1.1"); // AIA OID
// Extract the CA issuer URI using BouncyCastle
Optional caIssuerURI = extractAIAUriUsingBC(aiaExtension);
chain = downloadCertificateChain(caIssuerURI.get(), certificate);
return chain;
}
// Method to extract the AIA URI using BouncyCastle
private static Optional extractAIAUriUsingBC(byte[] aiaExtension) {
try (ASN1InputStream asn1InputStream = new ASN1InputStream(aiaExtension)) {
ASN1Primitive derObject = asn1InputStream.readObject();
if (derObject instanceof DEROctetString) {
derObject = ASN1Primitive.fromByteArray(((DEROctetString) derObject).getOctets());
}
AuthorityInformationAccess aia = AuthorityInformationAccess.getInstance(derObject);
if (aia != null) {
for (AccessDescription accessDescription : aia.getAccessDescriptions()) {
if (X509ObjectIdentifiers.id_ad_caIssuers.equals(accessDescription.getAccessMethod())) {
GeneralName generalName = accessDescription.getAccessLocation();
if (generalName.getTagNo() == GeneralName.uniformResourceIdentifier) {
String uri = generalName.getName().toString();
return Optional.of(uri);
}
}
}
}
} catch (Exception e) {
System.err.println("Error processing AIA extension: " + e.getMessage());
}
return Optional.empty();
}
// Method to download the CA certificate chain
private static List downloadCertificateChain(String uri, X509Certificate certificat) throws Exception {
System.out.println("Downloading certificate from: " + uri);
Security.addProvider(new BouncyCastleProvider());
URL url = new URL(uri);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
try (InputStream inputStream = connection.getInputStream()) {
byte[] pkcs7Bytes = readAllBytesFromInputStream(inputStream);
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
Collection
Подробнее здесь: [url]https://stackoverflow.com/questions/79267552/sign-pdf-using-itext-java-with-certificate-in-cloud-with-no-container-cms-naked[/url]
Мобильная версия