/* DigiDoc4J library * * This software is released under either the GNU Library General Public * License (see LICENSE.LGPL). * * Note that the only valid version of the LGPL license as far as this * project is concerned is the original GNU Library General Public License * Version 2.1, February 1999 */ package prototype.samples; import static org.digidoc4j.DigestAlgorithm.SHA256; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.PrivateKey; import java.security.cert.X509Certificate; import org.apache.commons.lang.ArrayUtils; import org.digidoc4j.Container; import org.digidoc4j.ContainerBuilder; import org.digidoc4j.DataToSign; import org.digidoc4j.DigestAlgorithm; import org.digidoc4j.Signature; import org.digidoc4j.SignatureBuilder; import org.digidoc4j.SignatureToken; import org.digidoc4j.exceptions.DigiDoc4JException; import org.digidoc4j.signers.ExternalSigner; /** * Example for asynchronous signing */ public class AsyncSigning { public static void main(String[] args) throws IOException, ClassNotFoundException { System.setProperty("digidoc4j.mode", "TEST"); Container container = ContainerBuilder. aContainer(). withDataFile("testFiles/test.txt", "text/plain"). build(); X509Certificate signerCert = getSignerCert(); DataToSign dataToSign = SignatureBuilder. aSignature(container). withSigningCertificate(signerCert). buildDataToSign(); serialize(container, "container.bin"); serialize(dataToSign, "dataToSign.bin"); //getSignature byte[] signatureValue = getExternalSignature(signerCert, dataToSign); Container deserializedContainer = deserializer("container.bin"); DataToSign deserializedDataToSign = deserializer("dataToSign.bin"); Signature signature = deserializedDataToSign.finalize(signatureValue); deserializedContainer.addSignature(signature); deserializedContainer.saveAsFile("deserializedContainer.bdoc"); //serialize container serialize(deserializedContainer, "container.bin"); serialize(deserializedDataToSign, "dataToSign.bin"); } private static byte[] getExternalSignature(X509Certificate signerCert, DataToSign dataToSign) { SignatureToken externalSigner = new ExternalSigner(signerCert) { @Override public byte[] sign(DigestAlgorithm digestAlgorithm, byte[] dataToSign) { try { KeyStore keyStore = KeyStore.getInstance("PKCS12"); try (FileInputStream stream = new FileInputStream("testFiles/signout.p12")) { keyStore.load(stream, "test".toCharArray()); } PrivateKey privateKey = (PrivateKey) keyStore.getKey("1", "test".toCharArray()); final String javaSignatureAlgorithm = "NONEwith" + privateKey.getAlgorithm(); return encrypt(javaSignatureAlgorithm, privateKey, addPadding(dataToSign)); } catch (Exception e) { throw new DigiDoc4JException("Loading private key failed"); } } private byte[] addPadding(byte[] digest) { return ArrayUtils.addAll(SHA256.digestInfoPrefix(), digest); } }; return externalSigner.sign(dataToSign.getDigestAlgorithm(), dataToSign.getDigestToSign()); } private static X509Certificate getSignerCert() { try { KeyStore keyStore = KeyStore.getInstance("PKCS12"); try (FileInputStream stream = new FileInputStream("testFiles/signout.p12")) { keyStore.load(stream, "test".toCharArray()); } return (X509Certificate) keyStore.getCertificate("1"); } catch (Exception e) { throw new DigiDoc4JException("Loading signer cert failed"); } } private static <T> void serialize(T container, String path) throws IOException { FileOutputStream fileOut = new FileOutputStream(path); ObjectOutputStream out = new ObjectOutputStream(fileOut); out.writeObject(container); out.flush(); out.close(); fileOut.close(); } private static <T> T deserializer(String path) throws IOException, ClassNotFoundException { FileInputStream fileIn = new FileInputStream(path); ObjectInputStream in = new ObjectInputStream(fileIn); T container = (T) in.readObject(); in.close(); fileIn.close(); return container; } /** * This method digest and encrypt the given {@code InputStream} with indicated private key and signature algorithm. To find the signature object * the list of registered security Providers, starting with the most preferred Provider is traversed. * * This method returns an array of bytes representing the signature value. Signature object that implements the specified signature algorithm. It traverses the list of * registered security Providers, starting with the most preferred Provider. A new Signature object encapsulating the SignatureSpi implementation from the first Provider * that supports the specified algorithm is returned. The {@code NoSuchAlgorithmException} exception is wrapped in a DSSException. * * @param javaSignatureAlgorithm signature algorithm under JAVA form. * @param privateKey private key to use * @param bytes the data to digest * @return digested and encrypted array of bytes */ @Deprecated public static byte[] encrypt(final String javaSignatureAlgorithm, final PrivateKey privateKey, final byte[] bytes) { try { java.security.Signature signature = java.security.Signature.getInstance(javaSignatureAlgorithm); signature.initSign(privateKey); signature.update(bytes); final byte[] signatureValue = signature.sign(); return signatureValue; } catch (GeneralSecurityException e) { throw new RuntimeException(e); } } }