第五十三章. 签名插件

Chapter 53. The Signing Plugin

签名插件添加了对构件的文件和artifacts进行数字签名的功能。这些数字签名可以用于证明使用这个签名的artifact是谁构建的,以及其他的信息,比如签名是什么时候生成的。
The signing plugin adds the ability to digitally sign built files and artifacts. These digital signatures can then be used to prove who built the artifact the signature is attached to as well as other information such as when the signature was generated.

签名插件目前只提供了生成PGP 签名的支持(这是发布到Maven 中央库所需的签名格式)。
The signing plugin currently only provides support for generating PGP signatures (which is the signature format required for publication to the Maven Central Repository).

53.1. 用法

53.1. Usage

要使用 Signing 插件,请在构建脚本中包含以下语句:
To use the Signing plugin, include in your build script:

示例 53.1. 使用Signing插件 - Example 53.1. Using the Signing plugin

build.gradle

apply plugin: 'signing'

53.2. 签名凭证

53.2. Signatory credentials

为了创建 PGP 签名,你将需要一个密钥对(有关使用GnuPG 工具创建密钥对的介绍可以在GnuPG Howto中找到)。您需要向签名插件提供你的关键信息,即如下三项信息:
In order to create PGP signatures, you will need a key pair (instructions on creating a key pair using the GnuPG tools can be found in the GnuPG HOWTOs). You need to provide the signing plugin with your key information, which means three things:

  • 公钥 ID (一个8位字符的十六进制字符串)。


    The public key ID (an 8 character hexadecimal string).

  • 指向包含了你的私钥的密钥环文件的绝对路径。


    The absolute path to the secret key ring file containing your private key.

  • 用来保护你的私钥的密码。


    The passphrase used to protect your private key.

这些条目必须分别作为属性项目signing.keyIdsigning.passwordsigning.secretKeyRingFile 进行提供。鉴于这些值的个人和私人性质,一个好的做法是将它们保存在用户的gradle.properties文件(第14.2 节,“Gradle 属性和系统属性”中所述)。
These items must be supplied as the property projects signing.keyId, signing.password and signing.secretKeyRingFile respectively. Given the personal and private nature of these values, a good practice is to store them in the user gradle.properties file (described in Section 14.2, “Gradle properties and system properties”).

signing.keyId=24875D73
signing.password=secret
signing.secretKeyRingFile=/Users/me/.gnupg/secring.gpg

如果在用户的gradle.properties文件中指定的信息不适合你的环境,你可以提供这些信息,但你需要手动设置项目的属性。
If specifying this information in the user gradle.properties file is not feasible for your environment, you can source the information however you need to and set the project properties manually.

import org.gradle.plugins.signing.Sign

gradle.taskGraph.whenReady { taskGraph ->
    if (taskGraph.allTasks.any { it instanceof Sign }) {
        // Use Java 6's console to read from the console (no good for a CI environment)
        Console console = System.console()
        console.printf "\n\nWe have to sign some things in this build.\n\nPlease enter your signing details.\n\n"

        def id = console.readLine("PGP Key Id: ")
        def file = console.readLine("PGP Secret Key Ring File (absolute path): ")
        def password = console.readPassword("PGP Private Key Password: ")

        allprojects { ext."signing.keyId" = id }
        allprojects { ext."signing.secretKeyRingFile" = file }
        allprojects { ext."signing.password" = password }

        console.printf "\nThanks.\n\n"
    }
}

53.3. 指定要签名的内容

53.3. Specifying what to sign

除了配置内容要如何签名(即签名配置),你还必须指定哪些文件要签名。Signing 插件提供了一个DSL,它允许你指定应签名的任务及配置。
As well as configuring how things are to be signed (i.e. the signatory configuration), you must also specify what is to be signed. The Signing plugin provides a DSL that allows you to specify the tasks and/or configurations that should be signed.

53.3.1. 签名配置

53.3.1. Signing Configurations

签名一个配置的artifacts是很常见的情况。例如, Java 插件配置了构建一个jar文件,并且把 jar 文件添加到archives配置。使用Signing DSL,你可以指定这个配置的所有 artifacts 都应该被签名。
It is common to want to sign the artifacts of a configuration. For example, the Java plugin configures a jar to built and this jar artifact is added to the archives configuration. Using the Signing DSL, you can specify that all of the artifacts of this configuration should be signed.

53.3.2. 签名一个配置 - Example 53.2. Signing a configuration

build.gradle

signing {
    sign configurations.archives
}

这将在你的项目中创建一个名为“signArchives”的任务(Sign类型),这个任务会构建任何archives的artifacts(如果需要),然后为它们生成签名。签名文件将和被签名的artifacts放在一起。
This will create a task (of type Sign) in your project named “signArchives”, that will build any archives artifacts (if needed) and then generate signatures for them. The signature files will be placed alongside the artifacts being signed.

