如何在Android中签署AAR构件?

17

我目前正在开发一个 .AAR 安卓库,希望使用自己的密钥签署发布的工件,以便确定是否有人发布了具有相同名称和功能的伪造 AAR 库。

注意事项 1:

我想要能够通过程序检查我的库的真实性,即使是一个伪造的库,也只是伪造了我的 AAR 文件的一部分功能。

注意事项 2:

不会将这个 AAR 库发布到 Maven、Sonatype 或任何其他公共仓库。因此,我将为典型的发布流程对其进行签名,就像签名 APK 文件一样。


“这样我就可以确定是否有人发布了与我的同名和功能相同的伪造AAR。”--但是如果您没有分发AAR,他们怎么会得到它来制作假冒品呢? - CommonsWare
@CommonsWare 我们将发布这个库给我们的一些商业合作伙伴,他们将把它集成到他们的应用程序中并发布到公共市场。 - Farhad
@FarhadFaghihi,你找到问题的答案了吗?我也在尝试在我的AAR库中实现相同的功能。我可以使用Jar签名器对我的AAR进行签名,但如何在运行时检查AAR的完整性呢? - MohanRaj
5个回答

27

你可以使用 jarsigner 对你的 aar 库进行签名,同时可以使用 keytool 生成签名密钥。这两个工具都位于随 Android Studio 附带的嵌入式 JDK 中。按照以下步骤对你的库进行签名。

签名

生成一个密钥库及其密钥对。你需要提供证书字段:

keytool -genkeypair -alias aarsign -keypass mypassword -keystore aarsign.keystore -storepass mypassword -v

将生成的证书导出为PEM文件:

keytool -exportcert -rfc -alias aarsign -file aarsign-public.pem -keystore aarsign.keystore -storepass mypassword -v

创建一个包含证书的密钥库:

keytool -importcert -alias aarsign -file aarsign-public.pem -keystore aarsign-public.keystore -storepass mypassword -v

签署库:

jarsigner -keystore aarsign.keystore -storepass mypassword -keypass mypassword -signedjar lib-signed.aar -verbose lib.aar aarsign

验证

任何希望证明库的真实性的人需要以可靠的方式获取您的证书(或包含其证书的密钥库),并输入以下命令:

jarsigner -keystore aarsign-public.keystore -storepass mypassword -verify -verbose -certs lib-signed.aar aarsign

它将会显示这条消息

jar verified.

关于证书到期和签名时间戳的一些警告。您可以通过创建更严格的证书来消除这些警告。请参考 keytooljarsigner 文档。

有两种方式可以确定您的库是否被篡改:不匹配的摘要或不匹配的证书。如果有人从不同的源代码或具有不同的资源生成 aar,则摘要将不匹配,jarsigner 将发出警告,例如:

jarsigner: java.lang.SecurityException: invalid SHA-256 signature file digest for <file>

如果有人提供了一张与您自己不同的证书,jarsigner 将会发出警告:

Warning: 
This jar contains entries whose certificate chain is not validated.
This jar contains signed entries which are not signed by the specified alias(es).
This jar contains signed entries that are not signed by alias in this keystore.

谢谢你的深入回答。 :) 我想更加互动。如果你愿意,可以在 Twitter 上关注我。 - Farhad
3
将签名的 AAR 文件集成到父应用程序中后,如何在运行时检查 AAR 的签名?我成功获取了父应用程序的 SHA-256,但我需要检查我的 AAR 文件的 SHA-256。 - MohanRaj
因此,从这个答案来看,安卓aar库的数字签名并不像使用安卓的apksigner.jar签名apk一样在安卓工具集内完成。因此,我可以使用gpg或openssl等工具对aar进行签名。 - daparic
@MohanRaj - 我和你处于相同的情况。你有找到一种在父应用程序内运行时验证 AAR 签名的方法吗?感谢任何建议。谢谢! - learner
我尝试了很久,决定使用AES加密将我的APK文件存储为文件在内存中。在运行时,我使用反射解密它,然后调用Dex文件中的所有关键方法和类。这是目前可用的最佳方式。 - MohanRaj
一个 aar 是否可以在运行时验证它是否被篡改? - sinek

1
因为 variant.signingConfig 对我不起作用,所以我使用了
apply plugin: 'com.android.library'

...

android {
    ...

    signingConfigs {
        release {
            storeFile file("${rootProject.projectDir}/keystore.jks")
            storePassword "XXXX"
            keyAlias "alias"
            keyPassword "XXXX"
        }
    }

    ...
}

tasks.whenTaskAdded { task ->
    if (task.name == 'assembleRelease') {
        def aarPath = "${project.buildDir}/outputs/aar/XXX-release.aar"

        task.doLast {
            ant.signjar(
                    alias: android.signingConfigs.release.keyAlias,
                    jar: aarPath,
                    keystore: android.signingConfigs.release.storeFile,
                    storepass: android.signingConfigs.release.storePassword,
                    keypass: android.signingConfigs.release.keyPassword,
                    preservelastmodified: 'true')

            ant.verifyjar(
                    alias: android.signingConfigs.release.keyAlias,
                    jar: aarPath,
                    keystore: android.signingConfigs.release.storeFile,
                    storepass: android.signingConfigs.release.storePassword,
                    keypass: android.signingConfigs.release.keyPassword)
        }
    }
}

1
在我开始新的问题之前:你如何捕获verifyJar任务的输出消息?否则,对我来说,任务似乎永远不会失败,因此实际上无法检查.AAR是否已成功签名。 - superjos
@superjos 我认为如果验证失败,它会抛出一些异常。难道它不是这样工作的吗? - CAMOBAP
@CAMOBAP,有没有办法在库消费者应用程序中验证aar? - tronku
@tronku 我认为你可以循环遍历依赖列表,并获取它们的路径。这样,你就可以过滤出你需要的确切AAR路径。然后将其提供给ant.verifyjar任务。 - CAMOBAP

0

你可以通过执行以下操作生成:

./gradlew assembleRelease

或者从Gradle菜单开始,在Android Studio右侧选择YourLibraryProject->Tasks->Build->AssembleRelease。

但是当然你需要在库项目中添加签名密钥。请阅读签署您的应用程序


那么如何确定这是一个签名的aar还是假冒的相似物呢? - Farhad

0
我还没有尝试过,但是这个“应该”可以工作:
在您的gradle配置文件中创建一个类似于此的块,用于创建aar:
signedAar {
    signedConfig{
        storeFile file("path/to/keystore")
        storePassword "Password"
        keyAlias "Alias"
        keyPassword "AliasPassword"
    }
}

然后将此添加到同一配置文件的buildTypes -> release块中:

signingConfig  signedAar.signedConfig

请告诉我们这是否有效


签署您的应用程序和库模块,.aar 将自动签署。 - Manoj Tarkar

-1
为什么不对你的 aar 文件进行 sha-256 哈希处理呢?即使有人搞了鬼,aar 的哈希值也会改变,这样你就能知道了。这个方法对我很有效 ;)

1
如何在运行时获取AAR的sha-256?当我尝试从我的包中提取已签名信息时,它只给出应用程序的签名,而不是集成的AAR。 - MohanRaj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接