Visual Studio的AndroidApkSigner在密钥库中找不到密钥

时间:2018-07-23 14:33:40

标签: visual-studio xamarin.android google-play keytool apksigner

在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的说明执行手动部署。

我正在使用JDK 1.8运行Visual Studio 2017 15.7.5(最新)。我的项目使用的是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应用签名。我已经通过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... {3}}。

作为一个旁注,该Microsoft文章非常令人沮丧,因为它没有提及签名或此问题,并且它们在these instructions上的articles与Google Play的运作方式不符,似乎以为您已将正确的APK上传到Google Play(绕过了Chicken-or-Egg Catch-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 verbosityMinimal更改为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\27.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\27.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 Package Signing选项卡中看到(已编辑)值。通过反复试验,我发现密钥库密码,别名和别名密码都是必需的。我将“密钥库密码”和“别名密码”设置为相同,因为与此密钥库关联的密码只有一个。如上所述,密码是低位字母数字(根据另一个SO问题的建议,无特殊字符)。

为什么当keytool毫无问题地找到密钥时,AndroidApkSigner为什么无法在密钥库中找到所提供别名的密钥?

而且,我不能成为唯一遇到此问题的人吗?从Visual Studio部署到Google Play应该是一个相当普遍的工作流程,但是我找不到遇到此问题的其他人(除signing以外)。我在做什么错了?

4 个答案:

答案 0 :(得分:1)

您缺少的重要事实:

Google Play永远不会给您提供用于签名的密钥 。它只会向您提供证书进行验证。

我将从您可能了解的基础知识开始。在公用密钥加密中,有一个专用密钥和一个公用密钥。只有签名的人才能拥有私钥。否则任何人都可以签名。任何人都可以拥有的公钥。他们可以使用它来检查签名是否有效。

upload_cert.der下载 仅包含公钥 。 Google Play允许您下载进行验证的原因。您可以离线验证您的签名是否符合Play商店的期望。您可能永远不需要这样做。

Google为什么不给您签名密钥?

出于两个原因,Google Play没有为您提供上传证书的私钥。

  1. Google没有您的上传密钥的私有部分!注册Google Play应用签名后,您创建了上传密钥的私钥部分。您从未将其提供给Google。 Google拥有的全部都是公钥部分。
  2. 如果Google确实把它给了您,则密钥将没有价值。上传密钥的全部意义在于,即使黑客闯入了您的Play控制台帐户,他们仍然无法上传您的应用的新版本。他们也将需要上传密钥。上载密钥表示Google Play知道该应用来自您。如果他们允许您从您的帐户下载签名密钥,那么黑客也可以下载它。那将毫无价值。

如何获取签名所需的上传密钥?

因此,现在您可能遇到的问题是“如何获取签名所需的公共密钥?”。答案是“您创建它”。首次上传APK时,该APK是用密钥签名的(Google坚持要求使用该密钥)。它可能存储在您的Visual Studio中。该密钥将成为您的上传密钥。找到保存它的地方。

如果我丢了怎么办?

现在,您可能在一个不知道最初使用密钥在哪里的地方。这对Google Play应用签名非常有用。如果您自己对应用程序进行签名,并且丢失了签名密钥,那么您将不得不创建一个新的应用程序。但是,通过Google Play应用签名,您可以联系Play控制台支持,他们可以为您提供帮助。 The process is on the help page

请查看标题为“创建新的上传密钥”的部分。请注意,步骤1是 您创建密钥 。 Google仍然没有它。

答案 1 :(得分:1)

我已经找到问题的答案。 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)将文件写入程序文件之外的其他位置;(2)使用Visual Studio喜欢的.keystore扩展名;(3)避免使用别名(Visual Studio不喜欢)中的特殊字符,从我读过的书中(也请避免在密码中使用特殊字符。)

请注意,keytool位于c:\Program Files\Java\jdk[version]\bin中。

线索

按照the documentation上的说明进行操作时,我收到了keytool的警告:

  

警告:   JKS密钥库使用专有格式。建议使用keytool -importkeystore -srckeystore c:\temp\myreleasekey.jks -destkeystore c:\temp\myreleasekey.jks -deststoretype pkcs12迁移到行业标准格式PKCS12。

验证密钥正确时,我也收到此警告:

keytool -v -list -keystore c:\temp\myreleasekey.jks -alias myalias

如果您有一个现有密钥并需要转换,请按照警告中的命令进行操作。

谢谢:

我要感谢Nick解释了在所有键之间进行签名和区分的原因。

乔恩(Jon),谢谢您指出如何创建自己的私钥。

答案 2 :(得分:0)

禁用选项“使用以下密钥库详细信息签署 .APK 文件。

你会得到这个选项

右键单击 android 项目选择 properties 转到 Android Package Signing

Example

答案 3 :(得分:0)

对我来说,这个问题与包装/签名屏幕有关。我最终从签名屏幕中删除了所有内容,然后构建了存档。

构建完成后,我点击存档并点击分发。此时它要求我提供密钥库和密码。我输入了它们并签署了apk。我用它来加载应用程序,效果很好。