Как экспортировать сертификат подписи кода Sectigo в PFX для подписи кода Windows от Electron Forge?

Я создаю приложение Electron Forge. Я считаю, что если я подпишу свое приложение как свое ООО, я избегу всплывающих окон «Неизвестный разработчик», которые пользователи получают при запуске моего exe. Я делаю это, потому что ошибка — это пугающий UX.

Я пытаюсь получить PFX-файл с USB-накопителя Sectigo, чтобы включить подпись моего приложения с помощью действия GitHub. Я понимаю, что USB не всегда требовался.

Вот шаги, которые я собираюсь выполнить, основываясь на документации Electron Forge:

  • Купите сертификат подписи кода у Sectigo и пройдите этапы проверки. Кажется, я купил версию без EV.
  • Подключите USB-накопитель, содержащий сертификат подписи.
  • Возьмите пароль, который они отправили по электронной почте.
  • Сделайте что-нибудь, чтобы получить файл PFX
  • Обновите forge.config.js с помощью:
{
      name: '@electron-forge/maker-squirrel',
      config: {
        certificateFile: './cert.pfx', <- I need this pfx file
        certificatePassword: process.env.CERTIFICATE_PASSWORD // <- This is the email password I asusme
      }
    }

Что я пытался получить в виде файла PFX

Вот несколько способов, которыми я пытался получить PFX. База знаний Sectigo невероятно сложна для навигации и понимания. Я не вижу ни одного примера использования моего PFX. При поиске в pfx появляется только статья, в которой предполагается, что она у вас уже есть.

Использование SafeNet

  • Загрузите и откройте клиент SafeNet Authentication, приложение Sectigo, которое предлагает вам использовать.
  • Обратите внимание на иерархию Tokens -> My Company LLC -> User Certificates -> My Company LLC
  • Войдите во внешний токен My Company LLC, используя пароль, отправленный по электронной почте.
  • Щелкните правой кнопкой мыши внутренний токен My Company LLC, экспортируйте.
  • Обратите внимание, что единственный вариант типа файла — .cer, когда .pfx — это то, что необходимо.

Использование сертификата

  • Запустите certmgr.msc (обратите внимание, что поиск диспетчера сертификатов в Windows вызывает одно и то же приложение, но с разными сертификатами, я не знаю почему)
  • См. My Company LLC в списке, составленном Sectigo Public Code Signing CA R36.
  • Щелкните правой кнопкой мыши, Все задачи, Экспорт, Далее.
  • Обратите внимание, что опция Yes, export the private key размыта.
  • Смотри Note: The associated private key is marked as not exportable. Only the certificate can be exported.

Подписываю его от руки

  • Беги certmgr.msc
  • Дважды щелкните My Company LLC, Подробности, прокрутите поля вниз.
  • Скопируйте значение поля Thumbprint.
  • Добавить Signtool в путь
  • Запустите make, чтобы получить exe-файл Electron Forge.
  • В административном bash запустите
signtool sign /sha1 THUMBPRINT_OF_CERTIFICATE /tr http://timestamp.sectigo.com /td sha256 /fd sha256 /ksp "SafeNet Key Storage Provider" "path\to\program.exe"

Это дает мне

SignTool Error: Multiple certificates were found that meet all the given
        criteria. Use the /a option to allow SignTool to choose the best
        certificate automatically or use the /sha1 option with the hash of the
        desired certificate.
The following certificates meet all given criteria:
    Issued to: 12a07552-4d30-4fca-846c-a8be84912193
    Issued by: 12a07552-4d30-4fca-846c-a8be84912193
    Expires:   Sat Mar 29 01:32:52 2025
    SHA1 hash: HASH_ONE

    Issued to: 2f31b0a3-ea27-4cd2-9667-2b0d00c33f1d
    Issued by: 2f31b0a3-ea27-4cd2-9667-2b0d00c33f1d
    Expires:   Tue Mar 25 20:44:51 2025
    SHA1 hash: HASH_TWO

    Issued to: MY COMPANY LLC
    Issued by: Sectigo Public Code Signing CA R36
    Expires:   Thu May 22 18:59:59 2025
    SHA1 hash: MY_CERTIFICATE_THUMBPRINT

Несмотря на запуск команды подписи с помощью /a и /sha1, я получаю только эту ошибку.

Требования к физическому устройству

