Sign PDF from usb Token Using MSCAPI & ITEXT - java

can anyone give me a simle example of pdf signing from usb token using MSCAPI and ITEXT. I do not want to use a fixed ocsp string.
I tried to follow this
Digital Signature book but it did not work. My code was:
LoggerFactory.getInstance().setLogger(new SysoLogger());
BouncyCastleProvider providerBC = new BouncyCastleProvider();
Security.addProvider(providerBC);
SunMSCAPI provdierMSCAP = new SunMSCAPI();
Security.addProvider(provdierMSCAP);
KeyStore ks = KeyStore.getInstance("Windows-MY");
ks.load(null, null);
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey)ks.getKey(alias, null);
Certificate[] chain = ks.getCertificateChain(alias);
PdfReader pdfreader = new PdfReader("HelloWorld.pdf");
FileOutputStream outputFile = new FileOutputStream("Signed.pdf");
PdfStamper pdfstamper;
pdfstamper = PdfStamper.createSignature(pdfreader, outputFile, '\0', null, true);
PdfSignatureAppearance sap = pdfstamper.getSignatureAppearance();
sap.setCrypto(pk, chain, null, PdfSignatureAppearance.SELF_SIGNED);
sap.setReason("Test");
sap.setLocation("Dhaka");
sap.setVisibleSignature(new Rectangle(10, 10, 50, 30), 1, "Test");
pdfstamper.close();
JOptionPane.showMessageDialog(null, "Successfully Signed");
And it is giving me following error:
java.lang.NullPointerException
I tried use itext 5.2.1/itextpdf-5.3.5 and bcmail-jdk16-1.46, bcprov-jdk16-1.46.jar, bctsp-jdk16-1.46.jar.
Can anyone help ? please ................

you are passing null values to load(),try this
ks.load(new FileInputStream("certificate_path"), keystore_password.toCharArray());

remove sap.setCrypto line. you don't need it.

In the latest version, the setCrypo is replaced by the following lines:
ExternalDigest digest = new BouncyCastleDigest();
BouncyCastleProvider provider = new BouncyCastleProvider();
ExternalSignature signature = new PrivateKeySignature(key, DigestAlgorithms.SHA256, provider.getName());
MakeSignature.signDetached(sap, digest, signature, chain, null, null, null, 0, CryptoStandard.CMS);
You have to put bcprov-jdk15on-1.60.jar and bcpkix-jdk15on-1.60.jar in your classpath.

Related

Problem signing PDF documents with iText 5.5.5

I'm trying to sign PDF documents with the library iText 5.5.5.
I have two certificates to sign documents, with one certificate all works perfect and you have a valid signed document. But the problem is with the second certificate, because you can sign the document but if I open the document with Adobe Reader the signature is invalid.
I'm using the same code for both certificates but I don't know why doesn´t works with one certificate. Here is the code that I use to sign the documents with iText 5.5.5
String pkcs11Config = "name=NAME" + "\n" + "library=PATH";
ByteArrayInputStream configStream = new ByteArrayInputStream(pkcs11Config.getBytes());
Provider pkcs11Provider = new sun.security.pkcs11.SunPKCS11(configStream);
Security.addProvider(pkcs11Provider);
KeyStore ks = KeyStore.getInstance("PKCS11");
ks.load(null, password);
PdfReader reader = new PdfReader(pdfInput);
FileOutputStream os = new FileOutputStream(pdfOutputTemp);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', null, true);
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
...
PrivateKey key = (PrivateKey) ks.getKey(alias, pass);
ExternalSignature es = new PrivateKeySignature(key, DigestAlgorithms.SHA256, null);
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, es, chain, crlList, null, tsc, 0, CryptoStandard.CADES);
I also attach two signed documents, one signed with the certificate that has no problems and the other with the certificate that invalidates the signature.
Invalid Document
Valid Document
I appreciate the help you can give me.Thank you

adding signer digital signature to pdf using itext

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.

Digital signature in pdf using java api and epass2003 token

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.

Signing a XFA-based PDF using iText

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.

CAdES Digital Signature

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...

Categories

Resources