为一个JAR签名
Java允许开发者为他们的jar文件进行签名。然而,这些签名不是被设计用作安全措施的,也不应当用于安全用途。签名是用来做完整性检查的,这样开发者就能够检验他们是否在运行他们自己的未被编辑过的代码。(译者注:这里影响完整性和所谓“未被编辑”的因素仅限非人为因素,如网络传输和存储介质问题等。安全用途的签名必须经过安全理论验证)
注意: 再次谨记这个系统不是用于安全措施的。只要有足够的恶意意图,它就很有可能被利用(译者注:如sha-1碰撞,或者直接盗用签名文件等)。
创建一个keystore
keystore是一个保存有成功签名jar所需信息的私密数据库文件。要为一个jar签名,你需要一个公钥和私钥。公钥将会被用来检查jar是否被正确签名。
要生成一个密钥,执行以下命令并遵循keytool给出的指引。密钥应当已被SHA-1(译者注:一种摘要算法)编码过。
keytool -genkey -alias signFiles -keystore examplestore.jks
*keytool 是 Java Development Kit 的一部分并可以在其下属的 bin 文件夹中找到。*alias signFiles 表示别名应当在将来被用作 keystore 的入口点。*-keystore examplestore.jks 意味着 keystore 将被储存在 examplestore.jks 文件中。
获取公钥
要获取Forge所需要的公钥,执行以下命令:
keytool -list -alias signFiles -keystore examplestore.jks
然后复制公钥并移除所有的列,并将所有的大写字母变为小写以保证FML可以使用这个密钥。
在运行时检查
要允许FML比较密钥,将公钥添加到 @Mod 记号中的 certificateFingerprint 参数里。
当FML检测到密钥不匹配时,模组生命周期事件 FMLFingerprintViolationEvent 会被触发。如何处理密钥不匹配将取决于开发者。
- event.isDirectory() —— 当模组在开发环境中运行时,返回true。
- event.getSource() —— 返回密钥不匹配的文件。
- event.getExpectedFingerprint() —— 返回公钥。
- event.getFingerprints() —— 返回找到的所有公钥。
Buildscript设置
最终,为了让 Gradle 使用生成的密钥对签名jar文件,还需要在 build.gradle 中再进行一些工作。
task signJar(type: SignJar, dependsOn: reobfJar) {
inputFile = jar.archivePath
outputFile = jar.archivePath
}
build.dependsOn signJar
- dependsOn: reobfJar —— 这一行的这一小段很重要,因为 Gradle 不得不在 ForgeGradle 重新混淆jar包之后签名这个jar文件。
- jar.archivePath —— 归档文件(jar)的构建路径。
- build.dependsOn signJar —— 这一行告诉 Gradle 这个任务是由 gradlew build 启动的构建任务的一部分。
接下来为 signJar 任务设定的值必须被定义以保证 Gradle 可以找到 keystore 并真正给jar签名。这项工作必须在 gradle.properties 文件中完成。
- keyStore —— 这个值告诉 Gradle 到哪里去寻找生成的 keystore。
- alias —— 需要之前上文中定义的别名来让 Gradle 为这个文件签名。
- storePass —— 需要创建 keystore 时定义的密码来给 Gradle 访问文件的能力。
- keyPass —— 需要创建 keystore 时为key定义的密码来给 Gradle 访问key的能力。这个密码可能与 storePass 一样,但也可能不一样。