Visual Studio 的 AndroidApkSigner 在密钥库中找不到密钥
Visual Studio's AndroidApkSigner does not find key in keystore
我在 Visual Studio 中创建 APK 时遇到此错误:
Failed to load signer "signer #1": C:\...\googleplay.keystore entry "googleplay" does not contain a key
我是一名长期 ASP.NET 的开发人员,熟悉 Visual Studio 但这是我的第一个 Xamarin 项目。 (我没有使用 Android Studio。)我正在尝试将 Android 构建部署到 Google Play。我从未将 APK 上传到 Google Play,所以我无法使用 Visual Studio 的自动部署;我必须先按照 Google 和 Microsoft 的说明执行手动部署。
我是 运行ning Visual Studio 2017 15.7.5(最新),JDK 1.8。我的项目正在使用 NETStandard.Library 2.0.3、Xamarin.Forms 3.1.0 和 Microsoft.EntityFrameworkCore 2.1.1.
这个问题与 this question that has no answers 类似,但我从 Visual Studio 中得到错误。如果这是重复的,我深表歉意,但我无法添加有关该问题的更多详细信息。
我正在使用 Google Play App Signing。我通过 Google Play 创建了一个密钥。我下载了 .der 格式的证书。我使用 keytool(来自 c:\Program Files\Java\jdk1.8.0_172\bin)通过以下命令将 .der 文件转换为 .keystore:
keytool -importcert -alias googleplay -file "C:\...\deployment_cert.der"
我已经重新运行这个实用程序几次更改选项,我想可能是 keytool 提示的密码中的别名或特殊字符区分大小写有问题。在本例中,别名全是字母,全是小写,密码是全小写的字母数字。 keytool 要求信任此证书,然后我按 "y"。
这会生成一个名为 .keystore
的文件。我将其重命名为 googleplay.keystore
并将其移动到更合适的位置。
我可以通过 运行 执行以下命令仔细检查 googleplay
别名是否存在于密钥库文件中:
C:\Program Files\Java\jdk1.8.0_172\bin>keytool -v -list -keystore "C:\...\googleplay.keystore" -alias googleplay
Enter keystore password:
Alias name: googleplay
Creation date: Jul 23, 2018
Entry type: trustedCertEntry
Owner: CN=Android, OU=Android, O=Google Inc., L=Mountain View, ST=California, C=US
Issuer: CN=Android, OU=Android, O=Google Inc., L=Mountain View, ST=California, C=US
Serial number: e8************************************8a
Valid from: Thu Jul 19 14:18:56 EDT 2018 until: Sun Jul 19 14:18:56 EDT 2048
Certificate fingerprints:
MD5: 0D:**:**:**:**:**:**:**:**:**:**:**:**:**:**:C8
SHA1: 11:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:CD
SHA256: D0:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:74
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 4096-bit RSA key
Version: 3
Extensions:
#1: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
CA:true
PathLen:2147483647
]
"googleplay" 别名绝对存在!证书指纹与 Google 给我的密钥相匹配(编辑)。
在Visual Studio中,我将解决方案配置设置为发布模式,我清理了我的整个解决方案(成功),重建了我的整个解决方案(成功),然后右键单击我的Android项目并点击 Archive...
每 these instructions。
作为旁注,微软的那篇文章非常令人沮丧,因为它没有提到签名或这个问题,而且他们的 articles on signing 与 Google Play 的运作方式不符,并且似乎假设你已将正确的 APK 上传到 Google 已经播放(绕过先有鸡还是先有蛋的第 22 条军规)。
起初我得到的只是The archiving process has failed. Please see the Errors section for more details.
错误列表面板是空的。输出面板只显示 "java.exe" exited with code 2.
我去了 Tools -> Options -> Projects and Solutions -> Build and Run
并将 MSBuild project build output verbosity
从 Minimal
更改为 Diagnostic
并重复了最后几个步骤(清理、重建、归档) .现在,输出面板(略有编辑)显示:
Using "AndroidApkSigner" task from assembly "C:\...\MSBuild\Xamarin\Android\Xamarin.Android.Build.Tasks.dll".
Task "AndroidApkSigner"
AndroidApkSigner:
ApkSignerJar: C:\Program Files (x86)\Android\android-sdk\build-tools.0.3\lib\apksigner.jar
ApkToSign: bin\Release\com.mycompany.myproject.apk
ManifestFile: obj\Release\android\AndroidManifest.xml
AdditionalArguments:
C:\Program Files\Java\jdk1.8.0_172\bin\java.exe -jar "C:\Program Files (x86)\Android\android-sdk\build-tools.0.3\lib\apksigner.jar" sign --ks "C:\...\googleplay.keystore" --ks-pass pass:******** --ks-key-alias googleplay --key-pass pass:******** --min-sdk-version 19 --max-sdk-version 27 C:\...\myproject.Android\bin\Release\com.mycompany.myproject.apk
Failed to load signer "signer #1": C:\...\googleplay.keystore entry "googleplay" does not contain a key
"java.exe" exited with code 2.
Done executing task "AndroidApkSigner" -- FAILED.
Done building target "_Sign" in project "myproject.Android.csproj" -- FAILED.
Done building project "myproject.Android.csproj" -- FAILED.
Build FAILED.
从上面的输出中,您可以看到我的项目 属性 的 Android 包签名选项卡中的(编辑)值是什么。通过反复试验,我发现 Keystore Password、Alias 和 Alias Password 都是必需的。我将密钥库密码和别名密码设置为相同,因为只有一个密码与此密钥库关联。如上所述,密码是小写字母数字(根据另一个 SO 问题的建议没有特殊字符)。
为什么当 keytool 可以毫无问题地找到密钥时,AndroidApkSigner 无法在提供的别名的密钥库中找到密钥?
而且,我不是唯一遇到这个问题的人吗?从 Visual Studio 部署到 Google Play 应该是一个相当常见的工作流程,但我没有找到其他人(除了 this other unanswered SO question)遇到这个问题。我做错了什么?
您遗漏的重要事实:
Google Play 永远不会给你一个用于签名的密钥。它只会给你证书来验证。
我将从您可能知道的基础知识开始。在 public 密钥密码学中,有一个私钥和一个 public 密钥。只有签名的人才有私钥。否则任何人都可以签名。 public 密钥任何人都可以拥有。他们可以用它来检查签名是否有效。
upload_cert.der 下载 仅包含 public 密钥。之所以Google Play让你下载验证。您可以离线验证您的签名是否符合 Play 商店的预期。您可能永远不需要这样做。
为什么 Google 不给你签名密钥?
Google Play 不向您提供上传证书的私钥有两个原因。
- Google 没有您上传密钥的私有部分!当您注册 Google Play 应用签名时,您创建了上传密钥的私钥部分。你从来没有把它给 Google。 Google 只有 public 关键部分。
- 如果Google确实给了你,那钥匙就没有价值了。上传密钥的全部意义在于,即使黑客侵入了您的 Play 管理中心帐户,他们仍然无法上传您应用的新版本。他们也需要上传密钥。上传密钥意味着 Google Play 知道该应用来自您。如果他们让您从您的帐户下载签名密钥,那么黑客也可以下载它。那就一文不值了
如何获取签名所需的上传密钥?
那么现在您可能遇到的问题是 "how do I get the public key I need for signing?"。答案是"you create it"。当您第一次上传您的 APK 时,该 APK 是用密钥签名的(Google 坚持这样做)。它可能存储在您的 Visual Studio 中。该密钥将成为您的上传密钥。找到你保存它的地方。
万一丢了怎么办?
现在您可能不知道您最初使用的密钥在哪里。这就是 Google Play App Signing 的伟大之处。如果您自己签署您的应用程序并丢失了签名密钥,您将被卡住,您必须创建一个新的应用程序。但是使用 Google Play App Signing,您可以联系 Play Console 支持,他们可以帮助您。 The process is on the help page.
查看标题为 "Create a new upload key" 的部分。请注意,第 1 步是 您创建密钥 。 Google 仍然没有。
我找到了问题的答案。 documentation on the Android Developer site 不适用于 Visual Studio。 Xamarin自带的ApkSigner不知道拿它干什么。相反,使用它来创建您自己的发布密钥:
keytool -v -list -keystore c:\temp\myreleasekey.keystore -alias myalias -storetype pkcs12
注意最后的-storetype pkcs12
。此命令也被修改为 (1) 将文件写入 Program Files 之外的某个地方,(2) 使用 Visual Studio 喜欢的 .keystore
扩展名,以及 (3) 避免别名中的特殊字符,[=41] =] 不喜欢,从我读过的。 (密码中也要避免使用特殊字符。)
注意,keytool
位于 c:\Program Files\Java\jdk[version]\bin
。
线索
当我按照 the documentation 上的说明进行操作时,我收到了来自 keytool
的警告:
Warning:
The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using keytool -importkeystore -srckeystore c:\temp\myreleasekey.jks -destkeystore c:\temp\myreleasekey.jks -deststoretype pkcs12
.
我在验证密钥是否正确时也收到此警告:
keytool -v -list -keystore c:\temp\myreleasekey.jks -alias myalias
如果您已有密钥并需要转换它,请按照警告中的命令进行操作。
谢谢:
感谢 Nick 解释了签名和区分所有密钥的原因。
乔恩,谢谢你指导我如何创建我自己的私钥。
禁用选项“使用以下密钥库详细信息签署 .APK 文件。”
你会得到这个选项
右键单击 android 项目 select 属性 转到 Android 包签名.
对我来说,问题与 packaging/signing 屏幕有关。我最终从签名屏幕上删除了所有内容,然后构建了存档。
构建完成后,我点击存档并点击分发。此时它要求我提供密钥库和密码。我输入了它们并签署了apk。我用那个来旁加载应用程序,效果很好。
我在 Visual Studio 中创建 APK 时遇到此错误:
Failed to load signer "signer #1": C:\...\googleplay.keystore entry "googleplay" does not contain a key
我是一名长期 ASP.NET 的开发人员,熟悉 Visual Studio 但这是我的第一个 Xamarin 项目。 (我没有使用 Android Studio。)我正在尝试将 Android 构建部署到 Google Play。我从未将 APK 上传到 Google Play,所以我无法使用 Visual Studio 的自动部署;我必须先按照 Google 和 Microsoft 的说明执行手动部署。
我是 运行ning Visual Studio 2017 15.7.5(最新),JDK 1.8。我的项目正在使用 NETStandard.Library 2.0.3、Xamarin.Forms 3.1.0 和 Microsoft.EntityFrameworkCore 2.1.1.
这个问题与 this question that has no answers 类似,但我从 Visual Studio 中得到错误。如果这是重复的,我深表歉意,但我无法添加有关该问题的更多详细信息。
我正在使用 Google Play App Signing。我通过 Google Play 创建了一个密钥。我下载了 .der 格式的证书。我使用 keytool(来自 c:\Program Files\Java\jdk1.8.0_172\bin)通过以下命令将 .der 文件转换为 .keystore:
keytool -importcert -alias googleplay -file "C:\...\deployment_cert.der"
我已经重新运行这个实用程序几次更改选项,我想可能是 keytool 提示的密码中的别名或特殊字符区分大小写有问题。在本例中,别名全是字母,全是小写,密码是全小写的字母数字。 keytool 要求信任此证书,然后我按 "y"。
这会生成一个名为 .keystore
的文件。我将其重命名为 googleplay.keystore
并将其移动到更合适的位置。
我可以通过 运行 执行以下命令仔细检查 googleplay
别名是否存在于密钥库文件中:
C:\Program Files\Java\jdk1.8.0_172\bin>keytool -v -list -keystore "C:\...\googleplay.keystore" -alias googleplay
Enter keystore password:
Alias name: googleplay
Creation date: Jul 23, 2018
Entry type: trustedCertEntry
Owner: CN=Android, OU=Android, O=Google Inc., L=Mountain View, ST=California, C=US
Issuer: CN=Android, OU=Android, O=Google Inc., L=Mountain View, ST=California, C=US
Serial number: e8************************************8a
Valid from: Thu Jul 19 14:18:56 EDT 2018 until: Sun Jul 19 14:18:56 EDT 2048
Certificate fingerprints:
MD5: 0D:**:**:**:**:**:**:**:**:**:**:**:**:**:**:C8
SHA1: 11:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:CD
SHA256: D0:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:74
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 4096-bit RSA key
Version: 3
Extensions:
#1: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
CA:true
PathLen:2147483647
]
"googleplay" 别名绝对存在!证书指纹与 Google 给我的密钥相匹配(编辑)。
在Visual Studio中,我将解决方案配置设置为发布模式,我清理了我的整个解决方案(成功),重建了我的整个解决方案(成功),然后右键单击我的Android项目并点击 Archive...
每 these instructions。
作为旁注,微软的那篇文章非常令人沮丧,因为它没有提到签名或这个问题,而且他们的 articles on signing 与 Google Play 的运作方式不符,并且似乎假设你已将正确的 APK 上传到 Google 已经播放(绕过先有鸡还是先有蛋的第 22 条军规)。
起初我得到的只是The archiving process has failed. Please see the Errors section for more details.
错误列表面板是空的。输出面板只显示 "java.exe" exited with code 2.
我去了 Tools -> Options -> Projects and Solutions -> Build and Run
并将 MSBuild project build output verbosity
从 Minimal
更改为 Diagnostic
并重复了最后几个步骤(清理、重建、归档) .现在,输出面板(略有编辑)显示:
Using "AndroidApkSigner" task from assembly "C:\...\MSBuild\Xamarin\Android\Xamarin.Android.Build.Tasks.dll".
Task "AndroidApkSigner"
AndroidApkSigner:
ApkSignerJar: C:\Program Files (x86)\Android\android-sdk\build-tools.0.3\lib\apksigner.jar
ApkToSign: bin\Release\com.mycompany.myproject.apk
ManifestFile: obj\Release\android\AndroidManifest.xml
AdditionalArguments:
C:\Program Files\Java\jdk1.8.0_172\bin\java.exe -jar "C:\Program Files (x86)\Android\android-sdk\build-tools.0.3\lib\apksigner.jar" sign --ks "C:\...\googleplay.keystore" --ks-pass pass:******** --ks-key-alias googleplay --key-pass pass:******** --min-sdk-version 19 --max-sdk-version 27 C:\...\myproject.Android\bin\Release\com.mycompany.myproject.apk
Failed to load signer "signer #1": C:\...\googleplay.keystore entry "googleplay" does not contain a key
"java.exe" exited with code 2.
Done executing task "AndroidApkSigner" -- FAILED.
Done building target "_Sign" in project "myproject.Android.csproj" -- FAILED.
Done building project "myproject.Android.csproj" -- FAILED.
Build FAILED.
从上面的输出中,您可以看到我的项目 属性 的 Android 包签名选项卡中的(编辑)值是什么。通过反复试验,我发现 Keystore Password、Alias 和 Alias Password 都是必需的。我将密钥库密码和别名密码设置为相同,因为只有一个密码与此密钥库关联。如上所述,密码是小写字母数字(根据另一个 SO 问题的建议没有特殊字符)。
为什么当 keytool 可以毫无问题地找到密钥时,AndroidApkSigner 无法在提供的别名的密钥库中找到密钥?
而且,我不是唯一遇到这个问题的人吗?从 Visual Studio 部署到 Google Play 应该是一个相当常见的工作流程,但我没有找到其他人(除了 this other unanswered SO question)遇到这个问题。我做错了什么?
您遗漏的重要事实:
Google Play 永远不会给你一个用于签名的密钥。它只会给你证书来验证。
我将从您可能知道的基础知识开始。在 public 密钥密码学中,有一个私钥和一个 public 密钥。只有签名的人才有私钥。否则任何人都可以签名。 public 密钥任何人都可以拥有。他们可以用它来检查签名是否有效。
upload_cert.der 下载 仅包含 public 密钥。之所以Google Play让你下载验证。您可以离线验证您的签名是否符合 Play 商店的预期。您可能永远不需要这样做。
为什么 Google 不给你签名密钥?
Google Play 不向您提供上传证书的私钥有两个原因。
- Google 没有您上传密钥的私有部分!当您注册 Google Play 应用签名时,您创建了上传密钥的私钥部分。你从来没有把它给 Google。 Google 只有 public 关键部分。
- 如果Google确实给了你,那钥匙就没有价值了。上传密钥的全部意义在于,即使黑客侵入了您的 Play 管理中心帐户,他们仍然无法上传您应用的新版本。他们也需要上传密钥。上传密钥意味着 Google Play 知道该应用来自您。如果他们让您从您的帐户下载签名密钥,那么黑客也可以下载它。那就一文不值了
如何获取签名所需的上传密钥?
那么现在您可能遇到的问题是 "how do I get the public key I need for signing?"。答案是"you create it"。当您第一次上传您的 APK 时,该 APK 是用密钥签名的(Google 坚持这样做)。它可能存储在您的 Visual Studio 中。该密钥将成为您的上传密钥。找到你保存它的地方。
万一丢了怎么办?
现在您可能不知道您最初使用的密钥在哪里。这就是 Google Play App Signing 的伟大之处。如果您自己签署您的应用程序并丢失了签名密钥,您将被卡住,您必须创建一个新的应用程序。但是使用 Google Play App Signing,您可以联系 Play Console 支持,他们可以帮助您。 The process is on the help page.
查看标题为 "Create a new upload key" 的部分。请注意,第 1 步是 您创建密钥 。 Google 仍然没有。
我找到了问题的答案。 documentation on the Android Developer site 不适用于 Visual Studio。 Xamarin自带的ApkSigner不知道拿它干什么。相反,使用它来创建您自己的发布密钥:
keytool -v -list -keystore c:\temp\myreleasekey.keystore -alias myalias -storetype pkcs12
注意最后的-storetype pkcs12
。此命令也被修改为 (1) 将文件写入 Program Files 之外的某个地方,(2) 使用 Visual Studio 喜欢的 .keystore
扩展名,以及 (3) 避免别名中的特殊字符,[=41] =] 不喜欢,从我读过的。 (密码中也要避免使用特殊字符。)
注意,keytool
位于 c:\Program Files\Java\jdk[version]\bin
。
线索
当我按照 the documentation 上的说明进行操作时,我收到了来自 keytool
的警告:
Warning: The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using
keytool -importkeystore -srckeystore c:\temp\myreleasekey.jks -destkeystore c:\temp\myreleasekey.jks -deststoretype pkcs12
.
我在验证密钥是否正确时也收到此警告:
keytool -v -list -keystore c:\temp\myreleasekey.jks -alias myalias
如果您已有密钥并需要转换它,请按照警告中的命令进行操作。
谢谢:
感谢 Nick 解释了签名和区分所有密钥的原因。
乔恩,谢谢你指导我如何创建我自己的私钥。
禁用选项“使用以下密钥库详细信息签署 .APK 文件。”
你会得到这个选项
右键单击 android 项目 select 属性 转到 Android 包签名.
对我来说,问题与 packaging/signing 屏幕有关。我最终从签名屏幕上删除了所有内容,然后构建了存档。
构建完成后,我点击存档并点击分发。此时它要求我提供密钥库和密码。我输入了它们并签署了apk。我用那个来旁加载应用程序,效果很好。