Exception when add digital signature to password producted pdf using PDFBOX? - pdf

When I am adding digital signature to the encrypted(password protected) PDF using PDF BOX am getting the following exceptions,
Exception in thread "main" java.lang.NullPointerException
at org.apache.pdfbox.pdmodel.encryption.StandardSecurityHandler.computeRevisionNumber(StandardSecurityHandler.java:128)
at org.apache.pdfbox.pdmodel.encryption.StandardSecurityHandler.prepareDocumentForEncryption(StandardSecurityHandler.java:299)
at org.apache.pdfbox.pdfwriter.COSWriter.write(COSWriter.java:1457)
at org.apache.pdfbox.pdmodel.PDDocument.saveIncremental(PDDocument.java:1396)
at com.seind.pdf.digitalsignature.CreateVisibleSignature.signPDF(CreateVisibleSignature.java:187)
at com.seind.pdf.digitalsignature.CreateVisibleSignature.main(CreateVisibleSignature.java:305)
But when I am using owner password to decrypt the PDF, its not working. its correct a password which I was used to encrypt... I hope you all understand the problem and here is my sample code:
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertStore;
import java.security.cert.Certificate;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.List;
import org.apache.pdfbox.pdfparser.PDFParser;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.encryption.StandardDecryptionMaterial;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureInterface;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSigProperties;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSignDesigner;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.CMSSignedGenerator;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
/**
* This is an example for visual signing a pdf with bouncy castle.
* {#see CreateSignature}
* #author Vakhtang Koroghlishvili
*/
public class CreateVisibleSignature implements SignatureInterface
{
public static final String RESOURCE ="stock1.jpg";//"Paul_Cézanne_222.jpg";//"signature-stamp.jpg";//"SJG_Signature.png";//"amber-signature.png";// "Man-Utd-v-Bayern-Munich-018.jpg";//"check_256.png";//"signature-stamp.jpg";
private static BouncyCastleProvider provider = new BouncyCastleProvider();
private PrivateKey privKey;
private Certificate[] cert;
private SignatureOptions options;
public CreateVisibleSignature()
{
}
/**
* Initialize the signature creator with a keystore (pkcs12) and pin that
* should be used for the signature.
*
* #param keystore is a pkcs12 keystore.
* #param pin is the pin for the keystore / private key
*/
public CreateVisibleSignature(KeyStore keystore, char[] pin)
{
try
{
// grabs the first alias from the keystore and get the private key. An
// alternative method or constructor could be used for setting a specific
// alias that should be used.
Enumeration<String> aliases = keystore.aliases();
String alias = null;
while (aliases.hasMoreElements())
{
alias = aliases.nextElement();
System.out.println(" alias name "+alias);
}
privKey = (PrivateKey) keystore.getKey(alias, pin);
cert = keystore.getCertificateChain(alias);
}
catch (KeyStoreException e)
{
e.printStackTrace();
}
catch (UnrecoverableKeyException e)
{
System.err.println("Could not extract private key.");
e.printStackTrace();
}
catch (NoSuchAlgorithmException e)
{
System.err.println("Unknown algorithm.");
e.printStackTrace();
}
}
/**
* Signs the given pdf file.
*
* #param document is the pdf document
* #param signatureProperties
* #return the signed pdf document
* #throws Exception
*/
public File signPDF(File document, PDVisibleSigProperties signatureProperties) throws Exception
{
PDDocument doc = openPDFDoc(document);
byte[] buffer = new byte[8 * 1024];
if (document == null || !document.exists())
{
new RuntimeException("Document for signing does not exist");
}
// creating output document and prepare the IO streams.
String name = document.getName();
String substring = name.substring(0, name.lastIndexOf("."));
File outputDocument = new File(document.getParent(), substring + "_signed.pdf");
FileInputStream fis = new FileInputStream(document);
FileOutputStream fos = new FileOutputStream(outputDocument);
int c;
while ((c = fis.read(buffer)) != -1)
{
fos.write(buffer, 0, c);
}
fis.close();
fis = new FileInputStream(outputDocument);
// load document
// PDDocument doc = PDDocument.load(document);
// create signature dictionary
PDSignature signature = new PDSignature();
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE); // default filter
// subfilter for basic and PAdES Part 2 signatures
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
signature.setName(signatureProperties.getSignerName());
signature.setLocation("chennai");
//signature.setReason("reason for signature");
// the signing date, needed for valid signature
signature.setSignDate(Calendar.getInstance());
// register signature dictionary and sign interface
options = new SignatureOptions();
options.setVisualSignature(signatureProperties);
// options.setPage(signatureProperties.getPage());
//options.setPreferedSignatureSize(signatureProperties.getPreferredSize());
doc.addSignature(signature, this, options);
doc.saveIncremental(fis, fos);
return outputDocument;
}
PDDocument openPDFDoc(File pdfFile) throws Exception
{
File originalPDF = pdfFile;
PDFParser parser = new PDFParser(new BufferedInputStream(new FileInputStream(originalPDF)));
parser.parse();
PDDocument originialPdfDoc = parser.getPDDocument();
boolean isOriginalDocEncrypted = originialPdfDoc.isEncrypted();
if (isOriginalDocEncrypted)
{
originialPdfDoc.openProtection(new StandardDecryptionMaterial("123456"));
}
return originialPdfDoc;
}
/**
* SignatureInterface implementation.
*
* This method will be called from inside of the pdfbox and create the pkcs7 signature.
* The given InputStream contains the bytes that are given by the byte range.
*
* This method is for internal use only. <-- TODO this method should be private
*
* Use your favorite cryptographic library to implement pkcs7 signature creation.
*/
#SuppressWarnings("deprecation")
#Override
public byte[] sign(InputStream content) throws IOException
{
CMSProcessableInputStream input = new CMSProcessableInputStream(content);
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
// CertificateChain
List<Certificate> certList = Arrays.asList(cert);
CertStore certStore = null;
try
{
certStore = CertStore.getInstance("Collection", new CollectionCertStoreParameters(certList), provider);
gen.addSigner(privKey, (X509Certificate) certList.get(0), CMSSignedGenerator.DIGEST_SHA256);
gen.addCertificatesAndCRLs(certStore);
CMSSignedData signedData = gen.generate(input, false, provider);
return signedData.getEncoded();
}
catch (Exception e)
{
// should be handled
System.err.println("Error while creating pkcs7 signature.");
e.printStackTrace();
}
throw new RuntimeException("Problem while preparing signature");
}
public static void main(String[] args) throws Exception
{
//String pdfPath="E:\\outputs1\\iText in Action.pdf";
String pdfPath="E:\\outputs1\\CNB_20131029_AAPL034_0490301_NSEFO_ECN_iPass.pdf";
// new PdfOptimize().reducePdfSize(pdfPath);
File ksFile = new File("E:/sol.p12");
KeyStore keystore = KeyStore.getInstance("PKCS12", provider);
char[] pin = "xxxxxxx".toCharArray();
keystore.load(new FileInputStream(ksFile), pin);
//String pdfPath="E:\\temp\\pdf\\security\\password\\hello_iText.pdf";
File document = new File(pdfPath);
CreateVisibleSignature signing = new CreateVisibleSignature(keystore, pin.clone());
FileInputStream image = new FileInputStream(RESOURCE);
PDVisibleSignDesigner visibleSig = new PDVisibleSignDesigner(pdfPath, image, 1);
visibleSig.xAxis(660).yAxis(480).zoom(-50).signatureFieldName("signature");
visibleSig.height(37);
visibleSig.width(70);
//visibleSig.imageSizeInPercents(50);
PDVisibleSigProperties signatureProperties = new PDVisibleSigProperties();
signatureProperties.signerName("XXXXXXX").signerLocation("chennai").signatureReason("Security").preferredSize(0)
.page(1).visualSignEnabled(true).setPdVisibleSignature(visibleSig).buildSignature();
signatureProperties.setPdVisibleSignature(visibleSig);
signing.signPDF(document, signatureProperties);
}
}
And most of the methods are deprecated which are used to verify the owner password ,user password and etc.

