Интеграция API
sslTrus предоставляет API удаленной подписи кода, предназначенный для разработчиков, которым необходимо самостоятельно разрабатывать клиенты подписи, системы сборки или другие программы интеграции подписи.
API принимает вычисленный клиентом дайджест файла, служба удаленной подписи кода выполняет подпись с использованием закрытого ключа указанного сертификата подписи кода и возвращает результат подписи.
Клиент отвечает за:
- Вычисление дайджеста данных, подлежащих подписи.
- Формирование структуры подписи, необходимой для целевого файла.
- Вызов интерфейса удаленной подписи.
- Запись возвращенного результата подписи в целевой файл или структуру подписи.
- По необходимости передачу итогового результата обработки клиентом.
Закрытый ключ подписи кода всегда хранится в облачном HSM и не возвращается клиенту через API.
Адрес подключения
Адрес производственной среды по умолчанию:
https://ssl.face.racent.com
NICSRS среда:
https://ssl.face.nicsrs.com
Интерфейс полной подписи:
POST https://ssl.face.racent.com/v1/codesign/sign
Интерфейс отправки результатов:
POST https://ssl.face.racent.com/v1/codesign/report-sign
Если в фактической среде поставки используются другие адреса служб, ориентируйтесь на адреса, предоставленные службой доставки или эксплуатации.
Аутентификация
API использует HTTP Basic Auth.
Соответствие:
Username = Access Key
Password = Access Secret
Заголовки запроса:
Authorization: Basic <base64(accessKey:accessSecret)>
Например:
printf "%s:%s" "$ACCESS_KEY" "$ACCESS_SECRET" | base64
При фактическом использовании curl его можно напрямую указать через параметр -u:
curl -u "$ACCESS_KEY:$ACCESS_SECRET"
Access Secret относится к конфиденциальным учетным данным и не должен записываться в исходный код, общедоступные файлы конфигурации, журналы или на страницы фронтенда.
Общий формат запроса
API использует:
HTTPS
POST
JSON
Заголовки запроса:
Content-Type: application/json
Accept: application/json
Authorization: Basic <credentials>
Общий формат ответа
API возвращает единую JSON-структуру:
{
"code": 0,
"message": "ok",
"data": {}
}
Описание полей:
| Поле | Тип | Описание |
|---|---|---|
code | integer | Код состояния бизнес-операции, 0 означает успех |
message | string | Статус или сообщение об ошибке |
data | object | Бизнес-данные интерфейса |
Клиенту необходимо одновременно проверять HTTP-код состояния и код состояния бизнес-операции.
Рекомендуется обрабатывать следующим образом:
HTTP 非 2xx
↓
HTTP 请求失败
HTTP 2xx + code != 0
↓
业务失败
HTTP 2xx + code == 0
↓
读取 data
Не судите об успехе запроса на подпись только по HTTP 200.
Интерфейс подписи
Интерфейс:
POST /v1/codesign/sign
Этот интерфейс используется для отправки дайджеста, ожидающего подписания, и получения результата подписания с использованием удаленного закрытого ключа.
Параметры запроса
Пример запроса:
{
"code": "CERT_CODE",
"digest": "BASE64_ENCODED_HASH",
"algorithm": "SHA256",
"padding": "PKCS1",
"extra": {
"platform": "windows/amd64",
"version": "1.0.0",
"revision": "abcdef0",
"time": "2026-06-12T10:00:00+08:00",
"hostname": "build-host-01",
"signing_filename": "Example.exe",
"signing_filesize": 1048576
}
}
Основные параметры:
| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
code | string | Да | Номер сертификата для подписи кода |
digest | string | Да | Base64-кодировка исходных байтов дайджеста для подписи |
algorithm | string | Да | Алгоритм дайджеста |
padding | string | Да | Способ заполнения RSA, в настоящее время фиксировано как PKCS1 |
extra | object | Нет | Контекст клиента и информация для аудита |
Алгоритм дайджеста
В настоящее время поддерживаются:
SHA1
SHA256
Например, при использовании SHA-256:
{
"algorithm": "SHA256"
}
algorithm должен совпадать с алгоритмом дайджеста, фактически используемым в digest.
Формат digest
digest должен быть:
Исходные байты хеша → Base64
не является:
文件内容 Base64
Также не является:
十六进制哈希字符串
Например, если сам дайджест SHA-256 составляет 32 байта, то перед передачей в интерфейс эти 32 исходных байта следует закодировать в Base64.
padding
В настоящее время используется фиксированно:
PKCS1
То есть:
{
"padding": "PKCS1"
}
Не передавайте другие способы заполнения.
extra
extra используется для записи клиентского контекста, аудиторской информации и помощи в устранении неполадок.
Поддерживается:
| Поле | Тип | Описание |
|---|---|---|
platform | string | Клиентская платформа |
version | string | Версия клиента |
revision | string | Ревизия сборки клиента |
time | string | Время сборки или время записи на стороне запроса |
hostname | string | Имя хоста, инициировавшего запрос |
signing_filename | string | Имя подписываемого файла или локальный путь |
signing_filesize | integer | Размер файла в байтах |
Например:
{
"extra": {
"platform": "linux/amd64",
"version": "1.2.0",
"hostname": "github-runner-01",
"signing_filename": "app.exe",
"signing_filesize": 5242880
}
}
Если signing_filename содержит внутренние каталоги, имена пользователей или другую конфиденциальную информацию, рекомендуется выполнить маскирование в соответствии с политикой безопасности на стороне клиента.
Пример запроса подписи
Использование curl:
curl -u "$ACCESS_KEY:$ACCESS_SECRET" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"code": "CERT_CODE",
"digest": "BASE64_ENCODED_HASH",
"algorithm": "SHA256",
"padding": "PKCS1",
"extra": {
"platform": "linux/amd64",
"version": "1.0.0",
"hostname": "build-host-01",
"signing_filename": "Example.exe",
"signing_filesize": 1048576
}
}' \
https://ssl.face.racent.com/v1/codesign/sign
Подписанный ответ
Успешный ответ:
{
"code": 0,
"message": "ok",
"data": {
"id": "735985894427246592",
"signature": "BASE64_ENCODED_SIGNATURE"
}
}
Возвращаемые поля:
| Поле | Тип | Описание |
|---|---|---|
id | string | Идентификатор записи подписи |
signature | string | Результат RSA-подписи в кодировке Base64 |
Для фактической возможности подписания клиент в основном использует:
data.signature
Если необходимо сообщить итоговый статус после завершения локальной обработки, также нужно сохранить:
data.id
Процесс обработки на стороне клиента
Типичный процесс:
读取待签名文件
↓
按照目标格式生成待签名数据
↓
计算摘要
↓
Base64 编码摘要
↓
POST /v1/codesign/sign
↓
获得 signature
↓
构造最终签名结构
↓
写回目标文件
↓
POST /v1/codesign/report-sign
Обратите внимание:
/v1/codesign/sign
Отвечает только за базовую удалённую подпись закрытым ключом.
То, как PE Authenticode, JAR, PDF или другие форматы файлов организуют структуру подписи, клиент обрабатывает самостоятельно в соответствии с целевым форматом.
Сообщить результат подписания
Интерфейс:
POST /v1/codesign/report-sign
После получения клиентом результата удалённого подписания на последующих этапах всё ещё могут возникать ошибки, например:
- не удалось сформировать итоговую структуру подписи;
- не удалось записать целевой файл;
- ошибка прав доступа к локальному файлу;
- последующая ошибка обработки на клиенте.
С помощью этого интерфейса можно передать итоговый статус обработки обратно на сервер.
Параметры запроса
{
"id": "735985894427246592",
"status": 1
}
Параметры:
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
id | string | Да | Идентификатор записи подписи, возвращённый /v1/codesign/sign |
status | integer | Да | Итоговый статус обработки на клиенте |
Значения статуса:
| Статус | Описание |
|---|---|
1 | Итоговая обработка на клиенте завершена успешно |
2 | Итоговая обработка на клиенте завершилась ошибкой |
Пример запроса
curl -u "$ACCESS_KEY:$ACCESS_SECRET" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"id": "735985894427246592",
"status": 1
}' \
https://ssl.face.racent.com/v1/codesign/report-sign
Ответ об успехе
{
"code": 0,
"message": "ok",
"data": null
}
Количество подписей
Количество подписей API определяется тем, была ли операция удаленной подписи успешной.
Когда:
HTTP 2xx
code == 0
data.signature 非空
Если оба условия выполняются одновременно, подпись считается успешной:
签名次数 +1
Следующие случаи не расходуют количество подписей:
- Ошибка аутентификации.
- Ошибка параметров.
- Сбой сетевого запроса.
- Сбой бизнес-запроса.
- Сервер не вернул содержимое подписи успешно.
На что следует обратить особое внимание:
/v1/codesign/report-sign
Это только сообщение о конечном статусе обработки на стороне клиента. Оно не является новой операцией подписания и не увеличивает и не уменьшает количество подписаний.
Даже если клиент успешно получил результат удалённого подписания, но затем не смог записать файл локально, ранее успешно выполненное подписание удалённым закрытым ключом всё равно уже засчитано как одно подписание.
Дополнительные правила подсчёта см. в справочных материалах.
Обработка ошибок
Клиент должен обрабатывать отдельно:
- Сетевые ошибки.
- Ошибки HTTP.
- Бизнес-ошибки API.
- Локальные ошибки обработки на стороне клиента.
Ошибка аутентификации
Например:
{
"code": 401,
"message": "unauthorized",
"data": null
}
Следует проверить:
- Правильный ли Access Key.
- Правильный ли Access Secret.
- Корректно ли передан Authorization Header в запросе.
Ошибка параметров
Например:
{
"code": 400,
"message": "invalid request",
"data": null
}
Следует обратить особое внимание на проверку:
- Корректность
code. - Является ли
digestправильным Base64. - Соответствует ли
algorithmсводке. - Является ли
paddingзначениемPKCS1.
Клиент не должен полагаться на фиксированные:
message
Строковое выполнение программной логики.
Бизнес-обработка должна в первую очередь опираться на коды состояния и контракт интерфейса.
Тайм-аут и повторные попытки
При вызове удалённого интерфейса подписания следует устанавливать разумный тайм-аут сети.
При необходимости повторных попыток следует особо учитывать:
签名接口不是普通查询接口
Если клиент из-за сбоя сети не получил ответ, это не обязательно означает, что сервер не завершил подписание.
Поэтому при разработке механизма автоматических повторных попыток следует избегать неограниченного или безусловного повторения запросов на подписание.
Рекомендуется отдельно фиксировать:
- Время начала запроса.
- Номер целевого сертификата.
- Идентификатор дайджеста.
- HTTP-статус.
- Код бизнес-статуса.
- Идентификатор возвращённой записи подписания.
- Итоговый статус обработки на стороне клиента.
Не записывайте в журнал полный Access Secret.
Журналирование и аудит
Рекомендуется фиксировать необходимый контекст подписания, например:
certificate code
platform
client version
hostname
filename
filesize
sign record id
result
Для:
digest
signature
Такие данные большой длины не рекомендуется записывать в обычные журналы целиком.
Можно фиксировать:
- Длину.
- Хеш.
- Обезличенные префикс и суффикс.
Путь к файлу также может содержать имя пользователя, название проекта или сведения о внутренней структуре каталогов, поэтому решение о его маскировании следует принимать исходя из фактических требований безопасности.
Примечания по безопасности
При интеграции через API рекомендуется соблюдать следующие принципы:
- Access Secret не должен сохраняться в коде фронтенда.
- Access Secret не должен добавляться в репозиторий Git.
- Не записывайте полный заголовок Authorization Header в обычные журналы.
- Не записывайте полный Access Secret.
- Выполняйте необходимое маскирование в журналах для
digestиsignature. - Вызывайте службу удаленного подписания через HTTPS.
- Клиент должен проверять HTTP-статус и бизнес-статус.
- Настройте разумные тайм-ауты и политику повторов для сетевых запросов.
API удаленного подписания кода возвращает результат подписания, а не закрытый ключ.
Закрытый ключ подписания кода всегда остается в удаленном HSM.
Когда использовать API
Если существующие способы интеграции уже удовлетворяют вашим потребностям, обычно можно сразу использовать соответствующие инструменты.
| Сценарий | Рекомендуемый способ |
|---|---|
| Непосредственное подписание файлов EXE, DLL, MSI и других | Клиентский инструмент |
| Microsoft SignTool, Visual Studio и другое программное обеспечение Windows | Windows Provider |
| Подписание файлов JAR | Интеграция с Java |
| Автоматическая сборка в GitHub Actions, Electron Builder и подобных средах | CI/CD и инструменты сборки |
| Самостоятельная разработка клиента подписания | API |
| Самостоятельная реализация процесса подписания файловых форматов | API |
| Необходимость напрямую управлять дайджестом и результатом подписания | API |
API больше подходит разработчикам, которым требуется управлять низкоуровневым процессом подписания.
Если нужно просто выполнить подписание кода для обычных файлов, предпочтительнее сначала использовать существующий клиент или стандартный Provider: это позволяет сократить объем работы по самостоятельной обработке формата подписываемых файлов.