[Refactor] Use GPG instead of using legacy java keystores

This commit is contained in:
2024-04-06 22:31:14 +02:00
parent 4ac1450cce
commit 0b344e20b6
9 changed files with 376 additions and 146 deletions

View File

@@ -32,6 +32,10 @@ dependencies {
implementation gradleApi() implementation gradleApi()
shadeMe "org.apache.commons:commons-lang3:${commons_lang}" shadeMe "org.apache.commons:commons-lang3:${commons_lang}"
shadeMe "org.bouncycastle:bcprov-jdk18on:${bouncy}"
shadeMe "org.bouncycastle:bcpg-jdk18on:${bouncy}"
shadeMe "commons-io:commons-io:${commons_io}"
shadeMe "commons-codec:commons-codec:${commons_codec}"
compileOnly "org.projectlombok:lombok:${lombok}" compileOnly "org.projectlombok:lombok:${lombok}"
annotationProcessor "org.projectlombok:lombok:${lombok}" annotationProcessor "org.projectlombok:lombok:${lombok}"

View File

@@ -4,4 +4,7 @@ version_patch=0
# Dependencies # Dependencies
lombok=1.18.30 lombok=1.18.30
commons_lang=3.14.0 commons_lang=3.14.0
commons_io=2.16.0
commons_codec=1.16.1
bouncy=1.77

View File

@@ -6,12 +6,19 @@ A Simple Gradle plugin to help you sign your jars.
### Getting Started ### Getting Started
To get started, you will need keystore. If you already have this, you can skip this part. To get started, you will a GPG key. If you already have this, you can skip it.
In a terminal, or in command line, run the following command: In a terminal, or in command line, run the following commands:
```bash ```bash
keytool -genkey -alias YOUR_ALIAS_HERE -keyalg RSA -keysize 2048 -keystore keystore.jks # generate the keys
gpg --gen-key
#export the private key with the specified id to a file
gpg --output {private key file name and path} --armor --export-secret-keys {key-id}
#export the public key with the specified id to a file
gpg --output {public key file name and path} --armor --export {key-id}
``` ```
Answer the required questions, and your file will be generated once completed. Answer the required questions, and your file will be generated once completed.
@@ -53,39 +60,35 @@ Finally, add the following to `build.gradle` file:
```groovy ```groovy
import dev.firstdark.keymaster.tasks.SignJarTask import dev.firstdark.keymaster.tasks.SignJarTask
// This is optional. These values can be configured on the task
keymaster {
// GPG Password
gpgPassword = "123456"
// GPG Key file, or String.
gpgKey = System.getenv("GPG_KEY")
// Generate a .sig file for signed jars, to be used for verification
generateSignature = true
}
// Register a custom task to sign your jar // Register a custom task to sign your jar
tasks.register('signJar', SignJarTask) { tasks.register('signJar', SignJarTask) {
// Depend on the task used to build your project // Depend on the task used to build your project
dependsOn jar dependsOn jar
// The input artifact. This can be a Task, File or File Name // The input artifact. This can be a Task, File or File Name
artifactInput = jar artifactInput = jar
// Optional. Set the output name of the signed jar. This defaults to the artifactInput file name, and will overwrite it // Optional. Set the output name of the signed jar. This defaults to the artifactInput file name, and will overwrite it
outputFileName = "testsign" outputFileName = "testsign"
// The password of your key // GPG Private key file or string. Not required when the extension is used
keyPass = "123456" gpgKey = System.getenv("GPG_KEY")
// Your key alias
keyStoreAlias = "testalias"
// Your keystore password
keyStorePass = "123456"
// Your keystore location
keyStore = "/home/hypherionsa/dummystore.jks"
}
// Example of signing another jar // GPG Private Key password. Not required when extension is used
tasks.register('signDummyJar', SignJarTask) { gpgPassword = "123456"
dependsOn createDummyJar
artifactInput = createDummyJar
keyPass = "123456" // Should the task generate a .sig file. Defaults to true, and not required when extension is used
keyStoreAlias = "testalias" generateSignature = false
keyStorePass = "123456"
keyStore = "/home/hypherionsa/dummystore.jks"
} }
``` ```
@@ -126,8 +129,18 @@ Finally, add the following to `build.gradle.kts` file:
import dev.firstdark.keymaster.tasks.SignJarTask import dev.firstdark.keymaster.tasks.SignJarTask
import org.gradle.kotlin.dsl.register import org.gradle.kotlin.dsl.register
// This is optional. These values can be configured on the task
extensions.configure<KeymasterExtension>("keymaster") {
// GPG Password
gpgPassword = "123456"
// GPG Key file, or String.
gpgKey = System.getenv("GPG_KEY")
// Generate a .sig file for signed jars, to be used for verification
generateSignature = true
}
// Register a custom task to sign your jar // Register a custom task to sign your jar
val signJar by tasks.register<SignJarTask>("signJar") { tasks.register("signJar", SignJarTask::class) {
// Depend on the task used to build your project // Depend on the task used to build your project
dependsOn(tasks.jar) dependsOn(tasks.jar)
@@ -137,28 +150,14 @@ val signJar by tasks.register<SignJarTask>("signJar") {
// Optional. Set the output name of the signed jar. This defaults to the artifactInput file name, and will overwrite it // Optional. Set the output name of the signed jar. This defaults to the artifactInput file name, and will overwrite it
outputFileName = "testsign" outputFileName = "testsign"
// The password of your key // GPG Private key file or string. Not required when the extension is used
keyPass = "123456" gpgKey = System.getenv("GPG_KEY")
// Your key alias // GPG Private Key password. Not required when extension is used
keyStoreAlias = "testalias" gpgPassword = "123456"
// Your keystore password // Should the task generate a .sig file. Defaults to true, and not required when extension is used
keyStorePass = "123456" generateSignature = false
// Your keystore location
keyStore = "/home/hypherionsa/dummystore.jks"
}
// Example of signing another jar
val signDummyJar by tasks.register<SignJarTask>("signDummyJar") {
dependsOn(tasks.createDummyJar)
artifactInput = tasks.createDummyJar
keyPass = "123456"
keyStoreAlias = "testalias"
keyStorePass = "123456"
keyStore = "/home/hypherionsa/dummystore.jks"
} }
``` ```

View File

@@ -0,0 +1,35 @@
/*
* This file is part of KeyMaster, licensed under the MIT License (MIT).
*
* Copyright (c) 2024 HypherionSA and Contributors
*
*/
package dev.firstdark.keymaster.plugin;
import lombok.Getter;
import lombok.Setter;
import org.gradle.api.Project;
import org.gradle.api.provider.Property;
/**
* @author HypherionSA
* Plugin Extension for sharing common configs between multiple tasks
*/
@Getter
@Setter
public class KeyMasterGradleExtension {
// Default properties. These are overridden by the values specified on the task
private final Property<String> gpgKey;
private final Property<String> gpgPassword;
private final Property<Boolean> generateSignature;
private final Property<String> outputDirectory;
public KeyMasterGradleExtension(Project project) {
this.gpgKey = project.getObjects().property(String.class);
this.gpgPassword = project.getObjects().property(String.class);
this.generateSignature = project.getObjects().property(Boolean.class).convention(true);
this.outputDirectory = project.getObjects().property(String.class).convention(project.getBuildDir() + "/libs");
}
}

View File

@@ -1,3 +1,9 @@
/*
* This file is part of KeyMaster, licensed under the MIT License (MIT).
*
* Copyright (c) 2024 HypherionSA and Contributors
*
*/
package dev.firstdark.keymaster.plugin; package dev.firstdark.keymaster.plugin;
import org.gradle.api.Plugin; import org.gradle.api.Plugin;
@@ -6,12 +12,13 @@ import org.jetbrains.annotations.NotNull;
/** /**
* @author HypherionSA * @author HypherionSA
* Main plugin class. Mostly a dummy for this plugin * Main plugin class.
*/ */
public class KeyMasterGradlePlugin implements Plugin<Project> { public class KeyMasterGradlePlugin implements Plugin<Project> {
@Override @Override
public void apply(@NotNull Project target) { public void apply(@NotNull Project target) {
target.getLogger().info("KeyMaster Plugin is activated"); target.getLogger().info("KeyMaster Plugin is activated");
target.getExtensions().create("keymaster", KeyMasterGradleExtension.class);
} }
} }

View File

@@ -1,21 +1,33 @@
/*
* This file is part of KeyMaster, licensed under the MIT License (MIT).
*
* Copyright (c) 2024 HypherionSA and Contributors
*
*/
package dev.firstdark.keymaster.tasks; package dev.firstdark.keymaster.tasks;
import dev.firstdark.keymaster.plugin.KeyMasterGradleExtension;
import dev.firstdark.keymaster.utils.PluginUtils;
import lombok.Setter; import lombok.Setter;
import org.apache.commons.lang3.StringUtils; import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.gradle.api.Project; import org.bouncycastle.openpgp.*;
import org.gradle.api.provider.Provider; import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
import org.gradle.api.GradleException;
import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.bundling.AbstractArchiveTask;
import org.gradle.jvm.tasks.Jar; import org.gradle.jvm.tasks.Jar;
import org.jetbrains.annotations.Nullable;
import java.io.File; import java.io.*;
import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import java.util.HashMap; import java.security.Security;
import java.util.Map;
import static dev.firstdark.keymaster.utils.PluginUtils.isNullOrBlank;
import static dev.firstdark.keymaster.utils.PluginUtils.resolveFile;
/** /**
* @author HypherionSA * @author HypherionSA
@@ -31,14 +43,20 @@ public class SignJarTask extends Jar {
private String outputFileName = "signed.jar"; private String outputFileName = "signed.jar";
// KeyStore values // KeyStore values
private String keyStorePass; private String gpgKey;
private String keyStore; private String gpgPassword;
private String keyStoreAlias; private Boolean generateSignature = true;
private String keyPass;
// Set the output directory. Defaults to build/libs // Set the output directory. Defaults to build/libs
private String outputDirectory = getProject().getBuildDir() + "/libs"; private String outputDirectory = getProject().getBuildDir() + "/libs";
@Nullable
private final KeyMasterGradleExtension extension;
public SignJarTask() {
extension = getProject().getExtensions().findByType(KeyMasterGradleExtension.class);
}
@Input @Input
public Object getArtifactInput() { public Object getArtifactInput() {
return resolveFile(getProject(), this.artifactInput); return resolveFile(getProject(), this.artifactInput);
@@ -50,28 +68,40 @@ public class SignJarTask extends Jar {
} }
@Input @Input
public String getKeyStorePass() { @Optional
return this.keyStorePass; @Nullable
public String getGpgKey() {
if (!isNullOrBlank(gpgKey))
return gpgKey;
if (extension != null && !isNullOrBlank(extension.getGpgKey().getOrNull()))
return extension.getGpgKey().get();
return null;
} }
@Input @Input
public String getKeyStore() { @Optional
return this.keyStore; @Nullable
} public String getGpgPassword() {
if (!isNullOrBlank(gpgPassword))
return gpgPassword;
@Input if (extension != null && !isNullOrBlank(extension.getGpgPassword().getOrNull()))
public String getKeyStoreAlias() { return extension.getGpgPassword().get();
return this.keyStoreAlias;
}
@Input return null;
public String getKeyPass() {
return this.keyPass;
} }
@Input @Input
public String getOutputDirectory() { public String getOutputDirectory() {
return this.outputDirectory; if (!isNullOrBlank(outputDirectory))
return outputDirectory;
if (extension != null && !isNullOrBlank(extension.getOutputDirectory().getOrNull()))
return extension.getOutputDirectory().get();
return outputDirectory;
} }
@OutputFile @OutputFile
@@ -79,6 +109,14 @@ public class SignJarTask extends Jar {
return new File(outputDirectory, outputFileName); return new File(outputDirectory, outputFileName);
} }
@Input
public Boolean getGenerateSignature() {
if (extension != null && extension.getGenerateSignature().isPresent())
return extension.getGenerateSignature().get();
return generateSignature;
}
/** /**
* Main Task Logic * Main Task Logic
*/ */
@@ -86,14 +124,14 @@ public class SignJarTask extends Jar {
@TaskAction @TaskAction
public void doTask() { public void doTask() {
// Check that input is supplied // Check that input is supplied
if (artifactInput == null) { if (getArtifactInput() == null) {
getProject().getLogger().error("Input cannot be null!"); getProject().getLogger().error("Input cannot be null!");
return; return;
} }
// Check that all the required values are supplied // Check that all the required values are supplied
if (isNullOrBlank(keyPass) || isNullOrBlank(keyStore) || isNullOrBlank(keyStoreAlias) || isNullOrBlank(keyStorePass)) { if (isNullOrBlank(getGpgKey()) || isNullOrBlank(getGpgPassword())) {
getLogger().error("Please provide all required parameters: keyStore, keyStoreAlias, keyStorePass, keyPass"); getLogger().error("Please provide all required parameters: keyStore, keyPass");
return; return;
} }
@@ -101,10 +139,11 @@ public class SignJarTask extends Jar {
File tempDir = new File(getProject().getBuildDir(), "signing"); File tempDir = new File(getProject().getBuildDir(), "signing");
tempDir.mkdirs(); tempDir.mkdirs();
// Try to sign the jar
try { try {
processArtifact(artifactInput, tempDir); processArtifact(getArtifactInput(), tempDir);
} catch (Exception e) { } catch (Exception e) {
getLogger().error("Failed to sign artifact {}", artifactInput, e); getLogger().error("Failed to sign artifact {}", getArtifactInput(), e);
} }
// Remove the temp working dir // Remove the temp working dir
@@ -118,36 +157,35 @@ public class SignJarTask extends Jar {
* @throws IOException This is mostly thrown when a file copy error occurs * @throws IOException This is mostly thrown when a file copy error occurs
*/ */
@SuppressWarnings("ResultOfMethodCallIgnored") @SuppressWarnings("ResultOfMethodCallIgnored")
private void processArtifact(Object input, File tempDir) throws IOException { private void processArtifact(Object input, File tempDir) throws IOException, PGPException {
// Set up the input file // Set up the input file
File inputFile = resolveFile(getProject(), input); File inputFile = resolveFile(getProject(), input);
// Check if the output file is specified. If not, default to the input file // Check if the output file is specified. If not, default to the input file
outputFileName = outputFileName.equalsIgnoreCase("signed.jar") ? inputFile.getName() : outputFileName + ".jar"; outputFileName = getOutputFileName().equalsIgnoreCase("signed.jar") ? inputFile.getName() : getOutputFileName() + ".jar";
// Copy the original input file to the temporary processing folder // Copy the original input file to the temporary processing folder
File tempInput = new File(tempDir, inputFile.getName()); File tempInput = new File(tempDir, inputFile.getName());
Files.copy(inputFile.toPath(), tempInput.toPath(), StandardCopyOption.REPLACE_EXISTING); Files.copy(inputFile.toPath(), tempInput.toPath(), StandardCopyOption.REPLACE_EXISTING);
// Create a temporary output jar // Create a temporary output jar
File tempOutput = new File(tempDir, outputFileName); File tempOutput = new File(tempDir, getOutputFileName());
File sigTempFile = new File(tempDir, tempOutput.getName() + ".sig");
File outputSigFile = new File(getOutputFile().getParentFile(), getOutputFile().getName() + ".sig");
// Configure the jar signing // Sign the damn thing
Map<String, Object> map = new HashMap<>(); signGPG(tempInput, sigTempFile, tempOutput);
map.put("alias", keyStoreAlias);
map.put("storePass", keyStorePass);
map.put("jar", tempInput.getAbsolutePath());
map.put("signedJar", tempOutput.getAbsolutePath());
map.put("keypass", keyPass);
map.put("keyStore", resolveFile(getProject(), keyStore).getAbsolutePath());
// SIGN IT
getProject().getAnt().invokeMethod("signjar", map);
// Copy the signed jar to the libs folder // Copy the signed jar to the libs folder
Files.copy(tempOutput.toPath(), getOutputFile().toPath(), StandardCopyOption.REPLACE_EXISTING); Files.copy(tempOutput.toPath(), getOutputFile().toPath(), StandardCopyOption.REPLACE_EXISTING);
getProject().getLogger().lifecycle("Signed " + getOutputFile().getName() + " successfully"); // Copy Signature File
if (getGenerateSignature()) {
Files.copy(sigTempFile.toPath(), outputSigFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
sigTempFile.delete();
}
getProject().getLogger().lifecycle("Signed {} successfully", getOutputFile().getName());
// Cleanup the temporary files // Cleanup the temporary files
tempOutput.delete(); tempOutput.delete();
@@ -155,45 +193,58 @@ public class SignJarTask extends Jar {
} }
/** /**
* Helper method to check if a supplied string is null or empty * Main Signing logic. This handles reading the GPG keys, and doing the actual signing
* @param s The string to test * @param inputFile The jar to be signed
* @return True if null or empty * @param signatureFile The GPG private key file or string
* @param signedOutputFile The output, signed jar file
* @throws IOException Thrown when a file error occurs
* @throws PGPException Thrown when a signature error occurs
*/ */
private boolean isNullOrBlank(String s) { private void signGPG(File inputFile, File signatureFile, File signedOutputFile) throws IOException, PGPException {
if (s == null) // Load Bouncy Castle
return true; BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
return StringUtils.isBlank(s); // Load the GPG private key
} byte[] keyBytes = PluginUtils.resolvePrivateKey(getGpgKey());
if (keyBytes == null) {
/** throw new GradleException("Could not read GPG private key. Signing will fail");
* Resolve an Object to a File
* @param project The project the file potentially belongs to
* @param obj The object to process
* @return A File object, ready to use
*/
private File resolveFile(Project project, Object obj) {
if (obj == null) {
throw new NullPointerException("Null Path");
} }
if (obj instanceof Provider) { // Process the private key
Provider<?> p = (Provider<?>) obj; try (ByteArrayInputStream keyInputStream = new ByteArrayInputStream(keyBytes);
obj = p.get(); FileOutputStream sigOutputStream = new FileOutputStream(signatureFile);
} FileOutputStream signedOutputStream = new FileOutputStream(signedOutputFile)) {
if (obj instanceof File) { PGPSecretKey secretKey = PluginUtils.readSecretKey(keyInputStream);
return (File) obj; PGPPrivateKey privateKey = secretKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider(provider).build(getGpgPassword().toCharArray()));
}
if (obj instanceof AbstractArchiveTask) { PGPSignatureGenerator signature = new PGPSignatureGenerator(
return ((AbstractArchiveTask)obj).getArchiveFile().get().getAsFile(); new JcaPGPContentSignerBuilder(secretKey.getPublicKey().getAlgorithm(), PGPUtil.SHA1)
} .setProvider(provider));
signature.init(PGPSignature.BINARY_DOCUMENT, privateKey);
if (obj instanceof String) { // Write signature to output .sig file
return new File(obj.toString()); if (getGenerateSignature()) {
} try (FileInputStream inputStream = new FileInputStream(inputFile)) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
signature.update(buffer, 0, bytesRead);
}
return project.file(obj); signature.generate().encode(sigOutputStream);
}
}
// Copy the signed content to the output signed jar file
try (FileInputStream inputStream = new FileInputStream(inputFile)) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
signedOutputStream.write(buffer, 0, bytesRead);
}
}
}
} }
} }

View File

@@ -0,0 +1,135 @@
/*
* This file is part of KeyMaster, licensed under the MIT License (MIT).
*
* Copyright (c) 2024 HypherionSA and Contributors
*
*/
package dev.firstdark.keymaster.utils;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.openpgp.*;
import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
import org.gradle.api.GradleException;
import org.gradle.api.Project;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.bundling.AbstractArchiveTask;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
/**
* @author HypherionSA
* Helper Methods used in the plugin
*/
public class PluginUtils {
/**
* Helper method to load PGP secrets from the user specified input
* @param input The InputStream of the file/string to process
* @return The signing key
* @throws IOException Thrown when a file error occurs
* @throws PGPException Thrown when a signature error occurs
*/
public static PGPSecretKey readSecretKey(InputStream input) throws IOException, PGPException {
PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(
PGPUtil.getDecoderStream(input), new JcaKeyFingerprintCalculator());
Iterator<PGPSecretKeyRing> keyRingIter = pgpSec.getKeyRings();
while (keyRingIter.hasNext()) {
PGPSecretKeyRing keyRing = keyRingIter.next();
Iterator<PGPSecretKey> keyIter = keyRing.getSecretKeys();
while (keyIter.hasNext()) {
PGPSecretKey key = keyIter.next();
if (key.isSigningKey()) {
return key;
}
}
}
throw new IllegalArgumentException("Can't find signing key in key ring.");
}
/**
* Helper method to read a GPG private key from either a file, or String
* @param input File or String to process
* @return The read key bytes, or null
*/
public static byte[] resolvePrivateKey(String input) {
File f = new File(input);
if (f.exists() && f.isFile()) {
try {
input = FileUtils.readFileToString(f, StandardCharsets.UTF_8);
} catch (Exception e) {
throw new GradleException("Failed to read GPG Private key", e);
}
}
if (!isNullOrBlank(input)) {
if (input.startsWith("-----")) {
String[] parts = input.split("\n");
StringBuilder sb = new StringBuilder();
for (String part : parts) {
if (!part.startsWith("-----")) {
sb.append(part);
}
}
return Base64.decodeBase64(sb.toString());
} else {
return input.getBytes(StandardCharsets.UTF_8);
}
}
return null;
}
/**
* Helper method to check if a supplied string is null or empty
* @param s The string to test
* @return True if null or empty
*/
public static boolean isNullOrBlank(String s) {
if (s == null)
return true;
return StringUtils.isBlank(s);
}
/**
* Resolve an Object to a File
* @param project The project the file potentially belongs to
* @param obj The object to process
* @return A File object, ready to use
*/
public static File resolveFile(Project project, Object obj) {
if (obj == null) {
throw new NullPointerException("Null Path");
}
if (obj instanceof Provider) {
Provider<?> p = (Provider<?>) obj;
obj = p.get();
}
if (obj instanceof File) {
return (File) obj;
}
if (obj instanceof AbstractArchiveTask) {
return ((AbstractArchiveTask)obj).getArchiveFile().get().getAsFile();
}
if (obj instanceof String) {
return new File(obj.toString());
}
return project.file(obj);
}
}

View File

@@ -16,6 +16,16 @@ dependencies {
} }
// This is optional. These values can be configured on the task
keymaster {
// GPG Password
gpgPassword = "123456"
// GPG Key file, or String.
gpgKey = System.getenv("GPG_KEY")
// Generate a .sig file for signed jars, to be used for verification
generateSignature = true
}
tasks.register('createDummyJar', Jar) { tasks.register('createDummyJar', Jar) {
// Configure the JAR task to have no files // Configure the JAR task to have no files
from {} from {}
@@ -33,26 +43,12 @@ tasks.register('signJar', SignJarTask) {
// Optional. Set the output name of the signed jar. This defaults to the artifactInput file name, and will overwrite it // Optional. Set the output name of the signed jar. This defaults to the artifactInput file name, and will overwrite it
outputFileName = "testsign" outputFileName = "testsign"
// The password of your key // GPG Private key file or string. Not required when the extension is used
keyPass = "123456" gpgKey = System.getenv("GPG_KEY")
// Your key alias // GPG Private Key password. Not required when extension is used
keyStoreAlias = "testalias" gpgPassword = "123456"
// Your keystore password // Should the task generate a .sig file. Defaults to true, and not required when extension is used
keyStorePass = "123456" generateSignature = false
}
// Your keystore location
keyStore = "/home/hypherionsa/dummystore.jks"
}
// Example of signing another jar
tasks.register('signDummyJar', SignJarTask) {
dependsOn createDummyJar
artifactInput = createDummyJar
keyPass = "123456"
keyStoreAlias = "testalias"
keyStorePass = "123456"
keyStore = "/home/hypherionsa/dummystore.jks"
}

Binary file not shown.