教程:了解 Android 应用签名

教程:了解 Android 应用签名

我必须承认,当我开始开发移动应用时,我对保护应用和保证其真实性的各种要求感到困惑。在 iOS 方面,您会遇到诸如 授权 (entitlement)描述文件 (provisioning profile)Bundle ID 以及许多其他术语。Android 具有类似的功能,它们的措辞同样令人困惑,包括诸如 密钥库 (keystore)密钥哈希 (key hash)别名 (alias) 等术语,此外,还需要在命令行中输入命令。

本周的教程专门关注 Android 签名过程,旨在为这个可能很复杂的主题带来清晰和理解。

密钥库

保护您的 Android 应用的基本原理是使用生成的证书和数字“密钥”,它提供唯一的、加密的且相当难以破解的签名。这证明该应用来自您,而不是其他可疑来源。

在 Android 上,这是通过 密钥库 来完成的。密钥库是一个简单的文件,其中包含一个非常大的加密数据块。此文件可以存储在您计算机上的任何位置,这通常是开发人员遇到的第一个问题。由于没有标准的位置来存储这些文件,因此很容易“丢失”它们 — 我们将在稍后解决这个问题。

接下来,您应该了解两种类型的密钥库:调试 (debug)发布 (release)。调试密钥库应在开发您的应用时使用 — 例如,它可以在手动安装(侧载)应用到本地 Android 设备时使用。但是,调试密钥库不能用于准备发布到 Google Play 或 Amazon 的应用 — 为此,您必须使用发布密钥库。

对于这两种类型,密钥库都由两个方面标识:它存储在其中的文件名和一个别名。由于一个密钥库文件可能存储多个密钥库,因此每个密钥库都由一个别名标识。在大多数情况下,您在文件中只会有一个证书/密钥对,但您仍然需要给它一个别名。

密钥库文件还受到一对密码的保护:一个用于密钥库文件本身,另一个用于文件中的每个密钥库/别名对。虽然这些密码理想情况下应该是唯一的,但大多数开发人员对两者都使用相同的密码。

调试

调试密钥库在某种程度上是标准的。Google 在 Android 开发工具中提供了一个,但为了方便您,Corona 也为您提供了一个调试密钥库。此密钥库位于 CoronaSDK 应用程序文件夹内的标准化文件夹中,您应该在开发 Corona 应用时使用它。

发布

要为您的应用创建 发布 密钥库,您需要从您的操作系统命令行执行一个命令。对于 OS X,这是通过 终端 应用程序完成的,您将看到一个 $ 提示符。对于 Windows,这是通过 命令提示符 完成的,可以通过打开 开始 菜单并搜索 cmd 来访问。在 Windows 中,您将看到类似于 C:\> 的提示符。

如上所述,没有标准的位置来存储密钥库文件,因此创建一个专门用于此目的的文件夹可能会很有用。默认情况下,OS X 终端和 Windows 命令提示符都将在您的“主”目录中启动。在 Mac 上,这会转换为 /Users/yourloginname,而在 Windows 上,这会转换为类似于 C:\Users\yourloginname 的内容。在此主文件夹中,您可以创建一个文件夹来保存您的密钥库。

在 Windows 中,键入

md Keystores

在 OS X 中,键入

mkdir Keystores

完成后,您可以通过键入以下内容访问该文件夹

cd Keystores

进入 Keystores 目录后,您应该发出一个相当复杂的命令。在继续之前,非常重要的一点是要理解这不是“复制粘贴”过程 — 您必须替换特定于您要生成的密钥库的值。

现在,让我们仔细检查并剖析以下行

keytool -genkey -v -keystore mykeystore.keystore -alias aliasname -keyalg RSA -validity 999999

本质上,第一个术语表示此行将执行一个名为 keytool 的程序。对于 OS X,这应该已经安装好了,但 Windows 用户可能需要安装它(请参阅下文)。在此之后,所有以连字符 (-) 开头的部分都表示 keytool 命令的参数。这些选项如下所示,其中以粗体显示的两个选项必须自定义(其他选项可以保持原样)

  • -genkey — 告诉 keytool 生成一个密钥。
  • -v — 告诉 keytool 详细(即告诉您它在做什么)。
  • -keystore保存密钥库的文件名。
  • -alias用于标识密钥库的别名。
  • -keyalg RSA — 这表示使用 RSA 方法生成密钥库。
  • -validity 999999 — 这表示使密钥库有效期为 999,999 天。

