Skip to content

Instantly share code, notes, and snippets.

@matthewprenger
Last active April 21, 2022 20:53
Show Gist options
  • Save matthewprenger/9b2da059b89433a01c1c to your computer and use it in GitHub Desktop.
Save matthewprenger/9b2da059b89433a01c1c to your computer and use it in GitHub Desktop.
A simple tutorial on setting up jar signing with ForgeGradle 2

Signing Your Jar

Signing your jar can help you and your users verify that the jar they have is an authentic jar created by you. This will help a lot, but is not 100% effective. If someone really wants to get around it, they can.

Creating a keystore

Let's start off by creating a new keystore. A keystore is the private database file that holds the information needed to sign a jar. This command requires a correctly setup Java Development Kit.

keytool -genkey -alias Matthew -keyalg RSA -keysize 2048 -keystore keystore.jks

In this case Matthew is my alias. You can think of this as a username. You can change the keysize if you wish, but 2048 bits should be plenty. The keystore parameter is the keystore file that will be created.

Next, answer the simple questions the keytool asks you. (You can press RETURN to accept the default values)

Buildscript setup

Once we have a keystore generated, we can now setup our build.gradle. We will define a new task, called signJar in this example, that will sign the jar for us.

build.gradle:

task signJar(type: SignJar, dependsOn: reobfJar) {
    onlyIf { // Skip the task if our secret data isn't available
        project.hasProperty('keyStore')
    }

    keyStore = project.keyStore // This needs to be a path to the keystore file
    alias = project.keyStoreAlias
    storePass = project.keyStorePass
    keyPass = project.keyStoreKeyPass
    inputFile = jar.archivePath
    outputFile = jar.archivePath
}

build.dependsOn signJar

Note the dependsOn: reobfJar statement. This is important because we need to sign the jar after ForgeGradle has reobfuscated the jar.

The build.dependsOn signJar statement is optional, but including it allows us to only execute gradle(w) build rather than gradle(w) build signJar.

Private information

Finally we need to create a file to hold the private information that shouldn't be kept in a public buildscript.

Create (or update) a gradle.properties file in the gradle user home directory:

  • Windows: C:\Users\Matthew\.gradle\gradle.propertes
  • Linux: /home/matthew/.gradle/gradle.properties
  • Mac: /Users/Matthew/.gradle/gradle.properties

Note: If you are using the Debian/Ubuntu jenkins package the path will be: /var/lib/jenkins/.gradle/gradle.properties

This is a Java properties file that is in the format: KEY=VALUE. Anything defined here can be referenced by project.KEY in the buildscript.

keyStore=/home/matthew/keystore.jks
keyStoreAlias=Matthew
keyStorePass=pass123
keyStoreKeyPass=pass456

Checking at runtime

The first thing we need to do is get the SHA1 fingerprint of our keystore. To get this, use the following command:

keytool -list -alias Matthew -keystore keystore.jks

Enter your password when prompted, and then it will output the fingerprint.

We need to transform this a bit for FML. Remove all colons, and change all of the uppercase letters to lowercase.

All we need to do is add one method to the @Mod file, and the SHA1 of the keystore to the @Mod annotation. FML will handle the rest.

@Mod(modId = "myMod", certificateFingerprint = "7649030e0bef927c405db85e02237b6a7b26376a")
public class MyMod {
    
    @Mod.EventHandler
    public void onFingerprintViolation(FMLFingerprintViolationEvent event) {
        logger.warning("Invalid fingerprint detected!");
    }
}
@Jess4Tech
Copy link

I have the jdk location set to JAVA_HOME is that what you mean by correctly set up JDK?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment