AndroidApkSigner Visual Studio не находит ключ в хранилище ключей

Я получаю эту ошибку при создании APK в Visual Studio:

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.

Я использую Visual Studio 2017 15.7.5 (последняя версия) с JDK 1.8. В моем проекте используются NETStandard.Library 2.0.3, Xamarin.Forms 3.1.0 и Microsoft.EntityFrameworkCore 2.1.1.

Этот вопрос похож на этот вопрос, на который нет ответов, но я получаю сообщение об ошибке из 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... для эти инструкции.

В качестве примечания: эта статья Microsoft чрезвычайно разочаровывает, потому что в ней не упоминается подписание или эта проблема, а их статьи на подписание не соответствует тому, как работает Google Play, и, похоже, предполагает, что у вас уже есть правильный APK, загруженный в Google Play (в обход Уловка курицы или яйца-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\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).

Почему AndroidApkSigner не может найти ключ в хранилище ключей для предоставленного псевдонима, когда keytool находит ключ без проблем?

И я не могу быть единственным с этой проблемой? Развертывание из Visual Studio в Google Play должно быть довольно распространенным рабочим процессом, но я не нахожу никого (кроме этот другой вопрос без ответа SO), у кого возникла бы эта проблема. Что я делаю неправильно?

поскольку 15.6, подпись нарушена. Я даже больше не могу развернуть свое приложение xamarin на физическом устройстве для отладки.

magicandre1981 23.07.2018 17:01

Как вы создаете хранилище ключей / ключ своего приложения перед загрузкой в ​​Google Play? Если это новое приложение, вам не нужно ничего делать, кроме как загрузить Release APK. Когда вы включаете программу подписи приложений, ключ, используемый для Release APK, станет ключом загрузки, и Google Play затем сгенерирует новый ключ для подписи APK, прежде чем он попадет к пользователям.

Jon Douglas 23.07.2018 19:01

@JonDouglas, первый созданный мной APK не был подписан. VS создал его очень хорошо, но когда я загрузил его в Google, он сказал, что APK не был выровнен по zip, что привело меня к zipalign.exe. Я загрузил это в Google, и там было сказано, что APK необходимо подписать, что соответствует эта страница, в котором говорится, что «требуется подписание приложения в Google Play». Что подводит меня сюда. Я выбрал подписку на приложение Google Play, которая дает мне сертификат (файл .der, описанный в вопросе). Должен ли я делать что-то другое?

Eric 23.07.2018 19:30

У вас должна быть возможность загрузить APK-файл выпуска, подписанный с помощью локального хранилища ключей. Ключ в этом магазине станет ключом загрузки. Затем он сгенерирует новый ключ загрузки, замененный исходным ключом для любых будущих обновлений APK.

Jon Douglas 23.07.2018 20:07

Хорошо, я только что создал свой собственный .keystore, независимый от Google Play. keytool -genkeypair -v -keystore mykey.keystore -alias eric -keyalg RSA -keysize 2048 -validity 10000. Я обновил свой проект, чтобы использовать это хранилище ключей. Очистите, перестройте, заархивируйте, и я получаю аналогичную ошибку, описанную выше: Failed to load signer "signer #1", за исключением того, что на этот раз в следующей строке написано: java.io.IOException: Failed to obtain key with alias "eric" from C:\...\mykey.keystore. Wrong password?. Как и в предыдущем вопросе, я могу проверить наличие псевдонима «eric» и правильность пароля.

Eric 23.07.2018 21:08
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
6
5
5 848
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Важный факт, который вам не хватает:

Google Play никогда не дает вам ключ, который вы используете для подписи вещей. Он дает вам только сертификаты для проверки.

Я начну с основ, которые вы, вероятно, знаете. В криптографии с открытым ключом есть закрытый ключ и открытый ключ. Только тот, кто подписывает, имеет закрытый ключ. В противном случае любой мог подписать. Открытый ключ может получить каждый. Они могут использовать его, чтобы проверить действительность подписи.

Загрузите файл upload_cert.der содержит только открытый ключ. Причина, по которой Google Play позволяет вам скачать его для проверки. Вы можете офлайн проверить, соответствуют ли ваши подписи тому, что ожидает Play Store. Вероятно, вам никогда не понадобится это делать.

Почему Google не дает вам ключ подписи?