对于 keystore 名称,请提供一个有意义的名称。理论上,您应该为每个应用使用一个唯一的发布密钥库,但这不是必需的。例如,名为“SwapIt”的益智游戏可能有一个密钥库名称,例如 swapit.keystore,但更通用的发布密钥库可能只是 release.keystore

对于 alias,请提供一个类似的合理名称,例如 swapit

进行这些更改后,该行应如下所示

keytool -genkey -v -keystore swapit.keystore -alias swapit -keyalg RSA -validity 999999

现在按 回车/Enter 键以执行该命令。然后,系统会提示您输入更多信息,该例程将在命令窗口中如下所示

第一个密码是整个密钥库文件的密码。接下来,系统会要求您输入您的名字和姓氏(名)。“组织单位”提示是针对具有多个部门(如“工程”或“开发”)的公司,此值对于大多数 Corona 开发人员来说并不重要,但您仍然需要提供一个值,例如“开发”。此外,系统会提示您输入您的城市、州/省和国家/地区代码。

此时,您必须键入 来确认信息。最后,如果需要,您可以为单个别名条目提供不同的密码,或者只需按 回车/Enter 即可使用与密钥库文件关联的同一密码。

完成后,您的密钥库文件将位于您运行命令的文件夹中。

安装“keytool”

keytool 实用程序应作为 JDK(Java 开发工具包)的一部分安装。本教程不会讨论 JDK 的实际安装,因此,如果您是此过程的新手,请阅读我们相应的 指南

在 Mac 上,keytool 实用程序将放置在某个位置,以便您只需在终端中键入 keystore 即可运行它。在 Windows 上,情况可能并非如此 — 当您安装 JDK 时,它可能安装在特定于 JDK 版本的文件夹中。例如,在我的 Windows 7 计算机上,它位于

由于 keytool 实用程序位于此处,因此很可能只是更改到此目录并直接键入 keytool ...,但是如果您更新/重新安装 JDK 并且您的密钥库存储在此处,您将丢失所有已创建的密钥库。因此,更好的解决方案是在 keytool 命令之前加上 Java 安装的位置。在执行此操作之前,您必须设置一个名为 JAVA_HOME环境变量,这将提供一个可以使用的快捷方式。如果您不熟悉此任务,请参阅此教程。设置后,您可以将它添加到 keytool 命令的前面,如下所示

%JAVA_HOME\bin\keytool ...

例如,使用上述示例密钥库详细信息,命令变为

%JAVA_HOME\bin\keytool -genkey -v -keystore swapit.keystore -alias swapit -keyalg RSA -validity 999999

构建应用

要使用发布密钥库进行构建,请启动 Corona SDK,加载您的应用程序,然后为 Android 构建(文件构建Android...)。在 密钥库 对话框中,单击 密钥库 下拉菜单旁边的 浏览... 按钮。导航到您保存密钥库文件的位置,然后从对话框中选择它,此时系统会提示您输入密钥库密码。

加载后,您将看到 密钥别名 字段为空。在此下拉列表中选择正确的别名,然后单击 构建 按钮。然后,Corona 会提示您输入别名密码。正确输入后,您将返回到构建屏幕,您可以在其中再次单击 构建 来构建应用程序。幸运的是,只要您使用相同的发布密钥库/别名,就不需要每次都重新输入密码。

密钥哈希和 SHA1 签名

在使用 Facebook 或 Google Play 游戏服务 (GPGS) 等第三方时,有时会要求您从密钥库生成一个值。对于 Google Play 游戏服务,您必须使用发布密钥库来执行此任务。对于 Facebook,您可以使用调试密钥库进行开发/测试,但最终需要为使用发布密钥库签名的应用程序提供信息。

密钥哈希(由 Facebook 使用)和 SHA1 签名(由 GPGS 使用)都是由从大得多的密钥库文件计算出的值组成的短字符串。虽然这两个值不同,但概念相同 — 在密钥库中的值上执行一些标准数学运算,以生成一个不易逆转的唯一值,这有助于确保密钥库没有被黑客篡改。

生成密钥哈希

要生成密钥哈希,您需要再次使用命令行并输入一行看起来很复杂,但实际上只包含三个命令的行

keytool -exportcert -alias yourkeyalias -keystore yourkeystore.keystore | openssl sha1 -binary | openssl base64

单独采用的三个命令如下

  • keytool -exportcert -alias yourkeyalias -keystore yourkeystore.keystore
  • openssl sha1 -binary — 使用 SHA1 方法计算签名,输出为二进制文件。
  • openssl base64 — 以 Base64 格式输出数据。

