From f94e0491f52560f6b1ee10bc0a9027292b6c119d Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Sun, 29 Oct 2023 22:18:21 +0800 Subject: [PATCH] feat: works with ecdsa --- .gitignore | 5 ++- .../hatter/tool/signpdf/CreateSignature.java | 7 ++-- .../tool/signpdf/CreateSignatureBase.java | 37 ++++++------------- .../hatter/tool/signpdf/main/SignPdfMain.java | 36 +++++------------- 4 files changed, 30 insertions(+), 55 deletions(-) diff --git a/.gitignore b/.gitignore index 94b7950..4be6fcc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +out/ +Resume*.pdf +__*.pem build classes .DS_Store @@ -7,4 +10,4 @@ classes .settings *.iml *.ipr -*.iws \ No newline at end of file +*.iws diff --git a/src/main/java/me/hatter/tool/signpdf/CreateSignature.java b/src/main/java/me/hatter/tool/signpdf/CreateSignature.java index 224c012..7ec22d0 100644 --- a/src/main/java/me/hatter/tool/signpdf/CreateSignature.java +++ b/src/main/java/me/hatter/tool/signpdf/CreateSignature.java @@ -7,10 +7,11 @@ import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature; import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions; import java.io.*; -import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; import java.security.UnrecoverableKeyException; +import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.util.Calendar; @@ -31,9 +32,9 @@ import java.util.Calendar; public class CreateSignature extends CreateSignatureBase { private final SignOptions signOptions; - public CreateSignature(SignOptions signOptions, KeyStore keystore, char[] pin) + public CreateSignature(SignOptions signOptions, Certificate[] certificateChain, PrivateKey privateKey) throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, CertificateException, IOException { - super(keystore, pin); + super(certificateChain, privateKey); this.signOptions = signOptions; } diff --git a/src/main/java/me/hatter/tool/signpdf/CreateSignatureBase.java b/src/main/java/me/hatter/tool/signpdf/CreateSignatureBase.java index d068401..bbd2688 100644 --- a/src/main/java/me/hatter/tool/signpdf/CreateSignatureBase.java +++ b/src/main/java/me/hatter/tool/signpdf/CreateSignatureBase.java @@ -18,7 +18,6 @@ import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Arrays; -import java.util.Enumeration; // https://svn.apache.org/viewvc/pdfbox/trunk/examples/src/main/java/ // org/apache/pdfbox/examples/signature/CreateSignatureBase.java?view=co @@ -28,34 +27,19 @@ public abstract class CreateSignatureBase implements SignatureInterface { private String tsaUrl; private boolean externalSigning; - public CreateSignatureBase(KeyStore keystore, char[] pin) + public CreateSignatureBase(Certificate[] certificateChain, PrivateKey privateKey) throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, IOException, CertificateException { // 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. - final Enumeration aliases = keystore.aliases(); - String alias; - Certificate cert = null; - while (aliases.hasMoreElements()) { - alias = aliases.nextElement(); - setPrivateKey((PrivateKey) keystore.getKey(alias, pin)); - final Certificate[] certChain = keystore.getCertificateChain(alias); - if (certChain == null) { - continue; - } - setCertificateChain(certChain); - cert = certChain[0]; - if (cert instanceof X509Certificate) { - // avoid expired certificate - ((X509Certificate) cert).checkValidity(); + this.privateKey = privateKey; + this.certificateChain = certificateChain; - SigUtils.checkCertificateUsage((X509Certificate) cert); - } - break; - } - - if (cert == null) { - throw new IOException("Could not find certificate"); + final Certificate cert = certificateChain[0]; + if (cert instanceof X509Certificate) { + // avoid expired certificate + ((X509Certificate) cert).checkValidity(); + SigUtils.checkCertificateUsage((X509Certificate) cert); } } @@ -82,9 +66,12 @@ public abstract class CreateSignatureBase implements SignatureInterface { final CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); final X509Certificate cert = (X509Certificate) certificateChain[0]; // TODO use customer signer - final ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256WithRSA").build(privateKey); + final String signatureAlgorithm = "SHA256WithECDSA"; +// final String signatureAlgorithm = "SHA256WithRSA"; + final ContentSigner contentSigner = new JcaContentSignerBuilder(signatureAlgorithm).build(privateKey); gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder( new JcaDigestCalculatorProviderBuilder().build()).build(contentSigner, cert)); + gen.addCertificates(new JcaCertStore(Arrays.asList(certificateChain))); final CMSProcessableInputStream msg = new CMSProcessableInputStream(content); CMSSignedData signedData = gen.generate(msg, false); diff --git a/src/main/java/me/hatter/tool/signpdf/main/SignPdfMain.java b/src/main/java/me/hatter/tool/signpdf/main/SignPdfMain.java index ede5faa..7401a5e 100644 --- a/src/main/java/me/hatter/tool/signpdf/main/SignPdfMain.java +++ b/src/main/java/me/hatter/tool/signpdf/main/SignPdfMain.java @@ -2,11 +2,11 @@ package me.hatter.tool.signpdf.main; import me.hatter.tool.signpdf.CreateSignature; import me.hatter.tool.signpdf.options.SignOptions; +import me.hatter.tools.commons.io.RFile; import me.hatter.tools.commons.security.cert.X509CertUtil; import me.hatter.tools.commons.security.key.KeyUtil; import java.io.File; -import java.security.KeyStore; import java.security.PrivateKey; import java.security.cert.X509Certificate; import java.util.List; @@ -21,34 +21,18 @@ public class SignPdfMain { final String tsaUrl = "https://hatter.ink/ca/sign_timestamp.action"; final List certs = X509CertUtil.parseX509CertificateList( - "-----BEGIN CERTIFICATE-----\n" + - "I6Syqg==\n" + - "-----END CERTIFICATE-----\n" + - "-----BEGIN CERTIFICATE-----\n" + - "O1XW8Bs24gI=\n" + - "-----END CERTIFICATE-----\n" + - "-----BEGIN CERTIFICATE-----\n" + - "UhQrqeqObukNbcGgWhwy3+PysJFky6peB6IexebbVYk=\n" + - "-----END CERTIFICATE-----"); - final PrivateKey privateKey = KeyUtil.parsePrivateKeyPEM("-----BEGIN PRIVATE KEY-----\n" + - "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCVlt5k68ngIZ3T\n" + - "xSGBfudXkCooM8/cjEefv/cI\n" + - "-----END PRIVATE KEY-----"); + RFile.from("__certs.pem").string() + ); + final PrivateKey privateKey = KeyUtil.parsePrivateKeyPEM( + RFile.from("__priv.pem").string() + ); - final X509Certificate[] chain = new X509Certificate[]{certs.get(0)}; - final KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); - keyStore.load(null); - for (X509Certificate c : certs) { - keyStore.setCertificateEntry(c.getSubjectX500Principal().getName(), c); - } - keyStore.setKeyEntry("", privateKey, new char[0], chain); + final X509Certificate[] chain = certs.toArray(new X509Certificate[0]); - System.out.println(keyStore); + final CreateSignature signing = new CreateSignature(signOptions, chain, privateKey); + // signing.setExternalSigning(true); - final CreateSignature signing = new CreateSignature(signOptions, keyStore, new char[0]); - // TODO signing.setExternalSigning(true); - - File inFile = new File("/Users/hatterjiang/07-057r7_Web_Map_Tile_Service_Standard.pdf"); + final File inFile = new File("Resume.pdf"); final String name = inFile.getName(); final String substring = name.substring(0, name.lastIndexOf('.'));