示例 53.3. 签署一个配置的输出 - Example 53.3. Signing a configuration output

gradle signArchives的输出结果
Output of gradle signArchives

> gradle signArchives
:compileJava
:processResources
:classes
:jar
:signArchives

BUILD SUCCESSFUL

Total time: 1 secs

53.3.2. 签名任务

53.3.2. Signing Tasks

在某些情况下,你需要签名的artifact 可能不是配置的一部分。在这种情况下,你可以直接签名生成了要签名的artifact 的任务。
In some cases the artifact that you need to sign may not be part of a configuration. In this case you can directly sign the task that produces the artifact to sign.

53.4. 签名一个任务 - Example 53.4. Signing a task

build.gradle

task stuffZip (type: Zip) {
    baseName = "stuff"
    from "src/stuff"
}

signing {
    sign stuffZip
}

这将在您的项目创建一个名为“signStuffZip”的(Sign类型) 的任务,这个任务会构建输入任务的archive(如果需要),并进行签字。签名文件将和被签名的 artifact 放在一起。
This will create a task (of type Sign) in your project named “signStuffZip”, that will build the input task's archive (if needed) and then sign it. The signature file will be placed alongside the artifact being signed.

示例 53.5. 签名一个任务的输出 - Example 53.5. Signing a task output

gradle signStuffZip的输出结果
Output of gradle signStuffZip

> gradle signStuffZip
:stuffZip
:signStuffZip

BUILD SUCCESSFUL

Total time: 1 secs

一个“可签名”的任务,必须输出某种类型的archive。这样的任务有 TarZipJarWarEar任务。
For a task to be “signable”, it must produce an archive of some type. Tasks that do this are the Tar, Zip, Jar, War and Ear tasks.

53.3.3. 有条件的签名

53.3.3. Conditional Signing

常见的使用模式是只在一定条件下签名构建的artifacts。例如,你可能不想对非发布版本签名artifacts。要做到这一点,你可以指定只在一定条件下才要求签名。
A common usage pattern is to only sign build artifacts under certain conditions. For example, you may not wish to sign artifacts for non release versions. To achieve this, you can specify that signing is only required under certain conditions.

53.6. 有条件的签名 - Example 53.6. Conditional signing

build.gradle

version = '1.0-SNAPSHOT'
ext.isReleaseVersion = !version.endsWith("SNAPSHOT")

signing {
    required { isReleaseVersion && gradle.taskGraph.hasTask("uploadArchives") }
    sign configurations.archives
}

在此示例中,我们只想要在我们构建一个我们即将去发布的发布版本的时候,才进行签名。由于我们正在检查任务图,以确定是否打算发布,我们必须将signing.required属性设置为一个闭包以推迟evaluation。更多的信息,请参阅SigningExtension.setRequired()
In this example, we only want to require signing if we are building a release version and we are going to publish it. Because we are inspecting the task graph to determine if we are going to be publishing, we must set the signing.required property to a closure to defer the evaluation. See SigningExtension.setRequired() for more information.

53.4. 发布签名

53.4. Publishing the signatures

当通过 Signing DSL指定什么要被签名的时候,生成的signature会自动地加入到 signaturesarchives 的依赖配置中。这意味着,如果你想要将你的签名以及artifacts上传到你的分布仓库中,正常来讲你只需要执行uploadArchives任务。
When specifying what is to be signed via the Signing DSL, the resultant signature artifacts are automatically added to the signatures and archives dependency configurations. This means that if you want to upload your signatures to your distribution repository along with the artifacts you simply execute the uploadArchives task as normal.

53.5. 签名 POM 文件

53.5. Signing POM files

当为你的artifacts部署签名到 Maven 仓库时,你还想签名发布的 POM 文件。签名插件添加了一个signing.signPom() (请参见: SigningExtension.signPom())方法,这个方法可以在你的上传任务配置的beforeDeployment()块中使用。
When deploying signatures for your artifacts to a Maven repository, you will also want to sign the published POM file. The signing plugin adds a signing.signPom() (see: SigningExtension.signPom()) method that can be used in the beforeDeployment() block in your upload task configuration.

示例 53.7. 为部署签名 POM - Example 53.7. Signing a POM for deployment

build.gradle

uploadArchives {
    repositories {
        mavenDeployer {
            beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
        }
    }
}

当不需要签名,以及由于缺少配置(即没有签名证书)而不能签名 POM 的时候,signPom()方法将什么都不会做,并且不会进行任何的提示。
When signing is not required and the POM cannot be signed due to insufficient configuration (i.e. no credentials for signing) then the signPom() method will silently do nothing.