如何在 Android 中签署 AAR Artifacts?

Posted

技术标签:

【中文标题】如何在 Android 中签署 AAR Artifacts?【英文标题】:How to sign AAR Artifacts in Android? 【发布时间】:2017-08-24 14:14:13 【问题描述】:

我目前正在开发一个 .AAR android 库,我想用我自己的密钥对发布的工件进行签名,这样我就可以确定我是否发布了具有相同名称和功能的假 aar。

注意事项 1:

我希望能够以编程方式检查我的库的真实性,即使伪造的库只是伪造我的 aar 文件的一部分功能。

注意事项 2:

不会将此 aar 发布到 maven、sonatype 或任何其他公共存储库中。因此,我将为典型的发布流程签署它,例如签署 apk 文件。

【问题讨论】:

“这样我就可以确定我是否已经发布了具有相同名称和功能的假 aar” - 但是如果您不分发 AAR,他们将如何获得它做个假的? @CommonsWare 我们将此库发布给我们的一些业务合作伙伴,他们将把它集成到他们的应用程序中并将它们发布到公共市场。 @FarhadFaghihi ,您找到问题的答案了吗?我也在尝试在我的 AAR 库中实现相同的目标。我可以使用 Jar 签名者对我的 AAR 进行签名,但是如何在运行时检查 AAR 的完整性? 【参考方案1】:

您可以使用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.

【讨论】:

感谢您富有洞察力的回答。 :) 我想要更多的联系。如果你愿意,请加入我的推特。 将签名的AAR文件集成到父App后,如何在运行时查看AAR的签名?我设法获取了父应用程序的 SHA-256,但我需要检查我的 AAR 文件的 SHA-256。 因此,从这个答案看来,android aar 库的数字签名并没有像使用 Android 的 apksigner.jarapk 那样在 android 的工具集中完成。因此,我可以使用 gpg 或 openssl 等签署aar @MohanRaj - 我和你的情况一样。您是否找到了一种在运行时从父应用程序中验证 AAR 签名的方法?任何输入表示赞赏。谢谢! 我尝试了很长时间,并决定使用 AES 加密对我的 APK 进行加密,并将其作为文件存储在内存中,在运行时,我解密它然后借助反射我调用所有关键方法和类dex 文件。这是目前可用的最佳方式。【参考方案2】:

因为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)
        
    

【讨论】:

在我开始一个新问题之前:您如何捕获来自verifyJar 任务的输出消息?否则,在我看来,该任务永远不会失败,因此无法实际检查 .AAR 是否已成功签署。 @superjos 我认为如果验证失败,它会引发一些异常。它不是以这种方式工作的吗? @CAMOBAP 有什么方法可以验证图书馆消费者应用程序中的 aar 吗? @tronku 我想是的,你可以loop through a list of dependencies,并得到他们的路径。因此您可以过滤掉您需要的确切 AAR 路径。然后将其提供给ant.verifyjar 任务【参考方案3】:

你可以通过执行来生成它:

./gradlew assembleRelease

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

当然,您需要在库项目中添加签名密钥。请阅读Sign Your App

【讨论】:

那么如何确定这是签名的 aar 还是只是假的相似?【参考方案4】:

我没有尝试过,但这个“应该”工作:

在你的 gradle 配置文件中为你要创建的 aar 创建一个这样的块:

signedAar 
    signedConfig
        storeFile file("path/to/keystore")
        storePassword "Password"
        keyAlias "Alias"
        keyPassword "AliasPassword"
    

然后将其添加到同一配置文件的 buildTypes -> 发布块中:

signingConfig  signedAar.signedConfig

让我们知道这是否可行

【讨论】:

为您的应用程序签名,lib modue .aar 将自动签名。【参考方案5】:

你为什么不 sha-256 散列你的 aar 文件?即使有人搞砸了,aar 的哈希值也会发生变化,你就会知道。它对我有用;)

【讨论】:

如何在运行时获取 AAR 的 sha-256 ?当我尝试从我的包中提取签名信息时,它只给了我 App 的签名,而不是集成的 AAR。

以上是关于如何在 Android 中签署 AAR Artifacts?的主要内容,如果未能解决你的问题,请参考以下文章

在 Android Studio 中签署 Android apk 文件的最简单方法是啥? [复制]

如何在 Serum Anchor 中签署代币交易

在移动应用程序中签署 jwt 是不是安全?

如何在 Xcode 中签署归档应用程序

如何在单个.JAR中签署和部署JavaFX应用程序?

在Visual Studio和InstallShield中签署所有需要的文件