feat: works with ecdsa
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,3 +1,6 @@
|
|||||||
|
out/
|
||||||
|
Resume*.pdf
|
||||||
|
__*.pem
|
||||||
build
|
build
|
||||||
classes
|
classes
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|||||||
@@ -7,10 +7,11 @@ import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
|
|||||||
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions;
|
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.security.KeyStore;
|
|
||||||
import java.security.KeyStoreException;
|
import java.security.KeyStoreException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.PrivateKey;
|
||||||
import java.security.UnrecoverableKeyException;
|
import java.security.UnrecoverableKeyException;
|
||||||
|
import java.security.cert.Certificate;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
|
||||||
@@ -31,9 +32,9 @@ import java.util.Calendar;
|
|||||||
public class CreateSignature extends CreateSignatureBase {
|
public class CreateSignature extends CreateSignatureBase {
|
||||||
private final SignOptions signOptions;
|
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 {
|
throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, CertificateException, IOException {
|
||||||
super(keystore, pin);
|
super(certificateChain, privateKey);
|
||||||
this.signOptions = signOptions;
|
this.signOptions = signOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import java.security.cert.Certificate;
|
|||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Enumeration;
|
|
||||||
|
|
||||||
// https://svn.apache.org/viewvc/pdfbox/trunk/examples/src/main/java/
|
// https://svn.apache.org/viewvc/pdfbox/trunk/examples/src/main/java/
|
||||||
// org/apache/pdfbox/examples/signature/CreateSignatureBase.java?view=co
|
// org/apache/pdfbox/examples/signature/CreateSignatureBase.java?view=co
|
||||||
@@ -28,34 +27,19 @@ public abstract class CreateSignatureBase implements SignatureInterface {
|
|||||||
private String tsaUrl;
|
private String tsaUrl;
|
||||||
private boolean externalSigning;
|
private boolean externalSigning;
|
||||||
|
|
||||||
public CreateSignatureBase(KeyStore keystore, char[] pin)
|
public CreateSignatureBase(Certificate[] certificateChain, PrivateKey privateKey)
|
||||||
throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, IOException, CertificateException {
|
throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, IOException, CertificateException {
|
||||||
// grabs the first alias from the keystore and get the private key. An
|
// grabs the first alias from the keystore and get the private key. An
|
||||||
// alternative method or constructor could be used for setting a specific
|
// alternative method or constructor could be used for setting a specific
|
||||||
// alias that should be used.
|
// alias that should be used.
|
||||||
final Enumeration<String> aliases = keystore.aliases();
|
this.privateKey = privateKey;
|
||||||
String alias;
|
this.certificateChain = certificateChain;
|
||||||
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();
|
|
||||||
|
|
||||||
SigUtils.checkCertificateUsage((X509Certificate) cert);
|
final Certificate cert = certificateChain[0];
|
||||||
}
|
if (cert instanceof X509Certificate) {
|
||||||
break;
|
// avoid expired certificate
|
||||||
}
|
((X509Certificate) cert).checkValidity();
|
||||||
|
SigUtils.checkCertificateUsage((X509Certificate) cert);
|
||||||
if (cert == null) {
|
|
||||||
throw new IOException("Could not find certificate");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,9 +66,12 @@ public abstract class CreateSignatureBase implements SignatureInterface {
|
|||||||
final CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
|
final CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
|
||||||
final X509Certificate cert = (X509Certificate) certificateChain[0];
|
final X509Certificate cert = (X509Certificate) certificateChain[0];
|
||||||
// TODO use customer signer
|
// 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(
|
gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(
|
||||||
new JcaDigestCalculatorProviderBuilder().build()).build(contentSigner, cert));
|
new JcaDigestCalculatorProviderBuilder().build()).build(contentSigner, cert));
|
||||||
|
|
||||||
gen.addCertificates(new JcaCertStore(Arrays.asList(certificateChain)));
|
gen.addCertificates(new JcaCertStore(Arrays.asList(certificateChain)));
|
||||||
final CMSProcessableInputStream msg = new CMSProcessableInputStream(content);
|
final CMSProcessableInputStream msg = new CMSProcessableInputStream(content);
|
||||||
CMSSignedData signedData = gen.generate(msg, false);
|
CMSSignedData signedData = gen.generate(msg, false);
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ package me.hatter.tool.signpdf.main;
|
|||||||
|
|
||||||
import me.hatter.tool.signpdf.CreateSignature;
|
import me.hatter.tool.signpdf.CreateSignature;
|
||||||
import me.hatter.tool.signpdf.options.SignOptions;
|
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.cert.X509CertUtil;
|
||||||
import me.hatter.tools.commons.security.key.KeyUtil;
|
import me.hatter.tools.commons.security.key.KeyUtil;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.security.KeyStore;
|
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -21,34 +21,18 @@ public class SignPdfMain {
|
|||||||
final String tsaUrl = "https://hatter.ink/ca/sign_timestamp.action";
|
final String tsaUrl = "https://hatter.ink/ca/sign_timestamp.action";
|
||||||
|
|
||||||
final List<X509Certificate> certs = X509CertUtil.parseX509CertificateList(
|
final List<X509Certificate> certs = X509CertUtil.parseX509CertificateList(
|
||||||
"-----BEGIN CERTIFICATE-----\n" +
|
RFile.from("__certs.pem").string()
|
||||||
"I6Syqg==\n" +
|
);
|
||||||
"-----END CERTIFICATE-----\n" +
|
final PrivateKey privateKey = KeyUtil.parsePrivateKeyPEM(
|
||||||
"-----BEGIN CERTIFICATE-----\n" +
|
RFile.from("__priv.pem").string()
|
||||||
"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-----");
|
|
||||||
|
|
||||||
final X509Certificate[] chain = new X509Certificate[]{certs.get(0)};
|
final X509Certificate[] chain = certs.toArray(new X509Certificate[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);
|
|
||||||
|
|
||||||
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]);
|
final File inFile = new File("Resume.pdf");
|
||||||
// TODO signing.setExternalSigning(true);
|
|
||||||
|
|
||||||
File inFile = new File("/Users/hatterjiang/07-057r7_Web_Map_Tile_Service_Standard.pdf");
|
|
||||||
final String name = inFile.getName();
|
final String name = inFile.getName();
|
||||||
final String substring = name.substring(0, name.lastIndexOf('.'));
|
final String substring = name.substring(0, name.lastIndexOf('.'));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user