如您所见,这三个命令由管道 (|) 字符分隔。第一个命令运行并输出其结果,然后结果又成为第二个命令的输入。然后,第二个命令输出其结果,该结果成为第三个命令的输入。这可能会导致潜在问题,因为如果较早的命令中出现哪怕是轻微的问题,错误也会传递到下一个命令,而不是预期的数据。例如,如果您输错了密码,此命令系列不会通知您,而是基于“无效密码”的输入生成 SHA1 字符串。

无论如何,如本教程前面所述,这不是一个复制粘贴命令 — 您必须将 -alias-keystore 调整为您的特定值。当使用上面创建的密钥库运行此命令时,结果为

tZRNBKXmYKOa22HvFl57za4gvU0=

注意末尾的 = 符号 — 这表示字符串的结尾,这一点很重要

生成 SHA1 签名

相比之下,GPGS 需要 SHA1 输出的文本表示形式。幸运的是,keytool 实用程序可以在没有任何其他命令的情况下输出此内容

keytool -exportcert -alias swapit -keystore swapit.keystore -list -v

输入密码后,输出将如下所示

在此输出中,SHA1: 行是您在设置应用时需要提供给 GPGS 的十六进制数字字符串,以及您在 Google 上设置应用时需要提供的值。 或者,如果您需要将 SHA1 签名格式化为字符串而不是以冒号分隔的十六进制字符串,请使用此命令

keytool -exportcert -alias swapit -keystore swapit.keystore | openssl sha1 -hex

结论

希望本教程能够帮助您更好地理解 Android 签名流程。 记住这些命令行并熟悉参数,Android 签名很快就会成为一项简单的任务。

罗布·米拉科
[email protected]

罗布是 Corona Labs 的开发者关系经理。 除了热衷于帮助其他开发者使用 Corona 制作出色的游戏外,他还喜欢在业余时间制作游戏。 自 1979 年以来,罗布一直在个人电脑到大型机上编写游戏代码。 他在游戏行业拥有超过 16 年的专业经验。

