Ответы пользователя по тегу Электронная цифровая подпись
  • Как подписать данные открепленной подписью для заказа КМ честного знака СУЗ?

    @Meller008 Автор вопроса
    Код который у меня работает! Пользуйтесь на здоровье!

    import win32com.client
    import base64
    import pythoncom
    import json
    import requests
    
    
    def signed_data(_data):
        # Функция подписывает данные открепленной подписью
        # Возращает обратно данные которые подписаны, и открепленную подпись
        CADES_BES = 1
        CAPICOM_ENCODE_BASE64 = 0
        CAPICOM_CURRENT_USER_STORE = 2
        CAPICOM_MY_STORE = "My"
        CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED = 2
        sSerialNumber = "SERIAL_NUMBER"  # ID ключа, берется из крипто-про
        # Инструменты криптопро -> контейнеры -> Найти нужный ключ (не просроченный, видно при тестировании контейнера) -> Протестировать контейнер -> серийный номер
    
        # Ищем сертификат в хранилище
        oCert = None
        oStore = win32com.client.Dispatch("CAdESCOM.Store", pythoncom.CoInitialize())
        oStore.Open(CAPICOM_CURRENT_USER_STORE, CAPICOM_MY_STORE, CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED)
        for val in oStore.Certificates:
            if val.SerialNumber.upper() == sSerialNumber.upper():
                oCert = val
        oStore.Close
        if not oCert:
            print("Не найден сертификат в хранилище")
            return None
    
        oSigner = win32com.client.Dispatch("CAdESCOM.CPSigner", pythoncom.CoInitialize())
        oSigner.Certificate = oCert
    
        # Строка JSON БЕЗ ПРОБЕЛОВ
        message = _data
        message_bytes = message.encode()
        base64_bytes = base64.b64encode(message_bytes)
        base64_message = base64_bytes.decode()
    
        signedData = win32com.client.Dispatch("CAdESCOM.CadesSignedData", pythoncom.CoInitialize())
        signedData.ContentEncoding = 1
        signedData.Content = base64_message
        sSignedData = signedData.SignCades(oSigner, CADES_BES, True, CAPICOM_ENCODE_BASE64)
    
        # Удаляем из подписи символы переноса строки, иначе не вставить в заголовок запроса
        sSignedData = sSignedData.replace('\r', '')
        sSignedData = sSignedData.replace('\n', '')
    
        return _data, sSignedData
    
    
    # token выдается при авторизации по URL <url стенда>/auth/simpleSignIn/{omsConnection}
    # Статья есть на хабре.
    headers = {"clientToken": "token", "Accept": "application/json", 'Content-type': 'application/json'}
    # oms_id - Находим в личном кабинете - управление заказами - устройства - OMS ID:
    query_params = {"omsId": "oms_id"}
    # Заполнение поля products я пропущу, оно хорошо описано в документации к СУЗ
    body = {
        "productGroup": "lp",
        "attributes": {
            "releaseMethodType": "PRODUCTION",
            "createMethodType": "SELF_MADE",
        },
        "products": [],
    }
    
    # Переводим словарь в JSON БЕЗ ПРОБЕЛОВ!
    json_str = json.dumps(body, separators=(',', ':'))
    sData, signed = signed_data(json_str)  # получаем подпись
    
    headers["X-Signature"] = signed
    
    # Так же в тело запроса отправляем этот JSON который подписывали без пробелов!
    response = requests.post(f"https://suz.sandbox.crptech.ru/api/v3/order", params=query_params, headers=headers, data=sData)
    if response.status_code == 200:
        response.json()
    Ответ написан
    Комментировать