Even the password you used is a correct one , when the PDF is Password protected it has some securities added to it. So you need to remove those securites.
In your openPDFDoc(File pdfFile) method
Add these lines to your method
if (isOriginalDocEncrypted)
{
originialPdfDoc.openProtection(new StandardDecryptionMaterial("123456"));
**originialPdfDoc.setAllSecurityToBeRemoved(true);**
}
This will remove the securities set to the PDF
Now you can do the job.

Related

Sign PDF with HSM [duplicate]

I am doing a project where i need to sign a pdf using a usb based digital signature. I have tried the following code locally and able to sign the pdf. my problem is weather the following code will work in a client server based senerio.
My code is:
import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfSignatureAppearance;
import com.lowagie.text.pdf.PdfStamper;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.cert.CRL;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import javax.servlet.RequestDispatcher;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import sun.security.mscapi.SunMSCAPI;
public class Testing {
private static boolean resFlag;
public static void main (String args[])
{
try {
BouncyCastleProvider providerBC = new BouncyCastleProvider();
Security.addProvider(providerBC);
SunMSCAPI providerMSCAPI = new SunMSCAPI();
Security.addProvider(providerMSCAPI);
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);
// //String e = request.getParameter("digiFile");
// KeyStore ks = KeyStore.getInstance("pkcs12");
// String f10 = CommonUtil.getRealPath();
// String str8 = f10 + "/DigiFiles/";
// //System.out.println("str8-->>>>>>>>" + str8 + e);
// ks.load(new FileInputStream("F:/DigiFiles/Anurag Goel.pfx"), "123".toCharArray());
//
//
// System.out.println("The actual path is " + str8);
// String alias = (String)ks.aliases().nextElement();
// PrivateKey key = (PrivateKey)ks.getKey(alias, "123".toCharArray());
// Certificate[] chain = ks.getCertificateChain(alias);
PdfReader reader = new PdfReader("F:/test.pdf");
FileOutputStream os = new FileOutputStream("F:/SampleOutPut61.pdf");
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0',null,true);
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setCrypto(pk, chain, (CRL[])null, PdfSignatureAppearance.VERISIGN_SIGNED);
appearance.setReason("elicense project");
appearance.setLocation("Assam");
appearance.setVisibleSignature("hi");
stamper.close();
} catch (KeyStoreException var27) {
var27.printStackTrace();
resFlag = false;
} catch (NoSuchAlgorithmException var28) {
var28.printStackTrace();
resFlag = false;
} catch (CertificateException var29) {
var29.printStackTrace();
resFlag = false;
} catch (FileNotFoundException var30) {
var30.printStackTrace();
resFlag = false;
} catch (IOException var31) {
var31.printStackTrace();
resFlag = false;
} catch (UnrecoverableKeyException var32) {
var32.printStackTrace();
resFlag = false;
} catch (DocumentException var33) {
var33.printStackTrace();
resFlag = false;
} catch (Exception var34) {
var34.printStackTrace();
resFlag = false;
} finally {
RequestDispatcher rd;
}
}
}
Please give me suggestion . thanks all
You are using the wrong iText version, hence you are creating signatures that are not future proof (please read this book to find out what's wrong with your code).
You are depending on the fact that the operating system is Windows. Is your server also a Windows server? Your code won't work if it's a Linux server. Check with your hosting provider and also ask your hosting provider if it is allowed for you to have a USB token on that server (if it's not a dedicated server, chances are they are going to refuse that).
You are using Windows-MY which means that you delegate the authentication to the operating system. If the USB needs a passphrase (they usually do), Windows will open up a dialog box for you to fill out that passphrase. If you deploy this on a server: will you have somebody sitting next to that server to fill out that password every time somebody requests a signature?
USB tokens are designed for people to sign a document manually. They usually have specific limitations. For instance: normally, you can not apply more than 1 signature per second. This is usually insufficient in a web context. In a web context, you are expected to use install a Hardware Security Module (HSM) on your server.
While your code may work on a server in theory, I see a lot of reasons why it's not a wise decision to use the code that works on a standalone machine in a client/server environment. There are too many practical issues (such as authentication, speed, wrong version of iText,...) that can make your project go wrong. I would answer "no" to your question whether that code will work in a client/server scenario.
Update:
In your comments to my answer, you indicate that your server is a Linux server. It should be obvious that using "Windows-MY" will never work on a Linux server. You'll have to use PKCS#11 instead of Windows-MY to talk to the hardware device on which your token is stored. This is a code sample that works on a Luna SA from SafeNet. As you can see, it uses PKCS#11:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import sun.security.pkcs11.SunPKCS11;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.log.LoggerFactory;
import com.itextpdf.text.log.SysoLogger;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.CertificateUtil;
import com.itextpdf.text.pdf.security.CrlClient;
import com.itextpdf.text.pdf.security.CrlClientOnline;
import com.itextpdf.text.pdf.security.DigestAlgorithms;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.ExternalSignature;
import com.itextpdf.text.pdf.security.MakeSignature;
import com.itextpdf.text.pdf.security.OcspClient;
import com.itextpdf.text.pdf.security.OcspClientBouncyCastle;
import com.itextpdf.text.pdf.security.PrivateKeySignature;
import com.itextpdf.text.pdf.security.TSAClient;
import com.itextpdf.text.pdf.security.TSAClientBouncyCastle;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
public class C4_01_SignWithPKCS11HSM {
public static final String SRC = "/home/itext/hello.pdf";
public static final String PROPS = "/home/itext/key.properties";
public static final String DEST = "/home/itext/hello_hsm.pdf";
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(36, 748, 144, 780), 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);
}
public static void main(String[] args) throws IOException, GeneralSecurityException, DocumentException {
LoggerFactory.getInstance().setLogger(new SysoLogger());
Properties properties = new Properties();
properties.load(new FileInputStream(PROPS));
char[] pass = properties.getProperty("PASSWORD").toCharArray();
String pkcs11cfg = properties.getProperty("PKCS11CFG");
BouncyCastleProvider providerBC = new BouncyCastleProvider();
Security.addProvider(providerBC);
FileInputStream fis = new FileInputStream(pkcs11cfg);
Provider providerPKCS11 = new SunPKCS11(fis);
Security.addProvider(providerPKCS11);
KeyStore ks = KeyStore.getInstance("PKCS11");
ks.load(null, pass);
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey)ks.getKey(alias, pass);
Certificate[] chain = ks.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));
C4_01_SignWithPKCS11HSM app = new C4_01_SignWithPKCS11HSM();
app.sign(SRC, DEST, chain, pk, DigestAlgorithms.SHA256, providerPKCS11.getName(), CryptoStandard.CMS,
"HSM test", "Ghent", crlList, ocspClient, tsaClient, 0);
}
}
The content of the config file that is used looks like this:
Name = Luna
library = /usr/lunasa/lib/libCryptoki2_64.so
slot = 1
Note that the so may be in another directory in your case, and your certificate may be in another slot. I also use a properties file to store the password for the certificate. Obviously I won't share my password ;-)
This example was tested on a server owned by GlobalSign using a GlobalSign certificate.