Я понимаю, что Microsoft теперь требует физического устройства для подписи приложений. Означает ли это, что мое приложение будет невозможно подписать с помощью CI? Отсутствие необходимости создавать приложения вручную избавляет меня от тысяч человеческих ошибок.

Некоторые ссылки, которые я нашел

Как выглядит мой ключ

Итак, вы купили сертификат подписи и что вы получили? Для создания файла pfx/p12 нам сначала нужно знать, что вы получили от Sectigo, обновите это в своем вопросе.

Robert 02.06.2024 01:06

В электронном письме Продукт указан как Сертификат подписи кода. Выпущено подпись открытого кода Sectigo CA R36, название продукта: SafeNet e Token 5110+ CC (940B). Были ли какие-либо из этих ценностей тем, что вы искали? Я новичок в этом пространстве, поэтому не знаю, что важно знать, спасибо за терпение.

Oliver Barnum 02.06.2024 10:06

Какие файлы вы получили от Sectigo (ключи, сгенерированные CA)? Или вам нужно создать запрос на подпись сертификата (CSR)? Проверьте документацию Sectigo.

Robert 02.06.2024 12:22

Я добавил изображения, касающиеся характера моих сертификатов, с заблокированной конфиденциальной информацией.

Oliver Barnum 03.06.2024 06:11
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
266
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Я пытаюсь получить PFX-файл с USB-накопителя Sectigo, чтобы включить подпись моего приложения с помощью действия GitHub. Я понимаю, что USB не всегда требовался.

Это невозможно, вы не можете извлечь закрытый ключ из USB-токена в файловое хранилище ключей. Новые ключи подписи кода, поставляемые с 1 июня 2023 г., должны храниться в аппаратном модуле хранения.

Вместо создания PFX-файла вам необходимо установить параметр signWithParams в конфигурации белки и указать параметры Signtool для использования USB-токена.

Что-то вроде этого:

"makers": [
  {
    "name": "@electron-forge/maker-squirrel",
    "config": {
      "signWithParams": " /a /tr http://rfc3161timestamp.globalsign.com/advanced /fd SHA256 /td SHA256 /sha1 [thumbprint]"
    }
  }
],

Спасибо вам за это, это очень полезно. Тем не менее, это может работать только на машине, где я могу ввести пароль, и только на компьютере с физическим токеном. Так что никакой непрерывной интеграции, верно?

Oliver Barnum 07.06.2024 00:49

Пароль можно передать как параметр, но вам действительно нужен доступ к токену от работника CI. Либо через прокси, например github.com/iksaif/pkcs11-proxy, либо через такой сервис, как SignServer. И в следующий раз, когда вы продлите свой сертификат, вы, возможно, захотите использовать облачную службу подписи, например Azure Trusted Signing, вместо аппаратного токена.

Emmanuel Bourg 07.06.2024 12:24

Боже, как бы мне хотелось знать, что это существует, прежде чем зайти так далеко, чтобы использовать свой жетон.

Oliver Barnum 07.06.2024 12:27

Первоначальный ответ, как сказал Эммануэль Бург, заключается в том, что вы не можете экспортировать PFX, используя новомодные физические токены.

Мое более масштабное решение заключалось в том, чтобы подписать OSX обычным способом, отправить файлы Windows в неподписанную папку и подписать их вручную с помощью сценария.

Вот мой процесс CI, который, как мне кажется, на данный момент максимально безболезненный:

  • Предполагая, что вы публикуете на s3, настройте издатель-s3 на публикацию в неподписанную папку.
        keyResolver: (fileName, platform, arch) => {
          return `${platform}/unsigned/${arch}/${fileName}`
        }
  • Установите updateSource для updateElectronApp и RemoteReleases создателя белки указывает на папку /signed.
updateElectronApp({
      updateSource: {
        type: UpdateSourceType.StaticStorage,
        baseUrl: `https://BUCKET.s3.amazonaws.com/${process.platform}/${process.arch}`
      },
      updateInterval: '1 hour',
      logger: require('electron-log')
    })
{
      name: '@electron-forge/maker-squirrel',
      config: (arch) => ({
        ...
        remoteReleases: `https://BUCKET.s3.amazonaws.com/win32/${arch}`, 
      })
    }
  • Переместите опубликованный zip-архив OSX из неподписанной в подписанную папку s3 с помощью aws cli в действии github, поскольку он подписан удаленно, поскольку Apple не требует физических токенов, СПАСИБО БОГУ. Зачем отправлять OSX в неподписанную папку? Потому что указание операционной системы s3-издателя ничего не дает, поэтому вам придется отправить оба в одно и то же ведро. Иметь двух разных издателей, один для каждой ОС, создает дубликаты.

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

  • Создайте скрипт bash, который вы будете запускать каждый раз, когда получаете зеленую сборку на github. Если полениться и не запустить его, то пользователи Windows просто не получат новых версий. Я боялся, что пользователи получат новые версии, которые не были подписаны, но этого избегают.
