Instantly share code, notes, and snippets.

Embed
What would you like to do?
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!");
    }
}
@nallar

This comment has been minimized.

nallar commented Sep 21, 2017

Overwriting the output of another task causes that task to always be rebuild. It'd be better if the output was a separate file.

Unfortunately the reobfJar task already does this overwriting so you're not making things much worse unless the reobfJar task is also fixed.

@Jess4Tech

This comment has been minimized.

Jess4Tech commented Aug 8, 2018

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