Apache FOP the method newInstance(FopFactoryConfig) in the type FopFactory is not applicable for the arguments ()

I am getting the following error:
Exception in thread "main" java.lang.Error: Unresolved compilation problem: The method newInstance(FopFactoryConfig) in the type FopFactory is not applicable for the arguments ()
at fopdemo.fopvass.PDFHandler.createPDFFile(PDFHandler.java:42)
at fopdemo.fopvass.TestPDF.main(TestPDF.java:40)
This is my code:
package fopdemo.fopvass;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.MimeConstants;
public class PDFHandler {
public static final String EXTENSION = ".pdf";
public String PRESCRIPTION_URL = "template.xsl";
public String createPDFFile(ByteArrayOutputStream xmlSource, String templateFilePath) throws IOException {
File file = File.createTempFile("" + System.currentTimeMillis(), EXTENSION);
URL url = new File(templateFilePath + PRESCRIPTION_URL).toURI().toURL();
// creation of transform source
StreamSource transformSource = new StreamSource(url.openStream());
// create an instance of fop factory
FopFactory fopFactory = FopFactory.newInstance();
// a user agent is needed for transformation
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
// to store output
ByteArrayOutputStream pdfoutStream = new ByteArrayOutputStream();
StreamSource source = new StreamSource(new ByteArrayInputStream(xmlSource.toByteArray()));
Transformer xslfoTransformer;
try {
TransformerFactory transfact = TransformerFactory.newInstance();
xslfoTransformer = transfact.newTransformer(transformSource);
// Construct fop with desired output format
Fop fop;
try {
fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, pdfoutStream);
// Resulting SAX events (the generated FO)
// must be piped through to FOP
Result res = new SAXResult(fop.getDefaultHandler());
// Start XSLT transformation and FOP processing
try {
// everything will happen here..
xslfoTransformer.transform(source, res);
// if you want to save PDF file use the following code
OutputStream out = new java.io.FileOutputStream(file);
out = new java.io.BufferedOutputStream(out);
FileOutputStream str = new FileOutputStream(file);
str.write(pdfoutStream.toByteArray());
str.close();
out.close();
} catch (TransformerException e) {
e.printStackTrace();
}
} catch (FOPException e) {
e.printStackTrace();
}
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerFactoryConfigurationError e) {
e.printStackTrace();
}
return file.getPath();
}
public ByteArrayOutputStream getXMLSource(EmployeeData data) throws Exception {
JAXBContext context;
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
try {
context = JAXBContext.newInstance(EmployeeData.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal(data, System.out);
m.marshal(data, outStream);
} catch (JAXBException e) {
e.printStackTrace();
}
return outStream;
}
}
This is where it is called:
package fopdemo.fopvass;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
/**
* #author Debasmita.Sahoo
*
*/
public class TestPDF {
public static void main(String args[]){
System.out.println("Hi Testing");
ArrayList employeeList = new ArrayList();
String templateFilePath ="C:/Paula/Proyectos/fop/fopvass/resources/";
Employee e1= new Employee();
e1.setName("Debasmita1 Sahoo");
e1.setEmployeeId("10001");
e1.setAddress("Pune");
employeeList.add(e1);
Employee e2= new Employee();
e2.setName("Debasmita2 Sahoo");
e2.setEmployeeId("10002");
e2.setAddress("Test");
employeeList.add(e2);
Employee e3= new Employee();
e3.setName("Debasmita3 Sahoo");
e3.setEmployeeId("10003");
e3.setAddress("Mumbai");
employeeList.add(e3);
EmployeeData data = new EmployeeData();
data.setEemployeeList(employeeList);
PDFHandler handler = new PDFHandler();
try {
ByteArrayOutputStream streamSource = handler.getXMLSource(data);
handler.createPDFFile(streamSource,templateFilePath);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The following line won't compile:
FopFactory fopFactory = FopFactory.newInstance();
The method newInstance() requires a parameter. From the documentation (provided by Mathias Muller), under 'Basic Usage', that parameter refers to a configuration file:
FopFactory fopFactory = FopFactory.newInstance(
new File( "C:/Temp/fop.xconf" ) );
You need to provide it a File object. Alternatively, it is also possible to create a FopFactory instance by providing a URI to resolve relative URIs in the input file (because SVG files reference other SVG files). As the documentation suggests:
FopFactory fopFactory = FopFactory.newInstance(
new File(".").toURI() );
The user agent is the entity that allows you to interact with a single rendering run, i.e. the processing of a single document. If you wish to customize the user agent's behaviour, the first step is to create your own instance of FOUserAgent using the appropriate factory method on FopFactory and pass that to the factory method that will create a new Fop instance.
FopFactory.newInstance() support
FopFactory.newInstance(File)
FopFactory.newInstance(Uri)
FopFactory.newInstance(Uri, InputStream)
FopFactory.newInstance(FopFactoryConfig)
I successfully implemented on Windows and Mac OS (i.e. a Unix\Linux like NFS) the following code
URI uri = new File(config.getRoot()).toPath().toUri();
FopFactory fopFactory = FopFactory.newInstance(uri);
On the other hand, this does not work (and I don't understand why)
URI uri = new File(config.getRoot()).toUri();

pdfbox sign pdf PKCS12 invalid signature bouncycastle

Already tested with various versions of PDFBox keeps giving the same error, generates a signature invalid in pdf reader adobe and does not show the certificate , I am using Java Jdk jdk1.8.0_40 , PDFBox -app- 2.0.0-20150529.000527-1365.jar the code is as follows (mycert22.p12 is sha256withrsa 2048bit key):
(pdf shows : signature invalid , there are mistakes in formatting or the information contained in this signature to didentidade the subscriber was not verified )
and not to see the certificate details what 'll be happening?
JAVA:
package ca_c4_sign_v2;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.List;
import org.apache.pdfbox.exceptions.COSVisitorException;
import org.apache.pdfbox.exceptions.SignatureException;
import org.apache.pdfbox.io.RandomAccessFile;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureInterface;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.CMSProcessable;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.CMSSignedGenerator;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class CA_c4_sign_v2 implements SignatureInterface{
private static BouncyCastleProvider provider = new BouncyCastleProvider();
private PrivateKey privKey;
private Certificate[] cert;
private SignatureOptions options;
/**
* Initialize the signature creator with a keystore (pkcs12) and pin that
* should be used for the signature.
*
* #param keystore
* is a pkcs12 keystore.
* #param pin
* is the pin for the keystore / private key
*/
public CA_c4_sign_v2(KeyStore keystore, char[] pin)
{
try
{
/*
* grabs the first alias from the keystore and get the private key. An
* alternative method or constructor could be used for setting a specific
* alias that should be used.
*/
Enumeration<String> aliases = keystore.aliases();
String alias = null;
if (aliases.hasMoreElements())
{
alias = aliases.nextElement();
}
else
{
throw new RuntimeException("Could not find alias");
}
privKey = (PrivateKey) keystore.getKey(alias, pin);
cert = keystore.getCertificateChain(alias);
System.out.println("alias: " + alias + "\n" + "cert: " + cert + "\n");
}
catch (KeyStoreException e)
{
e.printStackTrace();
}
catch (UnrecoverableKeyException e)
{
System.err.println("Could not extract private key.");
e.printStackTrace();
}
catch (NoSuchAlgorithmException e)
{
System.err.println("Unknown algorithm.");
e.printStackTrace();
}
}
/**
* Signs the given pdf file.
*
* #param document is the pdf document
* #return the signed pdf document
* #throws IOException
* #throws COSVisitorException
* #throws SignatureException
*/
public File signPDF(File document) throws IOException, COSVisitorException,
SignatureException
{
byte[] buffer = new byte[8 * 1024];
if (document == null || !document.exists())
{
new RuntimeException("Documento nao existe!");
}
// creating output document and prepare the IO streams.
String name = document.getName();
String substring = name.substring(0, name.lastIndexOf("."));
File outputDocument = new File(document.getParent(), substring+"_signed.pdf");
FileInputStream fis = new FileInputStream(document);
FileOutputStream fos = new FileOutputStream(outputDocument);
int c;
while ((c = fis.read(buffer)) != -1)
{
fos.write(buffer, 0, c);
}
fis.close();
fis = new FileInputStream(outputDocument);
File scratchFile = File.createTempFile("pdfbox_scratch", ".bin");
RandomAccessFile randomAccessFile = new RandomAccessFile(scratchFile, "rw");
try
{
// load document
PDDocument doc = PDDocument.load(document, randomAccessFile);
// create signature dictionary
PDSignature signature = new PDSignature();
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE); // default filter
// subfilter for basic and PAdES Part 2 signatures
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_X509_RSA_SHA1);
signature.setName("name");
signature.setLocation("loc");
signature.setReason("reason");
// the signing date, needed for valid signature
signature.setSignDate(Calendar.getInstance());
// register signature dictionary and sign interface
if (options==null)
{
doc.addSignature(signature, this);
}
else
{
doc.addSignature(signature, this, options);
}
// write incremental (only for signing purpose)
doc.saveIncremental(fis, fos);
}
finally
{
if (randomAccessFile!= null)
{
randomAccessFile.close();
}
if (scratchFile != null && scratchFile.exists() && !scratchFile.delete())
{
scratchFile.deleteOnExit();
}
}
return outputDocument;
}
/**
* <p>
* SignatureInterface implementation.
* </p>
*
* <p>
* This method will be called from inside of the pdfbox and create the pkcs7
* signature. The given InputStream contains the bytes that are providen by
* the byte range.
* </p>
*
* <p>
* This method is for internal use only.
* </p>
*
* <p>
* Here the user should use his favorite cryptographic library and implement a
* pkcs7 signature creation.
* </p>
*/
public byte[] sign(InputStream content) throws SignatureException,
IOException
{
CMSProcessableInputStream input = new CMSProcessableInputStream(content);
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
// CertificateChain
List<Certificate> certList = Arrays.asList(cert);
CertStore certStore = null;
try
{
certStore = CertStore.getInstance("Collection",
new CollectionCertStoreParameters(certList), provider);
gen.addSigner(privKey, (X509Certificate) certList.get(0),
CMSSignedGenerator.DIGEST_SHA256);
gen.addCertificatesAndCRLs(certStore);
CMSSignedData signedData = gen.generate(input, false, provider);
return signedData.getEncoded();
}
catch (Exception e)
{
// should be handled
System.err.println("Erro ao criar a assinatura.");
e.printStackTrace();
}
throw new RuntimeException("Problem while preparing signature");
}
public static void main(String[] args) throws KeyStoreException,
NoSuchAlgorithmException, CertificateException, FileNotFoundException,
IOException, COSVisitorException, SignatureException
{
File ksFile = new File("mycert22.p12");
KeyStore keystore = KeyStore.getInstance("PKCS12", provider);
char[] pin = "mycert22".toCharArray();
keystore.load(new FileInputStream(ksFile), pin);
File document = new File("C4_p.pdf");
CA_c4_sign_v2 signing = new CA_c4_sign_v2(keystore, pin.clone());
signing.signPDF(document);
}
}
/**
* Wrap a InputStream into a CMSProcessable object for bouncy castle. It's an
* alternative to the CMSProcessableByteArray.
*
* #author Thomas Chojecki
*
*/
class CMSProcessableInputStream implements CMSProcessable
{
InputStream in;
public CMSProcessableInputStream(InputStream is)
{
in = is;
}
public Object getContent()
{
return in;
}
public void write(OutputStream out) throws IOException, CMSException
{
// read the content only one time
byte[] buffer = new byte[8 * 1024];
int read;
while ((read = in.read(buffer)) != -1)
{
out.write(buffer, 0, read);
}
in.close();
}
}

How to retrieve my public and private key from the keystore we created

My task is the following:
Retrieve my public and private key from the keystore I created.
Use these keys to encrypt a paragraph using my RSA 2048-bit public key.
Digitally sign the result using the DSA-SHA-1 signature algorithm.
Save the digital signature output on a file called output.dat.
The program below is throwing error : "java.security.InvalidKeyException: No installed provider supports this key: sun.security.provider.DSAPublicKeyImpl".
import java.security.*;
import java.security.KeyStore.*;
import java.io.*;
import java.security.PublicKey;
import java.security.PrivateKey;
import javax.crypto.Cipher;
import java.nio.charset.*;
import sun.security.provider.*;
import javax.crypto.*;
public class Code {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
try {
/* getting data for keystore */
File file = new File(System.getProperty("user.home") + File.separatorChar + ".keystore");
FileInputStream is = new FileInputStream(file);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
/*Information for certificate to be generated */
String password = "abcde";
String alias = "mykeys";
String alias1 = "skeys";
String filepath ="C:\\email.txt";
/* getting the key*/
keystore.load(is, password.toCharArray());
PrivateKey key = (PrivateKey)keystore.getKey(alias, "bemylife".toCharArray());
//PrivateKey key = cert1.getPrivateKey();
//PublicKey key1= (PrivateKey)key;
/* Get certificate of public key */
java.security.cert.Certificate cert = keystore.getCertificate(alias);
/* Here it prints the public key*/
System.out.println("Public Key:");
System.out.println(cert.getPublicKey());
/* Here it prints the private key*/
System.out.println("\nPrivate Key:");
System.out.println(key);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE,cert.getPublicKey());
String cleartextFile = "C:\\email.txt";
String ciphertextFile = "D:\\ciphertextRSA.png";
FileInputStream fis = new FileInputStream(cleartextFile);
FileOutputStream fos = new FileOutputStream(ciphertextFile);
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
byte[] block = new byte[32];
int i;
while ((i = fis.read(block)) != -1) {
cos.write(block, 0, i);
}
cos.close();
/* computing the signature*/
Signature dsa = Signature.getInstance("SHA1withDSA", "SUN");
dsa.initSign(key);
FileInputStream f = new FileInputStream(ciphertextFile);
BufferedInputStream in = new BufferedInputStream(f);
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) >= 0) {
dsa.update(buffer, 0, len);
};
in.close();
/* Here it prints the signature*/
System.out.println("Digital Signature :");
System.out.println( dsa.sign());
/* Now Exporting Certificate */
System.out.println("Exporting Certificate. ");
byte[] buffer_out = cert.getEncoded();
FileOutputStream os = new FileOutputStream(new File("d:\\signedcetificate.cer"));
os.write(buffer_out);
os.close();
/* writing signature to output.dat file */
byte[] buffer_out1 = dsa.sign();
FileOutputStream os1 = new FileOutputStream(new File("d:\\output.dat"));
os1.write(buffer_out1);
os1.close();
} catch (Exception e) {System.out.println(e);}
}
}
You have to read it from the keystore file (which probably ends in .jks) into a java.security.KeyStore object.
/**
* Reads a Java keystore from a file.
*
* #param keystoreFile
* keystore file to read
* #param password
* password for the keystore file
* #param keyStoreType
* type of keystore, e.g., JKS or PKCS12
* #return the keystore object
* #throws KeyStoreException
* if the type of KeyStore could not be created
* #throws IOException
* if the keystore could not be loaded
* #throws NoSuchAlgorithmException
* if the algorithm used to check the integrity of the keystore
* cannot be found
* #throws CertificateException
* if any of the certificates in the keystore could not be loaded
*/
public static KeyStore loadKeyStore(final File keystoreFile,
final String password, final String keyStoreType)
throws KeyStoreException, IOException, NoSuchAlgorithmException,
CertificateException {
if (null == keystoreFile) {
throw new IllegalArgumentException("Keystore url may not be null");
}
LOG.debug("Initializing key store: {}", keystoreFile.getAbsolutePath());
final URI keystoreUri = keystoreFile.toURI();
final URL keystoreUrl = keystoreUri.toURL();
final KeyStore keystore = KeyStore.getInstance(keyStoreType);
InputStream is = null;
try {
is = keystoreUrl.openStream();
keystore.load(is, null == password ? null : password.toCharArray());
LOG.debug("Loaded key store");
} finally {
if (null != is) {
is.close();
}
}
return keystore;
}
Once you have the KeyStore, you can get to the Certificate and the public and private keys.
But using that to sign text and save it in a file is more involved, and easy to do wrong. Take a look at Sign string using given Public Key and replace the getKeyPair method with one that uses the KeyStore. Something along the lines of
public static KeyPair getKeyPair(final KeyStore keystore,
final String alias, final String password) {
final Key key = (PrivateKey) keystore.getKey(alias, password.toCharArray());
final Certificate cert = keystore.getCertificate(alias);
final PublicKey publicKey = cert.getPublicKey();
return KeyPair(publicKey, (PrivateKey) key);
}
(obviously a little rougher, I didn't have a sample handy)
The problem is that a DSA key is unsuitable for RSA encryption. You need an RSA key for encryption, maybe you can switch your signature algorithm to RSA/SHA1 to avoid the need for two keys..
In Spring Boot(my example is using 2.4.x), you can use a bean for your KeyStore, like so:
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
#Configuration
public class KeyStoreConfiguration {
private static final String KEY_STORE = "keystore.p12";
private static final String KEY_STORE_TYPE = "PKCS12";
private static final String KEY_STORE_PASSWORD = "password";
#Bean
public KeyStore keyStore() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE);
keyStore.load(new ClassPathResource(KEY_STORE).getInputStream(), KEY_STORE_PASSWORD.toCharArray());
return keyStore;
}
}
and you can then retrieve the public and private key like so:
import java.security.PrivateKey;
import java.security.PublicKey;
PrivateKey privateKey = (PrivateKey) keyStore.getKey("my-alias", "my-password".toCharArray());
PublicKey publicKey = keyStore.getCertificate("my-alias").getPublicKey();
trusted.load(in, ((PBCApplication) context.getApplicationContext()).getBuildSettings().getCertificatePass());
Enumeration enumeration = trusted.aliases();
while (enumeration.hasMoreElements()) {
String alias = (String) enumeration.nextElement();
System.out.println("alias name: " + alias);
Certificate certificate = trusted.getCertificate(alias);
certificate.getPublicKey();
}
I don't have the Java code stored at the top of my brain, but some general sanity checks are:
is the public certificate you want stored where you want it? In particular, my recollection is that the certificate with the public key and the private key are stored together under a single alias, so the two alias setting you have there seems really odd. Try storing both under the same alias and referencing it in both the private and public key calls.
can you get anything else out of the certificate - for example, subject DN or issuer DN are both must-have fields in a certificate. That gives you a good proof that the certificate is being read as expected.
in almost any crypto transaction, be very careful with how you read from files and transfer your encoding methods. If you've created your File IO and pulled from it in a weird way, you can corrupt the encoding of the key material. That's a last thing to check - usually Java and JKS haven't been so bad for this, but it happens. On the same vein, be clear about the format of the file - JKS files are different from PKCS 12 files, for example.