23 条评论
  • 安德烈亚斯
    发布于 16:43,8 月 26 日

    嗨,罗布,

    我已经有一段时间没有做这些步骤了,但我将在几周后再次做这些步骤 – 所以非常感谢你对所有必须做的事情进行了很好的总结。

    最好,
    安德烈亚斯

  • undecode
    发布于 20:10,8 月 26 日

    罗布,精彩的贡献。

    我记得当时在这方面遇到过问题,直到我找到了一份创建密钥库以发布我的应用程序的分步指南。 这真的很完整,将帮助新的开发者,此外,关于密钥哈希的附加信息在我使用 GPGS 时 Google 不会自动识别应用程序中的密钥哈希的情况下也会对我有帮助。

    谢谢

  • Mo
    发布于 21:40,8 月 26 日

    完美! 谢谢罗布 🙂

    MO

  • Mo
    发布于 21:44,8 月 26 日

    我说完美的原因不仅仅是因为这是一个很棒的教程,还因为我一直害怕接触 GPGS 部分(用于排行榜),有了这个,我想我可以尝试在我的 Android 应用中添加排行榜! 仍然感到害怕,但这解释了很多关于 SHA1 的事情(发明这个东西的人 🙂

    再次感谢。

    Mo

  • 丹尼尔
    发布于 04:38,8 月 27 日

    我从来不需要提供 SHA1 才能让我的 Android 应用的 GPGS 排行榜正常工作,我没有被要求提供它,所以我很困惑。

    • 罗布·米拉科
      发布于 19:09,8 月 27 日

      如果您在设置 GPGS 应用程序之前以 Beta 版或 Alpha 版模式将您的应用上传到 Google Play,那么它会从您上传的 APK 中获取 SHA1 签名(这是新的,以前不是这样)。 但是您可以在将 .apk 上传到 Google Play 之前设置 GPGS 应用程序。 在这种情况下,您必须输入应用程序发布密钥库的 SHA1 签名。

      • 丹尼尔
        发布于 09:11,8 月 28 日

        啊,谢谢罗布澄清了这一点! *呼*

  • Mo
    发布于 22:27,8 月 27 日

    嗨,罗布,

    你是说,如果我们的应用已经在 Google Play 上线并且想要在其中添加排行榜 (GPGS),我们就不需要处理所有关于 SHA1 的事情了吗?

    那太酷了! 我坦白说害怕经历这些步骤。 感谢上帝,感谢你的教程!

    谢谢,

    Mo

    • 罗布·米拉科
      发布于 15:33,8 月 28 日

      您仍然必须完成所有设置步骤,但是如果您先上传了 .apk,然后“链接到应用”,它会为您获取 SHA1 签名,这样至少可以省去您从命令行生成它的痛苦。

      罗布

  • Mo
    发布于 23:57,8 月 29 日

    谢谢罗布!

    Mo

  • 基芬·艾尔斯
    发布于 20:45,10 月 9 日

    在 GameThrive 上设置您的 Android 应用时,会要求提供 SHA1。 本教程是/是一个救命稻草! 谢谢罗布!

  • 塔伦
    发布于 22:32,3 月 28 日

    嗨,罗布,

    这对我来说是一个非常有用的教程,至少可以开始创建一个密钥库的过程。 但是我被困在一个地方。 它显示一个错误
    “-genkey” 未被识别为内部或外部命令,
    可操作的程序或批处理文件。

    请帮忙

    • 罗布·米拉科
      发布于 20:48,3 月 29 日

      这听起来像您在第二行上运行 -genkey。 该命令必须在一行上串在一起。

  • ssiri
    发布于 14:01,4 月 2 日

    精彩的解释。谢谢 🙂

  • 米林德
    发布于 21:35,9 月 8 日

    感谢您非常清晰和简洁的解释。 有一件事,我建议在您将第一个应用程序放入 PlayStore 之前尽可能提高密钥库的默认强度,因为您之后无法更改它。

    请参阅 https://commonsware.com/blog/2013/09/09/psa-think-about-stronger-app-signing-keys.html

    因此,在 keytool 命令中添加 -keysize 4096 将会很好。

  • 克里提卡·马赫什瓦里
    发布于 04:32,3 月 11 日


    我有一个第三方应用程序,我没有任何 SHA1 指纹。 因此,当上传时,它会说指纹不匹配。上传失败
    您上传的 APK 使用与您之前的 APK 不同的证书签名。 您必须使用相同的证书。 您现有的 APK 使用指纹的证书签名。

    我该怎么办? 我有很多下载量。

    • 罗布·米拉科
      发布于 19:44,3 月 11 日

      您必须在更新时使用您第一次提交应用程序时使用的相同密钥库。 如果您丢失了密钥库并创建了新的密钥库,那么您唯一的选择是创建一个新的应用程序。

  • 大卫
    发布于 07:22,3 月 17 日

    如何将密钥库中的证书创建为 p12 或 pfx 文件?

    • 罗布·米拉科
      发布于 16:53,3 月 17 日

      您可能必须去 Google 上查找。 我们的密钥库没有什么特别之处。 它们是标准的 Android 密钥库。 如果可以完成,那么应该有很多教程。

  • 乌塞夫
    发布于 16:27,3 月 31 日

    天啊,为什么你让它变得如此困难,而不用像 Eclipse 或 Android Studio 签名那样?

    • 罗布·米拉科
      发布于 06:40,4 月 1 日

      我认为我们的签名非常简单。 您点击构建对话框。 确保您指向密钥库并且您的应用程序在几乎不需要任何努力的情况下被签名。 获取密钥库不是基于 GUI 的,但没有任何东西可以阻止您首先使用 Eclipse 或 Android Studio 创建密钥库。 还要考虑您必须安装非常大的 IDE,其中无论是 Eclipse 还是 Android Studio,目的都只是生成密钥库。 Corona SDK 不需要这些 IDE 就能工作。 一个作为构建 Corona SDK 应用程序所需的 Android 工具的一部分安装的简单命令行命令已经在那里,随时可以使用。 现在,如果 Corona SDK 需要 Eclipse 或 Android Studio 作为其开发工作流程的一部分,那将是另一回事。

  • 马亨德
    发布于 07:02,7 月 14 日

    但是在添加密钥时间完成所有这些步骤后,它们显示“您的 Android 签名密钥已锁定”。
    我如何解决这个问题

    • 罗布·米拉科
      发布于 11:09,7 月 14 日

      我查看了该错误,它似乎是一个 PhoneGap 错误。 我从来没有见过 Corona Labs 项目产生该错误。 如果您正在使用 Corona SDK,我建议您在我们的社区论坛 https://forums.coronalabs.com 中提问。 如果您没有使用 Corona SDK 或我们的其他产品之一,我不知道我们对帮助您解决此问题有何好处。 如果您不知道 Corona SDK 是关于什么的,我邀请您访问 并查看我们出色的跨平台开发工具。