Skip to content

Commit

Permalink
Make key store types extensible conveniently
Browse files Browse the repository at this point in the history
  • Loading branch information
Vampire committed Nov 15, 2024
1 parent 6acd186 commit 5eb5d7f
Show file tree
Hide file tree
Showing 37 changed files with 1,967 additions and 1,125 deletions.
44 changes: 22 additions & 22 deletions jsign-cli/src/test/java/net/jsign/JsignCLITest.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public class JsignCLITest {
private JsignCLI cli;
private File sourceFile = new File("target/test-classes/wineyes.exe");
private File targetFile = new File("target/test-classes/wineyes-signed-with-cli.exe");

private String keystore = "keystore.jks";
private String alias = "test";
private String keypass = "password";
Expand All @@ -65,12 +65,12 @@ public class JsignCLITest {
@Before
public void setUp() throws Exception {
cli = new JsignCLI();

// remove the files signed previously
if (targetFile.exists()) {
assertTrue("Unable to remove the previously signed file", targetFile.delete());
}

assertEquals("Source file CRC32", SOURCE_FILE_CRC32, FileUtils.checksumCRC32(sourceFile));
Thread.sleep(100);
FileUtils.copyFile(sourceFile, targetFile);
Expand Down Expand Up @@ -219,7 +219,7 @@ public void testSigningMultipleFiles() throws Exception {
public void testSigningMultipleFilesWithListFile() throws Exception {
File listFile = new File("target/test-classes/files.txt");
Files.write(listFile.toPath(), Arrays.asList("# first file", '"' + targetFile.getPath() + '"', " ", "# second file", targetFile.getAbsolutePath()));

cli.execute("--name=WinEyes", "--url=http://www.steelblue.com/WinEyes", "--alg=SHA-1", "--keystore=target/test-classes/keystores/" + keystore, "--keypass=" + keypass, "@" + listFile);

assertTrue("The file " + targetFile + " wasn't changed", SOURCE_FILE_CRC32 != FileUtils.checksumCRC32(targetFile));
Expand Down Expand Up @@ -271,7 +271,7 @@ public void testSigningPowerShell() throws Exception {
File sourceFile = new File("target/test-classes/hello-world.ps1");
File targetFile = new File("target/test-classes/hello-world-signed-with-cli.ps1");
FileUtils.copyFile(sourceFile, targetFile);

cli.execute("--alg=SHA-1", "--replace", "--encoding=ISO-8859-1", "--keystore=target/test-classes/keystores/" + keystore, "--alias=" + alias, "--keypass=" + keypass, "" + targetFile);

PowerShellScript script = new PowerShellScript(targetFile);
Expand All @@ -284,7 +284,7 @@ public void testSigningPowerShellWithDefaultEncoding() throws Exception {
File sourceFile = new File("target/test-classes/hello-world.ps1");
File targetFile = new File("target/test-classes/hello-world-signed-with-cli.ps1");
FileUtils.copyFile(sourceFile, targetFile);

cli.execute("--alg=SHA-1", "--replace", "--keystore=target/test-classes/keystores/" + keystore, "--alias=" + alias, "--keypass=" + keypass, "" + targetFile);

PowerShellScript script = new PowerShellScript(targetFile);
Expand All @@ -297,7 +297,7 @@ public void testSigningMSI() throws Exception {
File sourceFile = new File("target/test-classes/minimal.msi");
File targetFile = new File("target/test-classes/minimal-signed-with-cli.msi");
FileUtils.copyFile(sourceFile, targetFile);

cli.execute("--alg=SHA-1", "--replace", "--keystore=target/test-classes/keystores/" + keystore, "--alias=" + alias, "--keypass=" + keypass, "" + targetFile);

try (MSIFile file = new MSIFile(targetFile)) {
Expand All @@ -308,7 +308,7 @@ public void testSigningMSI() throws Exception {
@Test
public void testSigningPKCS12() throws Exception {
cli.execute("--name=WinEyes", "--url=http://www.steelblue.com/WinEyes", "--alg=SHA-256", "--keystore=target/test-classes/keystores/keystore.p12", "--alias=test", "--storepass=password", "" + targetFile);

assertTrue("The file " + targetFile + " wasn't changed", SOURCE_FILE_CRC32 != FileUtils.checksumCRC32(targetFile));

try (PEFile peFile = new PEFile(targetFile)) {
Expand Down Expand Up @@ -341,7 +341,7 @@ public void testSigningJKS() throws Exception {
@Test
public void testSigningPVKSPC() throws Exception {
cli.execute("--url=http://www.steelblue.com/WinEyes", "--certfile=target/test-classes/keystores/jsign-test-certificate-full-chain.spc", "--keyfile=target/test-classes/keystores/privatekey-encrypted.pvk", "--storepass=password", "" + targetFile);

assertTrue("The file " + targetFile + " wasn't changed", SOURCE_FILE_CRC32 != FileUtils.checksumCRC32(targetFile));

try (PEFile peFile = new PEFile(targetFile)) {
Expand All @@ -352,7 +352,7 @@ public void testSigningPVKSPC() throws Exception {
@Test
public void testSigningPEM() throws Exception {
cli.execute("--certfile=target/test-classes/keystores/jsign-test-certificate.pem", "--keyfile=target/test-classes/keystores/privatekey.pkcs8.pem", "--keypass=password", "" + targetFile);

assertTrue("The file " + targetFile + " wasn't changed", SOURCE_FILE_CRC32 != FileUtils.checksumCRC32(targetFile));

try (PEFile peFile = new PEFile(targetFile)) {
Expand All @@ -363,7 +363,7 @@ public void testSigningPEM() throws Exception {
@Test
public void testSigningEncryptedPEM() throws Exception {
cli.execute("--certfile=target/test-classes/keystores/jsign-test-certificate.pem", "--keyfile=target/test-classes/keystores/privatekey-encrypted.pkcs1.pem", "--keypass=password", "" + targetFile);

assertTrue("The file " + targetFile + " wasn't changed", SOURCE_FILE_CRC32 != FileUtils.checksumCRC32(targetFile));

try (PEFile peFile = new PEFile(targetFile)) {
Expand All @@ -373,7 +373,7 @@ public void testSigningEncryptedPEM() throws Exception {

@Test
public void testSigningWithYubikey() throws Exception {
Assume.assumeTrue("No Yubikey detected", YubiKey.isPresent());
Assume.assumeTrue("No Yubikey detected", YubiKeyKeyStore.isPresent());

cli.execute("--storetype=YUBIKEY", "--certfile=target/test-classes/keystores/jsign-test-certificate-full-chain.spc", "--storepass=123456", "--alias=X.509 Certificate for Digital Signature", "" + targetFile, "" + targetFile);
}
Expand All @@ -383,7 +383,7 @@ public void testTimestampingAuthenticode() throws Exception {
File targetFile2 = new File("target/test-classes/wineyes-timestamped-with-cli-authenticode.exe");
FileUtils.copyFile(sourceFile, targetFile2);
cli.execute("--keystore=target/test-classes/keystores/" + keystore, "--alias=" + alias, "--keypass=" + keypass, "--tsaurl=http://timestamp.sectigo.com", "--tsmode=authenticode", "" + targetFile2);

assertTrue("The file " + targetFile2 + " wasn't changed", SOURCE_FILE_CRC32 != FileUtils.checksumCRC32(targetFile2));

try (PEFile peFile = new PEFile(targetFile2)) {
Expand Down Expand Up @@ -416,18 +416,18 @@ public HttpFilters filterRequest(HttpRequest originalRequest) {
}
})
.start();

try {
File targetFile2 = new File("target/test-classes/wineyes-timestamped-with-cli-rfc3161-proxy-unauthenticated.exe");
FileUtils.copyFile(sourceFile, targetFile2);
cli.execute("--keystore=target/test-classes/keystores/" + keystore, "--alias=" + alias, "--keypass=" + keypass,
"--tsaurl=http://timestamp.sectigo.com", "--tsmode=rfc3161", "--tsretries=1", "--tsretrywait=1",
"--proxyUrl=localhost:" + proxy.getListenAddress().getPort(),
"" + targetFile2);

assertTrue("The file " + targetFile2 + " wasn't changed", SOURCE_FILE_CRC32 != FileUtils.checksumCRC32(targetFile2));
assertTrue("The proxy wasn't used", proxyUsed.get());

try (PEFile peFile = new PEFile(targetFile2)) {
SignatureAssert.assertSigned(peFile, SHA256);
}
Expand Down Expand Up @@ -469,10 +469,10 @@ public String getRealm() {
"--proxyUser=jsign",
"--proxyPass=jsign",
"" + targetFile2);

assertTrue("The file " + targetFile2 + " wasn't changed", SOURCE_FILE_CRC32 != FileUtils.checksumCRC32(targetFile2));
assertTrue("The proxy wasn't used", proxyUsed.get());

try (PEFile peFile = new PEFile(targetFile2)) {
SignatureAssert.assertSigned(peFile, SHA256);
}
Expand All @@ -486,11 +486,11 @@ public void testReplaceSignature() throws Exception {
File targetFile2 = new File("target/test-classes/wineyes-re-signed.exe");
FileUtils.copyFile(sourceFile, targetFile2);
cli.execute("--keystore=target/test-classes/keystores/" + keystore, "--alias=" + alias, "--keypass=" + keypass, "" + targetFile2);

assertTrue("The file " + targetFile2 + " wasn't changed", SOURCE_FILE_CRC32 != FileUtils.checksumCRC32(targetFile2));

cli.execute("--keystore=target/test-classes/keystores/" + keystore, "--alias=" + alias, "--keypass=" + keypass, "--alg=SHA-512", "--replace", "" + targetFile2);

try (PEFile peFile = new PEFile(targetFile2)) {
SignatureAssert.assertSigned(peFile, SHA512);
}
Expand Down Expand Up @@ -526,7 +526,7 @@ public Integer getStatus() {
}

public void checkPermission(Permission perm) { }

public void checkPermission(Permission perm, Object context) { }

public void checkExit(int status) {
Expand Down
12 changes: 6 additions & 6 deletions jsign-core/src/main/java/net/jsign/SignerHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ public SignerHelper param(String key, String value) {
if (value == null) {
return this;
}

switch (key) {
case PARAM_COMMAND: return command(value);
case PARAM_KEYSTORE: return keystore(value);
Expand Down Expand Up @@ -328,7 +328,7 @@ private AuthenticodeSigner build() throws SignerException {
} catch (KeyStoreException e) {
throw new SignerException("Failed to load the keystore " + (ksparams.keystore() != null ? ksparams.keystore() : ""), e);
}
KeyStoreType storetype = ksparams.storetype();
JsignKeyStore storetype = ksparams.storetype();
Provider provider = ksparams.provider();

Set<String> aliases = null;
Expand Down Expand Up @@ -403,12 +403,12 @@ private AuthenticodeSigner build() throws SignerException {
}

// enable timestamping with Azure Trusted Signing
if (tsaurl == null && storetype == KeyStoreType.TRUSTEDSIGNING) {
if ((tsaurl == null) && (storetype instanceof AzureTrustedSigningKeyStore)) {
tsaurl = "http://timestamp.acs.microsoft.com/";
tsmode = TimestampingMode.RFC3161.name();
tsretries = 3;
}

// configure the signer
return new AuthenticodeSigner(chain, privateKey)
.withProgramName(name)
Expand All @@ -434,7 +434,7 @@ public void sign(File file) throws SignerException {
if (!file.exists()) {
throw new SignerException("The file " + file + " couldn't be found");
}

try (Signable signable = Signable.of(file, encoding)) {
File detachedSignature = getDetachedSignature(file);
if (detached && detachedSignature.exists()) {
Expand Down Expand Up @@ -638,7 +638,7 @@ private void timestamp(File file) throws SignerException {
SignerId signerId = signerInformation.getSID();
X509CertificateHolder certificate = (X509CertificateHolder) signature.getCertificates().getMatches(signerId).iterator().next();

String digestAlgorithmName = new DefaultAlgorithmNameFinder().getAlgorithmName(signerInformation.getDigestAlgorithmID());
String digestAlgorithmName = new DefaultAlgorithmNameFinder().getAlgorithmName(signerInformation.getDigestAlgorithmID());
String keyAlgorithmName = new DefaultAlgorithmNameFinder().getAlgorithmName(new ASN1ObjectIdentifier(signerInformation.getEncryptionAlgOID()));
String name = digestAlgorithmName + "/" + keyAlgorithmName + " signature from '" + certificate.getSubject() + "'";

Expand Down
34 changes: 17 additions & 17 deletions jsign-core/src/test/java/net/jsign/PESignerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ private KeyStore getKeyStore() throws Exception {
public void testSign() throws Exception {
File sourceFile = new File("target/test-classes/wineyes.exe");
File targetFile = new File("target/test-classes/wineyes-signed.exe");

FileUtils.copyFile(sourceFile, targetFile);

PESigner signer = new PESigner(getKeyStore(), ALIAS, PRIVATE_KEY_PASSWORD)
Expand Down Expand Up @@ -96,7 +96,7 @@ public void testSignWithUnknownKeyStoreEntry() {
public void testSigningWithKeyAndChain() throws Exception {
File sourceFile = new File("target/test-classes/wineyes.exe");
File targetFile = new File("target/test-classes/wineyes-signed-key-chain.exe");

FileUtils.copyFile(sourceFile, targetFile);

Certificate[] chain;
Expand Down Expand Up @@ -132,7 +132,7 @@ public void testSigningWithKeyAndChain() throws Exception {

@Test
public void testSigningWithYubikey() throws Exception {
Assume.assumeTrue("No Yubikey detected", YubiKey.isPresent());
Assume.assumeTrue("No Yubikey detected", YubiKeyKeyStore.isPresent());

File sourceFile = new File("target/test-classes/wineyes.exe");
File targetFile = new File("target/test-classes/wineyes-signed-yubikey.exe");
Expand Down Expand Up @@ -166,7 +166,7 @@ public void testNullChain() throws Exception {
public void testSigningWithMismatchingKeyAndCertificate() throws Exception {
File sourceFile = new File("target/test-classes/wineyes.exe");
File targetFile = new File("target/test-classes/wineyes-signed-mismatching-key-certificate.exe");

FileUtils.copyFile(sourceFile, targetFile);

Certificate[] chain;
Expand Down Expand Up @@ -202,7 +202,7 @@ public void testTimestampRFC3161() throws Exception {
public void testTimestamp(TimestampingMode mode, DigestAlgorithm alg) throws Exception {
File sourceFile = new File("target/test-classes/wineyes.exe");
File targetFile = new File("target/test-classes/wineyes-timestamped-" + mode.name().toLowerCase() + ".exe");

FileUtils.copyFile(sourceFile, targetFile);

PESigner signer = new PESigner(getKeyStore(), ALIAS, PRIVATE_KEY_PASSWORD);
Expand Down Expand Up @@ -234,7 +234,7 @@ public void testWithTimestamper() throws Exception {
signer.withDigestAlgorithm(SHA1);
signer.withTimestamping(true);
signer.withTimestamper(new AuthenticodeTimestamper() {

@Override
protected CMSSignedData timestamp(DigestAlgorithm algo, byte[] encryptedDigest) throws IOException, TimestampingException {
called.add(true);
Expand All @@ -257,7 +257,7 @@ protected CMSSignedData timestamp(DigestAlgorithm algo, byte[] encryptedDigest)
public void testSignTwice() throws Exception {
File sourceFile = new File("target/test-classes/wineyes.exe");
File targetFile = new File("target/test-classes/wineyes-signed-twice.exe");

FileUtils.copyFile(sourceFile, targetFile);

try (PEFile peFile = new PEFile(targetFile)) {
Expand Down Expand Up @@ -286,7 +286,7 @@ public void testSignTwice() throws Exception {
public void testSignThreeTimes() throws Exception {
File sourceFile = new File("target/test-classes/wineyes.exe");
File targetFile = new File("target/test-classes/wineyes-signed-three-times.exe");

FileUtils.copyFile(sourceFile, targetFile);

try (PEFile peFile = new PEFile(targetFile)) {
Expand Down Expand Up @@ -323,7 +323,7 @@ public void testSignThreeTimes() throws Exception {
public void testReplaceSignature() throws Exception {
File sourceFile = new File("target/test-classes/wineyes.exe");
File targetFile = new File("target/test-classes/wineyes-re-signed.exe");

FileUtils.copyFile(sourceFile, targetFile);

try (PEFile peFile = new PEFile(targetFile)) {
Expand Down Expand Up @@ -359,16 +359,16 @@ public void testInvalidRFC3161TimestampingAuthority() throws Exception {
public void testInvalidTimestampingAuthority(TimestampingMode mode) throws Exception {
File sourceFile = new File("target/test-classes/wineyes.exe");
File targetFile = new File("target/test-classes/wineyes-timestamped-unavailable-" + mode.name().toLowerCase() + ".exe");

FileUtils.copyFile(sourceFile, targetFile);

PESigner signer = new PESigner(getKeyStore(), ALIAS, PRIVATE_KEY_PASSWORD);
signer.withDigestAlgorithm(SHA1);
signer.withTimestamping(true);
signer.withTimestampingMode(mode);
signer.withTimestampingAuthority("http://www.google.com/" + mode.name().toLowerCase());
signer.withTimestampingRetries(1);

try (PEFile peFile = new PEFile(targetFile)) {
Exception e = assertThrows(TimestampingException.class, () -> signer.sign(peFile));
assertTrue("Missing suppressed IOException", e.getSuppressed() != null && e.getSuppressed().length > 0 && e.getSuppressed()[0].getClass().equals(IOException.class));
Expand All @@ -390,16 +390,16 @@ public void testBrokenRFC3161TimestampingAuthority() throws Exception {
public void testBrokenTimestampingAuthority(TimestampingMode mode) throws Exception {
File sourceFile = new File("target/test-classes/wineyes.exe");
File targetFile = new File("target/test-classes/wineyes-timestamped-broken-" + mode.name().toLowerCase() + ".exe");

FileUtils.copyFile(sourceFile, targetFile);

PESigner signer = new PESigner(getKeyStore(), ALIAS, PRIVATE_KEY_PASSWORD);
signer.withDigestAlgorithm(SHA1);
signer.withTimestamping(true);
signer.withTimestampingMode(mode);
signer.withTimestampingAuthority("http://github.com");
signer.withTimestampingRetries(1);

try (PEFile peFile = new PEFile(targetFile)) {
assertThrows(TimestampingException.class, () -> signer.sign(peFile));
}
Expand Down Expand Up @@ -434,7 +434,7 @@ public void testRFC3161TimestampingFailover() throws Exception {
public void testTimestampingFailover(TimestampingMode mode, String validURL) throws Exception {
File sourceFile = new File("target/test-classes/wineyes.exe");
File targetFile = new File("target/test-classes/wineyes-timestamped-failover-" + mode.name().toLowerCase() + ".exe");

FileUtils.copyFile(sourceFile, targetFile);

PESigner signer = new PESigner(getKeyStore(), ALIAS, PRIVATE_KEY_PASSWORD);
Expand Down Expand Up @@ -490,7 +490,7 @@ public void testWithSignatureAlgorithmSHA1withRSA() throws Exception {
@Test
public void testWithSignatureAlgorithmSHA256withRSAandMGF1() throws Exception {
Security.addProvider(new BouncyCastleProvider());

File sourceFile = new File("target/test-classes/wineyes.exe");
File targetFile = new File("target/test-classes/wineyes-signed.exe");

Expand Down
Loading

0 comments on commit 5eb5d7f

Please sign in to comment.