Safari Push Notifications

I would like to implement push notifications for my website (obviously only in compatible browser as Safari 7).
I have read the Apple documentation and I have successfully created my package containing my icon.iconset, my certificate.p12, manifest.json and a website.json.
Now I would like to ask the permission to the user when I first visit the website. If he allows it, I should send the package.
Everything is pretty clear but I don't know how to go on.
How do I create my push package out of my files? How do I precisely sign it? The package should be always the same so I could sign it on my mac and upload to my server only one package.
If you have experience with this technology, please let me know :)
I have successfully create push package to ask permission on safari web push notifications using REST API in java. Also I have follow steps which provide by Apple officials on there sites.
Please follow below steps to create push package.
Create your web push notification P12 certificate from your apple account.
Create your REST API using https for pushPackage which contain icon.iconset, your certificate.p12, manifest.json and a website.json. p12 certificate must be web push notification certificate.
How to create push package:- Please refer below java code. I have create push package using java servlet. which provide 2 web service end points.
v1/pushpackage/webpushID
v1/log
Servlet which process your push package request which send by safari push notification method
SafariPushPakageAPI.java
/*
Push Package REST API handler
*/
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import com.safari.Packager;
public class SafariPushPakageAPI extends HttpServlet{
/**
*
*/
private static final long serialVersionUID = 1L;
public static String ServerPath = null;
private static final String REQUEST_PERMISSION = "/v1/pushPackages/YOUR_WEB_PUSH_ID";
private static final String REQUEST_ERRORLOG = "/v1/log";
#Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doRequest(request, response);
}
// /v1/pushPackages/webpushID
// /v1/log
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doRequest(request, response);
}
private void doRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("===>> SAFARI PUSH NOTIFICATION REQUEST");
String path = request.getPathInfo();
System.out.println("PATH ===>> "+path);
if(path == null){
doRequestPermission(request, response);
}else if (path.equalsIgnoreCase(REQUEST_PERMISSION)){
doRequestPermission(request, response);
}else if (path.equalsIgnoreCase(REQUEST_ERRORLOG)){
doRequestShowErrorLog(request, response);
}else{
doRequestPermission(request, response);
}
}
private void doRequestPermission(HttpServletRequest request,HttpServletResponse response) {
try{
System.out.println("INSIDE REQUEST PERMISSION ==>>>");
System.out.println(IOUtils.toString(request.getReader()));
String authToken = StringUtils.isBlank(request.getParameter("token")) ? "UserTokenRT124DFGH" : StringUtils.trimToEmpty(request.getParameter("token"));
System.out.println("=>>>>>>>>>> USER TOKEN =>>>>>>>>>> "+authToken);
#SuppressWarnings("deprecation")
String packagePath =request.getRealPath("pushPackage.raw/icon.iconset/"); // LOCATION WHERE YOUR PUSH PACKAGE FOLDER CONTAIN LOGOS AND website.json file
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment;filename=\"pushpackage.zip\"");
OutputStream out = response.getOutputStream();
out.write(Packager.createPackageFile(authToken,packagePath));
response.flushBuffer();
}catch(IOException ioe){
ioe.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
private void doRequestShowErrorLog(HttpServletRequest request,HttpServletResponse response) {
try{
System.out.println("ERROR LOG STARTED");
System.out.println(IOUtils.toString(request.getReader()));
System.out.println("END");
}catch(Exception e){
e.printStackTrace();
}
}
}
Packager.java
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.io.IOUtils;
import org.json.JSONArray;
import org.json.JSONObject;
/**
*
* #author Ritesh
*/
public class Packager {
final static String CERTIFICATE_PATH="PATH TO YOUR 12 CERTIFICATE";
final static String CERTIFICATE_PASS="PASSWORD";
static String getJSON(String authenticationToken) throws Exception {
JSONObject obj = new JSONObject();
obj.put("websiteName", "WEB SITE NAME");
obj.put("websitePushID", "WEB PUSH ID");
obj.put("allowedDomains", new JSONArray());
obj.getJSONArray("allowedDomains").put("https://TEST.EXAMPLE.net");//LIST OF DOMAINS ALLOW
obj.put("urlFormatString", "https://TEST.EXAMPLE.net/%#");
obj.put("authenticationToken", authenticationToken);
obj.put("webServiceURL", "https://API.EXAMPLE.COM");//callback URL WITHOUT WEB SERVICE ENDPOINT NAME
return obj.toString();
}
public static byte[] createPackageFile(String authenticationToken, String path) throws Exception {
System.out.println("packaging safari file with token: " + authenticationToken);
ZipHandler zip = new ZipHandler();
File dir = new File(path);
for (File file : dir.listFiles()) {
InputStream is = new FileInputStream(file);
byte[] bytes = IOUtils.toByteArray(is);
zip.addFile("icon.iconset", file.getName(),bytes );
}
zip.addFile("", "website.json", getJSON(authenticationToken).getBytes());
byte[] manifest = zip.manifest();
zip.addFile("", "manifest.json", manifest);
zip.addFile("", "signature", sign(manifest));
return zip.getBytes();
}
static byte[] sign(byte bytesToSign[]) throws Exception {
return new PKCS7Signer().sign(CERTIFICATE_PATH,CERTIFICATE_PASS, bytesToSign);
}
/**
* Servlet handler , should listen on the callback URL (as in webServiceURL)
* #param requestPath
* #param req
* #param servletRequest
* #param servletResponse
* #throws Exception
*/
public static void main(String[] args) throws Exception {
Packager.createPackageFile("SafriNotifcation","");
}
}
PKCS7Signer.java which create your signature file.
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaCertStore;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.CMSTypedData;
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.bouncycastle.util.Store;
public final class PKCS7Signer {
static {
try{
Security.addProvider(new BouncyCastleProvider());
}catch(Exception e){
e.printStackTrace();
}
}
private KeyStore getKeystore(String storeLocation, String storePasswd) throws Exception {
if (storeLocation == null) {
System.out.println("Could not find store file (.p12)");
return null;
}
// First load the keystore object by providing the p12 file path
KeyStore clientStore = KeyStore.getInstance("PKCS12");
// replace testPass with the p12 password/pin
clientStore.load(new FileInputStream(storeLocation), storePasswd.toCharArray());
return clientStore;
}
private X509CertificateHolder getCert(KeyStore keystore, String alias) throws Exception {
java.security.cert.Certificate c = keystore.getCertificate(alias);
return new X509CertificateHolder(c.getEncoded());
}
private PrivateKey getPrivateKey(KeyStore keystore, String alias, String storePasswd) throws Exception {
return (PrivateKey) keystore.getKey(alias, storePasswd.toCharArray());
}
public byte[] sign(String storeLocation, String storePasswd, byte[] dataToSign) throws Exception {
KeyStore clientStore = getKeystore(storeLocation, storePasswd);
if (clientStore == null) {
return null;
}
Enumeration aliases = clientStore.aliases();
String alias = "";
while (aliases.hasMoreElements()) {
alias = (String) aliases.nextElement();
if (clientStore.isKeyEntry(alias)) {
break;
}
}
CMSTypedData msg = new CMSProcessableByteArray(dataToSign); // Data to sign
X509CertificateHolder x509Certificate = getCert(clientStore, alias);
List certList = new ArrayList();
certList.add(x509Certificate); // Adding the X509 Certificate
Store certs = new JcaCertStore(certList);
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
// Initializing the the BC's Signer
ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").build(
getPrivateKey(clientStore, alias, storePasswd));
gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder()
.setProvider("BC").build()).build(sha1Signer, x509Certificate));
// adding the certificate
gen.addCertificates(certs);
// Getting the signed data
CMSSignedData sigData = gen.generate(msg, false);
return sigData.getEncoded();
}
}
please note used latest bouncy castle jars for create signature file
bcprov-jdk15on-157.jar
bcpkix-jdk15on-157.jar
Write your javascript on your client side page.it contains simple java script to get permissions.
///
// For safari
var domain="YOUR WEB PUSH ID";
function safariIniti() {
var pResult = window.safari.pushNotification.permission(domain);
if(pResult.permission === 'default') {
//request permission
requestPermissions();
} else if (pResult.permission === 'granted') {
console.log("Permission for " + domain + " is " + pResult.permission);
var token = pResult.deviceToken;
// Show subscription for debug
console.log('Subscription details:'+token);
} else if(pResult.permission === 'denied') {
console.log("Permission for " + domain + " is " + pResult.permission);
}
}
function getToken(){
// always start with a letter (for DOM friendlyness)
var idstr=String.fromCharCode(Math.floor((Math.random()*25)+65));
do {
// between numbers and characters (48 is 0 and 90 is Z (42-48 = 90)
var ascicode=Math.floor((Math.random()*42)+48);
if (ascicode<58 || ascicode>64){
// exclude all chars between : (58) and # (64)
idstr+=String.fromCharCode(ascicode);
}
} while (idstr.length<32);
return (idstr);
}
function requestPermissions() {
var tokenVal = getToken();
window.safari.pushNotification.requestPermission('WEb service url without end points',domain,{token:tokenVal},
function(subscription) {
console.log(subscription.permission);
console.log("PERMISSION ====>> "+subscription.permission);
if(subscription.permission === 'granted') {
//TODO
}
else if(subscription.permission === 'denied') {
// TODO:
}
});
}
Apple provides a php file that you can use to create your push package including the signature. https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/NotificationProgrammingGuideForWebsites/CompanionFile.zip
Alternatively, you can use the push_package gem, https://github.com/SymmetricInfinity/push_package, which we developed when implementing safari push notifications for zeropush.com. More details are available at https://zeropush.com/blog/implementing-safari-push-notifications-in-osx-mavericks.
Follow this apple documentation and github repo, they include sufficient information required to create a safari push notifications.