...
sign_setup_exe() {
    local version=$1
    TIMESTAMP_SERVER = "http://timestamp.sectigo.com"

    echo "Signing..."
    signtool sign -sha1 "$THUMBPRINT" -tr "$TIMESTAMP_SERVER" -td sha256 -fd sha256 "$LOCAL_DIR/APP-$version Setup.exe"
    signtool sign -sha1 "$THUMBPRINT" -tr "$TIMESTAMP_SERVER" -td sha256 -fd sha256 "$LOCAL_DIR/APP-win32-x64-$version/APP-$version Setup.exe"
}

process_setup_file() {
    local setup_file=$1
    local version

    version=$(echo "$setup_file" | grep -oP '(?<=APP-).*')

    echo "Considering $version..."
    if aws s3api head-object --bucket "BUCKET" --key "win32/x64/APP-win32-x64-$version.zip" >/dev/null 2>&1; then
        echo "BUCKET/win32/x64/APP-$version Setup.exe already exists so we are skipping."
        return 1
    fi

    download_files "$version"
    if [ $? -ne 0 ]; then
        echo "Failed to download files for version $version."
        return 1
    fi
    unzip_file "$version"
    if [ $? -ne 0 ]; then
        echo "Error Unzipping $version."
        return 1
    fi
    sign_setup_exe "$version"
    if [ $? -ne 0 ]; then
        echo "Error signing $version."
        return 1
    fi
    rezip_directory "$version"
    if [ $? -ne 0 ]; then
        echo "Error zipping directory signed files $version."
        return 1
    fi  
    upload_signed_files "$version"
    if [ $? -ne 0 ]; then
        echo "Error uploading signed files $version."
        return 1
    fi    
    remove_local_files
    if [ $? -ne 0 ]; then
        echo "Error removing local files for $version."
        return 1
    fi
    return 0
}
# The releases file is used to manage versions, I think both post and getting versions relies on this.
copy_releases_file() {
    aws s3 cp s3://$TEMP_BUCKET/RELEASES s3://$FINAL_BUCKET/RELEASES
}
check_for_new_files() {
    echo "Checking for new setup.exe in $TEMP_BUCKET..."

    setup_files=$(aws s3 ls "s3://$TEMP_BUCKET/" | grep 'Setup.exe' | awk '{print $4}')

    for setup_file in $setup_files; do
        process_setup_file "$setup_file"
    done
    copy_releases_file
}
check_for_new_files

Устойчиво ли это для более чем одного человека? Нет. Поможет ли приобретение выделенного сервера Windows для создания кода решить эту проблему? Нет! Кто-то все равно должен каждый раз подходить к компьютеру и вводить пароль. Я просмотрел статью, где один парень сказал, что может дать пароль для токена один раз за сеанс, но я не знаю, как они это сделали.

Вы пробовали использовать Jsign (ebourg.github.io/jsign) вместо Signtool? Это кроссплатформенный проект, и вы можете передать пароль в командной строке: jsign --storetype ETOKEN --storepass 123456 setup.exe (отказ от ответственности, я автор этого проекта).

Emmanuel Bourg 07.06.2024 16:27

я буду чувствовать себя глупо, разве вы не используете разные сертификаты для OSX и Microsoft?

Oliver Barnum 07.06.2024 18:13

Правильно. Но вы можете подписать двоичные файлы Windows в macOS, для этого не обязательно иметь сервер Windows.

Emmanuel Bourg 07.06.2024 18:23

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

Вопрос в подписи кода. Если где-то полезно настроить параметры входа в систему, прежде чем пытаться подписать, отредактируйте ответ, чтобы уточнить, где находятся эти настройки клиента и на каком этапе длительных шагов Олвера это следует сделать.

SmellyCat 12.07.2024 16:18

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