Содержание

Skip to end of metadata
Go to start of metadata

Данная статья предназначена в первую очередь для разработчиков, чьи программные продукты должны работать на компьютерах под управлением ОС СН в условиях применения Замкнутой Программной Среды (ЗПС). Для того, чтобы ЗПС позволила запуск добавляемых разработчиками файлов (исполняемых файлов и файлов библиотек), эти файлы должны быть подписаны. Предлагаемый сценарий позволяет автоматизировать задачу подписания файлов.

Данная статья применима к:

  • ОС СН Смоленск 1.6
  • ОС СН Ленинград 8.1

В данной статье предполагается, что комплект ключей для подписи ПО уже получен. В ином случае требуется запросить такой комплект (см. Как получить ключи для подписи СПО).
Также в данной статье:

  • Название организации принято за org;
  • Текст сценария, приведённый в настоящей статье, скопирован в файл signdll;
  • Подписываемый файл test.dll находится в том же каталоге, что и сценарий подписывания;
  • ЗПС выключена, так как библиотека Python xattr получается из стороннего репозитория и не подписана;
  • Для установки библиотеки xattr требуется настроенный доступ в Интернет.

Установка пакетов и настройка ключей

Файл с текстом сценария нужно сделать исполняемым:

chmod +x signdll

Для нормальной работы сценария необходимо установить набор пакетов и библиотек. Команды для установки:

sudo apt install python3 python3-pip python3-dev python-dev build-essential libssl-dev libxml2-dev libffi-dev libxslt1-dev zlib1g-dev
pip3 install xattr

Перед выполнением подписания нужно импортировать секретный ключ (предполагается, что он уже получен):

gpg --import --pinentry-mode=loopback --passphrase-file=org_password.txt org_secret.gpg

Синтаксис вызова сценария

signdll [-h] [-p PGOPTIONS] [-R] filename.dll

Параметры вызова сценария:

  • -p, --pgoptions передать следующие параметры программе bsign;
  • -R --replace - заменить оригинальный DLL не изменяя его имя;
  • -h - вывод краткой подсказки.

Текст сценария:

#!/usr/bin/python3
import sys
import shutil
import subprocess
import argparse
import xattr

DIGSIG_ELF_SIG_SIZE = 512

parser = argparse.ArgumentParser()
parser.add_argument('dll', metavar='filename.dll', help='path to dll to sign')
parser.add_argument('-p', '--pgoptions', help='pass options to the privacy guard program')
parser.add_argument('-R', '--replace', help='replace original dll', action='store_true')
args = parser.parse_args()

if not args.dll.endswith('.dll'):
    print("[Error] Must have filename.dll as an argument")
    sys.exit(1)

name = args.dll

try:
    if args.replace:
        new_name = name
    else:
        new_name = name[:-4] + '_signed.dll'
        shutil.copyfile(name, new_name)

    with open(new_name, mode='ab') as f:
        f.write(b'\x00' * DIGSIG_ELF_SIG_SIZE)

    bsign_args = ['bsign', '--sign', '--xattr', new_name]
    if args.pgoptions is not None:
        if '--batch' in args.pgoptions:
            bsign_args.append('--nopass')
        bsign_args.extend(['-p', args.pgoptions])

    if subprocess.call(bsign_args):
        print("[Error] Calling bsign failure")
        sys.exit(1)
        
    sig = xattr.getxattr(new_name, 'user.sig')
    xattr.removexattr(new_name, 'user.sig')

    with open(new_name, mode='r+b') as f:
        f.seek(-DIGSIG_ELF_SIG_SIZE, 2)
        f.write(sig)

except Exception as e:
    print(str(e))
    sys.exit(1)

Пример вызова сценария

Для подписания одного файла

Пример вызова для подписания файла test.dll (предполагается, что сценарий и подписываемый файл находятся в одном каталоге):

./signdll test.dll

После вызова сценария ввести пароль из файла org_password.txt.

При успешном подписывании в  текущем каталоге будет создан файл test_signed.dll.

Для подписания пакета файлов

Получить шестнадцатеричный идентификатор ключа командой:

gpg -k

Подписание всех файлов в текущем каталоге:

find . -name "*.dll" -exec  ./signdll -R --pgoptions="--batch --pinentry-mode=loopback --passphrase-file=org_password.txt --default-key=1234...CDEF" {} \;

где default-key - шестнадцатеричный идентификатор ключа. В данном примере использован ключ -R, который позволяет встроить подпись в подписываемый файл не создавая его копию.