Google Play не предоставляет вам закрытый ключ для сертификата загрузки по двум причинам.

  1. У Google нет частной части вашего ключа загрузки! Вы создали часть закрытого ключа ключа загрузки при регистрации в программе подписания приложений Google Play. Вы никогда не давали это Google. Все, что есть у Google, - это часть открытого ключа.
  2. Если бы Google дал его вам, ключ не имел бы никакого значения. Весь смысл ключа загрузки заключается в том, что даже если хакер взломает вашу учетную запись Play Console, он все равно не сможет загрузить новую версию вашего приложения. Им также понадобится ключ загрузки. Ключ загрузки означает, что Google Play знает, что приложение пришло от вас. Если они позволят вам загрузить ключ подписи из вашей учетной записи, то хакер может просто загрузить его. Тогда это было бы бесполезно.

Как мне получить ключ загрузки, который мне нужен для подписи?

Итак, теперь у вас, вероятно, возникает вопрос: «Как мне получить открытый ключ, который мне нужен для подписи?». Ответ - «вы создаете это». Когда вы впервые загружаете APK, этот APK был подписан ключом (на этом настаивает Google). Вероятно, он хранился в вашей Visual Studio. Этот ключ становится вашим ключом загрузки. Найдите, где вы его хранили.

Что, если я его потеряю?

Теперь вы можете оказаться в таком месте, где не знаете, где находится ключ, который вы использовали изначально. Это отличное свойство подписи приложений Google Play. Если бы вы подписывали свое приложение самостоятельно и потеряли ключ подписи, вы бы застряли, вам пришлось бы создать новое приложение. Но с помощью подписки на приложение Google Play вы можете связаться со службой поддержки Play Console, и они могут вам помочь. Процесс находится на странице справки.

Посмотрите раздел под названием «Создать новый ключ загрузки». Шаг уведомления 1 - вы создаете ключ. У Google его до сих пор нет.

Спасибо за объяснение, Ник. Я новичок в Google Play, поэтому, пока вы пишете, мне нужно создать свой собственный ключ (я ничего не потерял). Ваша ссылка ведет меня на эта страница. Это немного сложно понять, потому что это для Android Studio, а не Visual Studio. Кроме того, как я писал выше Джону Дугласу, я создал свой собственный ключ (подробности см. Выше; я следовал инструкциям keytool из этой ссылки), и ApkSigner все еще не нравился. Что я делаю неправильно? Как мне это сделать правильно?

Eric 24.07.2018 15:35

Внизу страницы, на которую вы ссылаетесь, находится раздел «Создайте и подпишите приложение из командной строки» developer.android.com/studio/publish/app-signing, который дает инструкции по созданию ключа и подписи APK в командной строке. Это помогает?

Nick Fortescue 24.07.2018 16:58

«Создайте и подпишите приложение из командной строки» - это именно то, чего я придерживался, когда писал Джону выше. Я сделал это. Я настроил Visual Studio на использование созданного мной ключа. При создании APK ApkSigner не может найти ключ в хранилище ключей.

Eric 24.07.2018 17:18
Ответ принят как подходящий

Я нашел ответ на свой вопрос. документация на сайте разработчика Android не будет работать с Visual Studio. ApkSigner, поставляемый с Xamarin, не знает, что с ним делать. Вместо этого используйте это, чтобы создать свой собственный ключ выпуска:

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

Обратите внимание на -storetype pkcs12 в конце. Эта команда также модифицируется, чтобы (1) записать файл где-нибудь, кроме Program Files, (2) использовать расширение .keystore, которое нравится Visual Studio, и (3) избегать специальных символов в псевдониме, что не нравится Visual Studio, из того, что я ' я читал. (Также избегайте использования специальных символов в пароле.)

Обратите внимание, что keytool находится в c:\Program Files\Java\jdk[version]\bin.

Ключ

Когда я выполнил инструкции на документация, я получил предупреждение от 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

Если у вас есть существующий ключ и вам нужно его преобразовать, следуйте команде в предупреждении.

Спасибо:

Я хочу поблагодарить Ника за объяснение причин подписания и различения всех ключей.

И спасибо, Джон, за то, что указал мне, как создать свой собственный закрытый ключ.

я получаю исключение ошибки «Псевдоним XX не существует»

Thomas Klammer 15.06.2021 09:18

Отключить опцию "подпишите файл .APK, используя следующие сведения о хранилище ключей."

вы получите эту опцию

щелкните правой кнопкой мыши проект андроид, выберите характеристики и перейдите к Подписание пакета Android.

Example

Для меня проблема была связана с экраном упаковки / подписи. В итоге я удалил все с экрана подписи, а затем собрал архив.

После сборки я щелкнул по архиву и нажал «распространить». На этом этапе он запросил у меня хранилище ключей и пароль. Я ввел их и подписал apk. Я использовал его для загрузки приложения, и оно отлично работало.

Другие вопросы по теме