Using Gradle to PGP sign and checksum files

When creating software for distribution to end users, it’s a good idea to enable checking its integrity and trustworthiness.

A checksum file allows a user to download the file and ensure that it wasn’t corrupted during download or replaced on the server by an attacker. A signature file allows a user to verify that it actually came from the developer.

Creating a checksum file

A simple way to do this is to use the ant checksum integration that comes with Gradle. There are several algorithms to choose from including MD5, SHA-1, SHA-256 and SHA-512. This will create a myFile.SHA256 file, where myFile is the thing you want to distribute to users, such as an .exe or .apk.

ant.checksum(file: 'myFile', fileext: '.SHA256', algorithm: "SHA-256", pattern: "{0} {1}")

Creating a signed file

Gradle comes with a signing plugin. First apply the plugin in your build.gradle,

apply plugin: 'signing'

You’ll need to provide the signing plugin with the PGP key ID and passphrase to use. There are several ways to do this, one way is to create file at ~/.gradle/gradle.properties

signing.gnupg.keyName=ABCD1234
signing.gnupg.passphrase=hunter2

The advantage of this gradle.properties file is that it sits outside source control, no accidental commits, and its properties are read by Gradle when a task is run.

Finally you can sign the file, this will create a myFile.asc file with a PGP signature in it.

signing {
            useGpgCmd()
            sign file('myFile')
        }

useGpgCmd() will use the GPG executable on your system, this should already be present on Linux systems. With Windows you’d need to install GPG, it comes with with Git for Windows.

You will find other instructions where a key, password and secretKeyRingFile file are required. However, since GPG 2.1 there is no secring file, so it is better to useGpgCmd() instead.

All together in a Gradle task

In this example, I’m creating an Android APK, its checksum and signature files in a task.

task createVerificationFiles(group:'build') {
    def finalApkName = "gpslogger-"+android.defaultConfig.versionName+".apk"

    copy{
        from "build/outputs/apk/release/gpslogger-release.apk"
        into "./"

        // copy and rename file
        rename { String fileName ->
            fileName.replace("gpslogger-release.apk", finalApkName)
        }
    }

    if(file(finalApkName).isFile()){
        //PGP Sign
        signing {
            useGpgCmd()
            sign file(finalApkName)
        }

        //SHA256 Checksum
        ant.checksum(file: finalApkName, fileext: '.SHA256', algorithm: "SHA-256", pattern: "{0} {1}")
    }
}

Verifying your downloads

Help your users out by sharing instructions on how to verify your downloads.

Verify the checksum

To verify the checksum file, you can use sha256sum, if you used SHA-512, you can use sha512sum on Linux.

sha256sum -c ~/Downloads/myFile.SHA256

Verify the signature

Users will first need to import your public PGP key. Easy ways are via keybase or a receive key command

gpg --recv-key 6989CF77490369CFFDCBCD8995E7D75C76CBE9A9

You can then verify the .asc

gpg --verify ~/Downloads/myFile.asc

Updated: