I am try to add a digital signature to a pdf using java api, and signature was read by epass2003 token. so,here i done this job(add digital signature to pdf),
and its working fine, but when i open this pdf document in another system it shows
the "Atleast one signature has problem", bu in my system validate sign correctly please help me.I have attached my code below please find it.
public class Test {
public static void main(String args[]) throws IOException, GeneralSecurityException, DocumentException, CertificateVerificationException{
// Create instance of SunPKCS11 provider
String userFile = "C:/results/test.pdf";
String userFile_signed = "C:/results/test_signed.pdf";
String pkcs11Config = "name=eToken\nlibrary=C:\\Windows\\System32\\eps2003csp11.dll";
java.io.ByteArrayInputStream pkcs11ConfigStream = new java.io.ByteArrayInputStream(pkcs11Config.getBytes());
sun.security.pkcs11.SunPKCS11 providerPKCS11 = new sun.security.pkcs11.SunPKCS11(pkcs11ConfigStream);
java.security.Security.addProvider(providerPKCS11);
// Get provider KeyStore and login with PIN
String pin = "12345678";
java.security.KeyStore keyStore = java.security.KeyStore.getInstance("PKCS11", providerPKCS11);
keyStore.load(null, pin.toCharArray());
// Enumerate items (certificates and private keys) in the KeyStore
java.util.Enumeration<String> aliases = keyStore.aliases();
String alias = null;
while (aliases.hasMoreElements()) {
alias = aliases.nextElement();
System.out.println(alias);
}
PrivateKey pk = (PrivateKey)keyStore.getKey(alias, "12345678".toCharArray());
Certificate[] chain = keyStore.getCertificateChain(alias);
OcspClient ocspClient = new OcspClientBouncyCastle();
TSAClient tsaClient = null;
for (int i = 0; i < chain.length; i++) {
X509Certificate cert = (X509Certificate)chain[i];
String tsaUrl = CertificateUtil.getTSAURL(cert);
if (tsaUrl != null) {
tsaClient = new TSAClientBouncyCastle(tsaUrl);
break;
}
}
List<CrlClient> crlList = new ArrayList<CrlClient>();
crlList.add(new CrlClientOnline(chain));
Test t = new Test();
t.sign(userFile, userFile_signed, chain, pk, DigestAlgorithms.SHA256, providerPKCS11.getName(),
CryptoStandard.CMS, "Test", "Signature", crlList, ocspClient, tsaClient, 0);
}
public void sign(String src, String dest,
Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider, CryptoStandard subfilter,
String reason, String location,
Collection<CrlClient> crlList,
OcspClient ocspClient,
TSAClient tsaClient,
int estimatedSize)
throws GeneralSecurityException, IOException, DocumentException {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setReason(reason);
appearance.setLocation(location);
appearance.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, "sig");
// Creating the signature
ExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
}
so above is my code please help me.
Looking at the signature properties one sees:
This dialog states the problem:
The signer's identity is unknown because it has not been included in your list of trusted certificates and none of its parent certificates are trusted certificates.
Furthermore a look at the signer's certificate shows:
Thus, your code only embeds the signer certificate itself, not its certificate path (otherwise they would have shown in the certificate viewer window). Unfortunately the issuer certificate (SafeScrypt sub-CA for RCAI Class 2 2014) is not immediately trusted, neither is that certificate's issuer (SafeScrypt CA 2014), but that certificate's issuer (CCA India 2014) in turn is.
Most likely on your computer either the whole certificate chain is known or at least up to a certificate which is explicitly trusted.
To get the same effect on other computers which only know the root certificate, simply add the certificates for "SafeScrypt sub-CA for RCAI Class 2 2014" and "SafeScrypt CA 2014" to your Certificate[] chain.
Related
Trying to add digital signature(.JKS file) to pdf by using below code. Problem is that when run the code using self signed digital certificate its working fine but when we run the code with signer digital certificate (verisign) its giving NullPointerException.
KeyStore ks = null;
PrivateKey key = null;
Certificate[] chain = null;
PdfStamper stp = null;
PdfReader pdfreader = null;
PdfSignatureAppearance sap = null;
int numberPages = 0;
ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(jksFile), jksPassword.toCharArray());
String alias = (String) ks.aliases().nextElement();
key = (PrivateKey) ks.getKey(alias, jksPassword.toCharArray());
chain = ks.getCertificateChain(alias);
pdfreader = new PdfReader(baos.toByteArray());
numberPages = pdfreader.getNumberOfPages();
stp = PdfStamper.createSignature(pdfreader, baosWithSign, '\0');
stp.setEncryption(null, null, PdfWriter.AllowPrinting, PdfWriter.STRENGTH128BITS);
sap = stp.getSignatureAppearance();
sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
sap.setVisibleSignature(new Rectangle(532, 50, 532 + 30, 50 + 30), numberPages, null);
stp.close();
baos.close();
Exception:
Exception in thread "main" java.lang.NullPointerException
at com.lowagie.text.pdf.PdfSignatureAppearance.getAppearance(PdfSignatureAppearance.java:395)
at com.lowagie.text.pdf.PdfSignatureAppearance.preClose(PdfSignatureAppearance.java:902)
at com.lowagie.text.pdf.PdfSignatureAppearance.preClose(PdfSignatureAppearance.java:847)
at com.lowagie.text.pdf.PdfStamper.close(PdfStamper.java:175)
at testjks.ConvertPDFtoByteArray.convertPDFToDigitalSigatureAndPassword(ConvertPDFtoByteArray.java:99)
at testjks.ConvertPDFtoByteArray.main(ConvertPDFtoByteArray.java:115)
Even i tried with below but same error
sap.setCrypto(key, chain, null, PdfSignatureAppearance.VERISIGN_SIGNED);
Can any one help, Why i am getting PrivateKey object and Certificate[] object as null, where as selfsigned digital certificate giving output. Is there any extra code required for signer digital certificate.
For a project I have to digitally sign PDFs on an additionally created page by multiple people in a workflow. To realize this we're using the iText 7 libraries with following code, based on Bruno Lowagie's examples:
public static void main(String[] args) throws IOException, GeneralSecurityException, XMPException {
String path = "F:/Java/keystores/testPdfSign";
char[] pass = "test".toCharArray();
KeyStore ks = KeyStore.getInstance("pkcs12", "SunJSSE");
ks.load(new FileInputStream(path), pass);
String alias = "";
Enumeration<String> aliases = ks.aliases();
while (alias.equals("tester")==false && aliases.hasMoreElements())
{
alias = aliases.nextElement();
}
PrivateKey pk = (PrivateKey) ks.getKey(alias, pass);
Certificate[] chain = ks.getCertificateChain(alias);
PDFSign app = new PDFSign();
app.sign(SRC, DEST, chain, pk, DigestAlgorithms.SHA1, "SunJSSE", PdfSigner.CryptoStandard.CMS, "Test", "Test", null, null, null, 0);
}
public void sign(String src, String dest,
Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider, PdfSigner.CryptoStandard subfilter,
String reason, String location,
Collection<ICrlClient> crlList,
IOcspClient ocspClient,
ITSAClient tsaClient,
int estimatedSize)
throws GeneralSecurityException, IOException, XMPException {
// Creating the reader and the signer
PdfDocument document = new PdfDocument(new PdfReader(SRC), new PdfWriter(DEST+"_temp"));
if (initial == true)
{
document.addNewPage();
}
int pageCount = document.getNumberOfPages();
document.close();
PdfSigner signer = new PdfSigner(new PdfReader(DEST+"_temp"), new FileOutputStream(DEST), true);
// Creating the appearance
if (initial == true)
{
signer.setCertificationLevel(PdfSigner.CERTIFIED_FORM_FILLING_AND_ANNOTATIONS);
}
PdfSignatureAppearance appearance = signer.getSignatureAppearance()
.setReason(reason)
.setLocation(location)
.setReuseAppearance(false);
Rectangle rect = new Rectangle(10, 400, 100, 100);
appearance
.setPageRect(rect)
.setPageNumber(pageCount);
appearance.setRenderingMode(RenderingMode.NAME_AND_DESCRIPTION);
signer.setFieldName(signer.getNewSigFieldName());
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
ProviderDigest digest = new ProviderDigest(provider);
signer.signDetached(digest, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
This results in an invalid signature in the new signed version of the PDF, as Adobe Acrobat Reader says it has been edited after signing. Surprisingly when I open the file in Foxit Reader it says it hasn't been modified and is valid.
Also what I tried was to leave out the first step of adding a new page and just sign on the last page of the original document, then the signature is valid in Adobe Reader, but no solution for my situation, as an extra page is a must have.
The other thing I tried was not setting the certificationLevel to CERTIFIED_FORM_FILLING_AND_ANNOTATIONS, but just leaving it at the default NOT_CERTIFIED, this way I also had a valid signature on a new page, but this is not a solution either, because it won't let me add any additional signatures later on.
Does someone have an idea what could be the reason for Adobe Reader rating the signature as invalid and/or has a solution to this problem?
Thanks in Advance
David
In short
I could not reproduce the OP's issue. Running his code (with slight adaptions to local circumstances) resulted in a java.security.NoSuchAlgorithmException: no such algorithm: SHA1 for provider SunJSSE. Having replaced the provider argument "SunJSSE" to the sign call with "BC", on the other hand, the code creates a properly certified PDF.
The adapted code
I usually examine code from stackoverflow in the form of a JUnit test; this implies a few changes. Furthermore, the OP's code contained a number of variables which were referenced but not defined; these had to be given a definition. Finally i load the file to sign from a resource as stream, not from the file system as file.
Thus:
final static File RESULT_FOLDER = new File("target/test-outputs", "signature");
#BeforeClass
public static void setUpBeforeClass() throws Exception
{
RESULT_FOLDER.mkdirs();
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
}
#Test
public void testSignLikeXinDHA() throws GeneralSecurityException, IOException, XMPException
{
String path = "keystores/demo-rsa2048.p12";
char[] pass = "demo-rsa2048".toCharArray();
KeyStore ks = KeyStore.getInstance("pkcs12", "SunJSSE");
ks.load(new FileInputStream(path), pass);
String alias = "";
Enumeration<String> aliases = ks.aliases();
while (alias.equals("demo") == false && aliases.hasMoreElements())
{
alias = aliases.nextElement();
}
PrivateKey pk = (PrivateKey) ks.getKey(alias, pass);
Certificate[] chain = ks.getCertificateChain(alias);
try ( InputStream resource = getClass().getResourceAsStream("/mkl/testarea/itext7/content/test.pdf"))
{
sign(resource, new File(RESULT_FOLDER, "test_XinDHA_signed_initial.pdf").getAbsolutePath(),
chain, pk, DigestAlgorithms.SHA1, /*"SunJSSE"*/"BC", PdfSigner.CryptoStandard.CMS, "Test", "Test",
null, null, null, 0, true);
}
}
public void sign(InputStream src, String dest, Certificate[] chain, PrivateKey pk, String digestAlgorithm,
String provider, PdfSigner.CryptoStandard subfilter, String reason, String location,
Collection<ICrlClient> crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize,
boolean initial)
throws GeneralSecurityException, IOException, XMPException
{
// Creating the reader and the signer
PdfDocument document = new PdfDocument(new PdfReader(src), new PdfWriter(dest + "_temp"));
if (initial == true)
{
document.addNewPage();
}
int pageCount = document.getNumberOfPages();
document.close();
PdfSigner signer = new PdfSigner(new PdfReader(dest + "_temp"), new FileOutputStream(dest), true);
// Creating the appearance
if (initial == true)
{
signer.setCertificationLevel(PdfSigner.CERTIFIED_FORM_FILLING_AND_ANNOTATIONS);
}
PdfSignatureAppearance appearance = signer.getSignatureAppearance().setReason(reason).setLocation(location)
.setReuseAppearance(false);
Rectangle rect = new Rectangle(10, 400, 100, 100);
appearance.setPageRect(rect).setPageNumber(pageCount);
appearance.setRenderingMode(RenderingMode.NAME_AND_DESCRIPTION);
signer.setFieldName(signer.getNewSigFieldName());
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
ProviderDigest digest = new ProviderDigest(provider);
signer.signDetached(digest, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
(AddPageAndSign.java)
Running the code
I ran the code using a fairly recent Oracle Java 8 with Unlimited Strength JavaTM Cryptography Extension Policy Files, BouncyCastle 1.49, and iText either in version 7.0.0 or 7.0.1-SNAPSHOT (the current development branch).
(Definitively use an Oracle Java as downloaded from their web site, some variants of the Oracle JDK (supplied by some Linux distributions) contains changes in the security providers which can break your code.)
Running the code using the provider argument "SunJSSE" to the sign call results in
java.security.NoSuchAlgorithmException: no such algorithm: SHA1 for provider SunJSSE
at sun.security.jca.GetInstance.getService(GetInstance.java:87)
at sun.security.jca.GetInstance.getInstance(GetInstance.java:206)
at java.security.Security.getImpl(Security.java:698)
at java.security.MessageDigest.getInstance(MessageDigest.java:227)
at com.itextpdf.signatures.SignUtils.getMessageDigest(SignUtils.java:134)
at com.itextpdf.signatures.DigestAlgorithms.getMessageDigest(DigestAlgorithms.java:182)
at com.itextpdf.signatures.ProviderDigest.getMessageDigest(ProviderDigest.java:69)
at com.itextpdf.signatures.SignUtils.getMessageDigest(SignUtils.java:127)
at com.itextpdf.signatures.PdfSigner.signDetached(PdfSigner.java:528)
at mkl.testarea.itext7.signature.AddPageAndSign.sign(AddPageAndSign.java:125)
at mkl.testarea.itext7.signature.AddPageAndSign.testSignLikeXinDHA(AddPageAndSign.java:81)
Running the code using the provider argument "BC" to the sign call results in a properly certified PDF with the signature visualization on an extra page:
Why using SunJSSE doesn't make sense
The exception I get with the "SunJSSE" provider actually is not surprising as that provider does not provide a SHA1 algorithm.
According to its documentation by Oracle, it provides no MessageDigest algorithm as such at all, merely in combination as a signature algorithm (SHA1withRSA).
Thus, the IExternalSignature defined in sign as
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
will work because here SHA1withRSA will be used, but the ProviderDigest defined there as
ProviderDigest digest = new ProviderDigest(provider);
will fail because it attempts to use the message digest algorithm SHA1.
As an aside
You use SHA1. As this message digest algorithm is less and less trusted in the context of signature creation, that is not a good idea. I would advise switching to an algorithm of the SHA2 famaily.
I have a XFA-based PDF with some fields need to be signed. However, these fields are embedded in the XFA form, so I can't sign it using the following codes
public void sign(String keystore, char[] password, String src, String name, String dest)
throws GeneralSecurityException, IOException, DocumentException {
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(keystore), password);
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, password);
Certificate[] chain = ks.getCertificateChain(alias);
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', null, true);
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setVisibleSignature(name);
// Creating the signature
PrivateKeySignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256, "BC");
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, MakeSignature.CryptoStandard.CMS);
}
For example, I have a field named "root[0].mainpage[0].root[2].DefaultPage[0].Page1[0].SignArea[0].GSA[0].GSF-shinfo_sh-tmp03_sh_sf[0]". When I tried to put it to the argument "name", I got the error message
"Exception in thread "main" java.lang.IllegalArgumentException: The field root[0].mainpage[0].root[2].DefaultPage[0].Page1[0].SignArea[0].GSA[0].GSF-shinfo_sh-tmp03_sh_sf[0] does not exist."
I've worked on this problem for a week, but I haven't come up with a solution. Is there any ideas about this issue? Thanks!
PS:This is the download url of the file.
I've been trying to implement digital signing (CAdES) for PDF files using Portuguese Citizen Card, however I'm having a hard time figuring out the perfectly working solution. Currently I have two sets of code.
First one:
public void signCAdES(...)
{
String pkcs11Config = "name=GemPC" + "\n" + "library=C:\\WINDOWS\\SysWOW64\\pteidpkcs11.dll";
ByteArrayInputStream configStream = new ByteArrayInputStream(pkcs11Config.getBytes());
Provider pkcs11Provider = new sun.security.pkcs11.SunPKCS11(configStream);
//provider_name: SunPKCS11-GemPC
Security.addProvider(pkcs11Provider);
javax.security.auth.callback.CallbackHandler cmdLineHdlr = new DialogCallbackHandler();
KeyStore.Builder builder = KeyStore.Builder.newInstance("PKCS11", pkcs11Provider,
new KeyStore.CallbackHandlerProtection(cmdLineHdlr));
KeyStore ks= builder.getKeyStore();
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', new File(tempPath), true);
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setReason(reason);
appearance.setLocation(location);
appearance.setCertificationLevel(level);
String alias = "CITIZEN SIGNATURE CERTIFICATE";
//certificates from electronic card and resources folder
Certificate[] certs = getSignatureCertificatesChain(ks);
PrivateKey pk = (PrivateKey) ks.getKey(alias, null);
ExternalSignature es = new PrivateKeySignature(pk, "SHA-1", pkcs11Provider.getName());
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, es, certs, null, null, null, 0, MakeSignature.CryptoStandard.CADES);
}
The first one works, however I have a validator given to me that verifies if the signatures of a PDF satisfies the standards, and it seems that one of the attributes is missing (sigining certificate issuer's serial number).
The second one is different, and I have to add the attributes manually, however the generated PDF is corrupted (and then I might need to add the issuer serial attribute too):
private static void signCAdES(byte[] aDocument, PrivateKey aPrivateKey, Certificate[] certChain, String outputPath) {
try {
Security.addProvider(new BouncyCastleProvider());
ArrayList<X509Certificate> certsin = new ArrayList<X509Certificate>();
for (Certificate certChain1 : certChain) {
certsin.add((X509Certificate) certChain1);
}
X509Certificate signingCertificate= certsin.get(0);
MessageDigest dig = MessageDigest.getInstance("SHA-1");
byte[] certHash = dig.digest(signingCertificate.getEncoded());
ESSCertID essCertid = new ESSCertID(certHash);
DERSet set = new DERSet(new SigningCertificate(essCertid));
Attribute certHAttribute = new Attribute(PKCSObjectIdentifiers.id_aa_signingCertificate, set);
AttributeTable at = getAttributeTableWithSigningCertificateAttribute(certHAttribute);
CMSAttributeTableGenerator attrGen = new DefaultSignedAttributeTableGenerator(at);
SignerInfoGeneratorBuilder genBuild = new SignerInfoGeneratorBuilder(new BcDigestCalculatorProvider());
genBuild.setSignedAttributeGenerator(attrGen);
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
ContentSigner shaSigner = new JcaContentSignerBuilder("SHA1withRSA").build(aPrivateKey);
SignerInfoGenerator sifGen = genBuild.build(shaSigner, new X509CertificateHolder(signingCertificate.getEncoded()));
gen.addSignerInfoGenerator(sifGen);
JcaCertStore jcaCertStore = new JcaCertStore(certsin);
gen.addCertificates(jcaCertStore);
CMSTypedData msg = new CMSProcessableByteArray(aDocument);
CMSSignedData sigData = gen.generate(msg, false); // false=detached
byte[] encoded = sigData.getEncoded();
ASN1InputStream in = new ASN1InputStream(encoded);
CMSSignedData sigData2 = new CMSSignedData(new CMSProcessableByteArray(aDocument), in);
byte[] encoded2 = sigData2.getEncoded();
FileOutputStream fos = new FileOutputStream(outputPath);
fos.write(encoded2);
// fos.write(encoded);
fos.flush();
fos.close();
} catch (CMSException | IOException | OperatorCreationException | CertificateEncodingException ex) {
log("signCAdES", "Error: " + ex.toString());
}
}
Is there anyone who understands CAdES digital signature using Java? Any help would be appreciated!
The 'issuer-serial' attribute is absent or does not match!
It means that your cades signature has not signed attribute: the signed reference to the signing certificate or that this reference is tampered.
Please check: ETSI TS 101 733 V2.2.1 (2013-04) for more information:
5.7.3 Signing Certificate Reference Attributes
The Signing certificate reference attributes are supported by using either the
ESS signing-certificate attribute or the ESS-signing-certificate-v2 attribute...
I have method in order to sign document.
public static void sign(String src, String dest,
java.security.cert.Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider, CryptoStandard subfilter,
String reason, String location) throws GeneralSecurityException,
IOException, DocumentException, com.itextpdf.text.DocumentException {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setVisibleSignature(new Rectangle(0, 100, 50, 300), 1, "sig");
// Creating the signature
ExternalDigest digest = new BouncyCastleDigest();
ExternalSignature signature = new PrivateKeySignature(pk, digestAlgorithm, provider);
MakeSignature.signDetached(appearance, digest, signature, chain, null,null, null, 0, subfilter);
}
When I use BouncyCastleProvider everything works well.
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(KEYSTORE), PASSWORD);
String alias = (String) ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
java.security.cert.Certificate[] chain = ks.getCertificateChain(alias);
for (int i = 0; i < chain.length; i++) {
System.out.println(("Public Key"+chain[i].getPublicKey()));
}
System.out.println("Priate Key:"+ Arrays.toString(pk.getEncoded()));
System.out.println("Lengh of key is:"+ Arrays.toString(pk.getEncoded()).length());
sign(SRC, String.format(DEST, 1), chain, pk,DigestAlgorithms.SHA256, provider.getName(),CryptoStandard.CMS, "Test 1", "Ghent" );
it signs well, and the result is that:
Public Key Sun RSA public key, 2048 bits. I have only Self Sign sertificate here. Created By Key tool.
modulus: 19757623340732442247234242 ... and etc
public exponent: 65537
Priate Key:[48, -126, 4, -66, 2, 1, ... and etc ]
Lengh of key is:5618
Wen I use My provider. I have No Runtime Error or exceptipon but when i open pdf file , I have singature error. adobe reader have that allert ":At least one signature is invalid:. When I try to see the certificate, I have that alert "Error during signature verification. Error encountered while validating. Internal Cryptographic library error. Error Code: 0x2726""
A is root CA. B is Children of A. C is signer certificate. I have also T certificate, Children of A A
MyProvider provider= newMyProvider();
CallbackHandler console= new com.sun.security.auth.callback.TextCallbackHandler();
provider.setCallbackHandler(console);
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance("KeyStore");
ks.load(null, new char[] {});
List < java.security.cert.Certificate > chainList = new ArrayList< java.security.cert.Certificate>();
System.out.println("My Certificates in chain:");
Enumeration<String> aliases = ks.aliases();
while (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
if( alias.equalsIgnoreCase("T")
continue;
if (ks.isCertificateEntry(alias)) {
X509Certificate cert = (X509Certificate) ks.getCertificate(alias);
if(!chainList.contains(ks.getCertificate(alias))){
chainList.add(ks.getCertificate(alias));
}
System.out.println("Public Key"+(cert.getPublicKey()));
}
}
java.security.cert.Certificate[] chain = new java.security.cert.Certificate[chainList.size()];
chainList.toArray(chain);
enter code here
PrivateKey pk = (PrivateKey) ks.getKey("C", null);
System.out.println("Priate Key:"+ Arrays.toString(pk.getEncoded()));
System.out.println("Lengh of key is:"+ Arrays.toString(pk.getEncoded()).length());
sign(SRC, String.format(DEST, 1), chain, pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS, "Test sign", "testing");
Result of command line is that:
My Certificates in chain. First is Main CA .
Public Key Sun RSA public key, 4096 bits
modulus: 7233349847339212226486269.... and etc
public exponent: 65537
Public Key Sun RSA public key, 4096 bits
modulus: 8191375554227623097382171... and etc
public exponent: 65537
Public Key Sun RSA public key, 4096 bits
modulus: 8221477538578824228200634... and etc
public exponent: 65537
Priate Key:[66, 69, 105, 106, 105, 192 ... and etc]
Lengh of key is:306
When I open PDF file, I have singature error, if I use my provider.
:At least one signature is invalid:.
When I try to see the certificate, I have that alert "Error during signature verification. Error encountered while validating. Internal Cryptographic library error. Error Code: 0x2726"
Looking into the signature (using an ASN.1 dump) reveals that:
It includes in its certificates CertificateSet the certificates issued for
C = GE,O = Ministry of Justice of Georgia,OU = Civil Registry Agency,CN = GEO Root CA
C = GE,O = Ministry of Justice of Georgia,OU = Civil Registry Agency,CN = GEO Signing CA
C = GE,O = Ministry of Justice of Georgia,OU = Civil Registry Agency,CN = GEO Authentication CA
It claims in its SignerInfo's sid SignerIdentifier to have used the private key associated with the "GEO Root CA" certificate to sign
Looking at your code, issue 1 indicates that your key store contents are different from what you think. On the one hand "GEO Authentication CA" is present in it at least once with an alias not equal to "T", and on the other hand your signer certificate does not seem to be included (or has alias "T" and is ignored due to that). Your private key is included, though, as "C".
Issue 2 is due to the fact that iText expects the first entry of the certificates array to be the signer certificate. As "GEO Root CA" seems to be the first certificate found in your key store, it is the first certificate in your chainList, so also in your chain, and therefore assumed by iText to be the signer certificate.
To resolve your issue you have to
inspect your key store and make sure it also contains your signer certificate, not merely the associated private key, and
make sure your signer certificate is first in your chain certificate array.
BTW, have you yet tried using
Certificate[] chain = ks.getCertificateChain("C");
to retrieve the certificate chain? This is generally used in Digital Signatures for PDF documents...