Simple Library with Signature
In this tutorial, we are going to build our minimal component with a digital signature.
The sample project is here.
Project setup#
#
pom.yamlgroup: jarbirdsamplesartifactId: simplelibversion: 1.0
The version suffix -SNAPSHOT
is removed. Then we may publish the component again.
Before you start, you may want to setup a temporary Gradle environment for this tutorial. Then your working environment will not be messed up.
#
Run it, the first attempt$ ./gradlew jbPublish Build with Groovy build scriptFill in the property values in `gradle.properties` before build.
> Task :signSimplelibPublication FAILEDgpg: skipped "........": No secret keygpg: signing failed: No secret key
FAILURE: Build failed with an exception.
* What went wrong:Execution failed for task ':signSimplelibPublication'.> Process 'command 'gpg2'' finished with non-zero exit value 2
It seems thing does not go well. It is because we have not set up the key used for signing the artefact.
#
GnuPGWe need to set up a signing key pair. (If you already have it, just skip this part) It is a one-off task, that we may reuse the key pair for all of our projects. There are various choices to do so, but we do the simplest thing here. Please refer to the Signing configuration for other possibilities.
We need to have an implementation of GnuPG installed on our computer. There are a few choices:
Keypair can be generated by the command gpg --gen-key
. You need to provide your name and email address.
$ gpg --gen-keygpg (GnuPG/MacGPG2) 2.2.24; Copyright (C) 2020 Free Software Foundation, Inc.This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.
Note: Use "gpg --full-generate-key" for a full-featured key generation dialog.
GnuPG needs to construct a user ID to identify your key.
Real name: Jarbird DemoEmail address: jarbird.demo@fake-email.comYou selected this USER-ID: "Jarbird Demo <jarbird.demo@fake-email.com>"
Change (N)ame, (E)mail, or (O)kay/(Q)uit? O
You will be asked for a passphrase to protect the key pair at this point. It is a passphrase to protect your keybox file. If you already have a keybox, use the same passphrase. Otherwise, create a new passphrase and keep it safe.
We need to generate a lot of random bytes. It is a good idea to performsome other action (type on the keyboard, move the mouse, utilize thedisks) during the prime generation; this gives the random numbergenerator a better chance to gain enough entropy.We need to generate a lot of random bytes. It is a good idea to performsome other action (type on the keyboard, move the mouse, utilize thedisks) during the prime generation; this gives the random numbergenerator a better chance to gain enough entropy.gpg: key BCCF8CD8B61806FE marked as ultimately trustedgpg: revocation certificate stored as '/Users/me/.gnupg/openpgp-revocs.d/6BA0B340ABB2411040589423BCCF8CD8B61806FE.rev'public and secret key created and signed.
pub rsa3072 2021-05-12 [SC] [expires: 2023-05-12] 6BA0B340ABB2411040589423BCCF8CD8B61806FEuid Jarbird Demo <jarbird.demo@fake-email.com>sub rsa3072 2021-05-12 [E] [expires: 2023-05-12]$
The generated key is identified by the key ID (that ended with B61806FE
)
#
gradle.propertiesThe Jarbird plugin uses the key ID and passphrase specified in gradle.properties
. It could be in ~/.gradle/gradle.properties
or gradle.properties
under the project directory. We may also specify these pieces of information in environment variables, which may be more suitable for CI/CD environment.
caution
Putting this information at ~/.gradle/gradle.properties
or environment variable is preferable to avoid putting sensitive information in a project. we put the gradle.properties
in this project just for simplifying the demonstration.
# ...signing.gnupg.keyName=B61806FEsigning.gnupg.passphrase=your-GnuPg-passphrase# ...
The keyName is the last 8 characters of the key ID in the result of key generation. If you forget it, use gpg --list-key
to find it.
The gradle.properties
in the sample project contains these entries for your reference.
#
Run it, the second attempt$ ./gradlew jbPublishBuild with Groovy build scriptFill in the property values in gradle.properties before build.
> Configure project :
> Task :jbDokkaHtmlSimplelibInitializing pluginsDokka is performing: documentation for simplelibValidity checkCreating documentation models
WARN: The registry key 'java.correct.class.type.by.place.resolve.scope' accessed, but not loaded yet
> Task :jbDokkaHtmlSimplelibTransforming documentation model before mergingMerging documentation modelsTransforming documentation model after mergingCreating pagesTransforming pagesRendering
BUILD SUCCESSFUL in 8s9 actionable tasks: 9 executed
We did it successfully. The produced results are in ~/.m2/repository/jarbirdsamples/simplelib/1.0
$ ls -1 ~/.m2/repository/jarbirdsamples/simplelib/1.0simplelib-1.0-javadoc.jarsimplelib-1.0-javadoc.jar.ascsimplelib-1.0-sources.jarsimplelib-1.0-sources.jar.ascsimplelib-1.0.jarsimplelib-1.0.jar.ascsimplelib-1.0.modulesimplelib-1.0.module.ascsimplelib-1.0.pomsimplelib-1.0.pom.asc
The files with the .asc
extension are the signature file. Note that the metadata-local.xml
file when building 1.0-SNAPSHOT
is not here. The non SNAPSHOT
version does not need the file.
#
Bonus: Setup temporary Gradle environment for tutorialWe may set up an isolated Gradle environment for this tutorial. set the environment variable GRADLE_USER_HOME
like this.
export GRADLE_USER_HOME=~/.gradle_jarbird_trial
Then Gradle uses the directory ~/.gradle_jarbird_trial
instead of the default ~/.gradle
for all working and caching files.
If you are using zsh shell, you may want to enable autoenv
plugin so that it is done automatically.
In this sample, we have set up the environment variable in the .in
file and undo it in the .out
file.
# setup GRADLE_USER_HOME automatically for https://github.com/zpm-zsh/autoenvexport GRADLE_USER_HOME=~/.gradle_jarbird_trial
# setup GRADLE_USER_HOME automatically for https://github.com/zpm-zsh/autoenvunset GRADLE_USER_HOME
It may take a while to use this alternate environment to build the Gradle project for the first time. It will load the Gradle itself, and all plugin and library dependencies for this project.