doc/IT/CADES/AI/cryptcp-verification1.md
2025-11-27 10:41:37 +03:00

20 KiB
Raw Blame History

cryptcp.exe signature verification

1

Алгоритм проверки подписи CAdES-XL с учетом того, что TSP должен быть действительным при проверке, а сертификаты подписанта могут быть просрочены.

Алгоритм проверки подписи с cryptcp.exe

graph TB
    A[Начало проверки] --> B[Подготовка окружения]
    B --> C[Проверка TSP-метки]
    C --> D{TSP действителен?}
    D -->|Нет| E[❌ Подпись недействительна]
    D -->|Да| F[Проверка целостности]
    F --> G{Подпись соответствует документу?}
    G -->|Нет| E
    G -->|Да| H[Проверка исторической действительности]
    H --> I{Сертификат был действителен при подписании?}
    I -->|Нет| E
    I -->|Да| J[✅ Подпись действительна]

Детальный алгоритм проверки

1. Подготовка окружения для проверки

Обязательные условия:

  • Установлен КриптоПРО CSP
  • Установлены актуальные доверенные корневые сертификаты для TSA
  • Доступ к интернету для проверки TSP
# Проверка установки КриптоПРО
where cryptcp.exe

# Проверка доступности TSP-сервиса
ping tsp.tensor.ru

2. Проверка TSP-метки (критически важно)

# Команда проверки с акцентом на TSP
cryptcp -verify -cadestype XL -v "signature.sig" "document.pdf"

Что проверяет cryptcp в TSP:

  • Действительность сертификата TSA на момент проверки
  • Цепочку доверия TSA до доверенного корневого УЦ
  • Корректность временной метки
  • Соответствие хэша подписи

3. Анализ результатов проверки

import subprocess
import re

def verify_signature(signature_file, document_file):
    """
    Функция проверки подписи с анализом TSP
    """
    command = [
        "cryptcp.exe",
        "-verify",
        "-cadestype", "XL", 
        "-v",  # Детальный вывод
        signature_file,
        document_file
    ]
    
    result = subprocess.run(command, capture_output=True, text=True, encoding='cp866')
    
    return analyze_verification_result(result)

def analyze_verification_result(result):
    """
    Анализ вывода cryptcp с акцентом на TSP
    """
    output = result.stdout + result.stderr
    
    # Критически важные проверки
    checks = {
        'tsp_valid': False,
        'signature_integrity': False,
        'historical_cert_valid': False
    }
    
    # Проверка TSP-метки
    if re.search(r'Timestamp.*valid|Временная.*метка.*действительна', output, re.IGNORECASE):
        checks['tsp_valid'] = True
    
    # Проверка целостности подписи
    if re.search(r'signature.*valid|подпись.*действительна', output, re.IGNORECASE):
        checks['signature_integrity'] = True
    
    # Проверка исторической действительности сертификата
    if re.search(r'certificate.*was.*valid|сертификат.*был.*действителен', output, re.IGNORECASE):
        checks['historical_cert_valid'] = True
    
    # Определение итогового результата
    if checks['tsp_valid'] and checks['signature_integrity']:
        return "✅ Подпись действительна"
    else:
        return "❌ Подпись недействительна"

4. Интерпретация кодов возврата cryptcp.exe

def interpret_exit_code(exit_code):
    """
    Интерпретация кодов возврата cryptcp.exe
    """
    exit_codes = {
        0: "✅ Успешная проверка",
        1: "❌ Общая ошибка",
        2: "❌ Неверный формат подписи", 
        3: "❌ Проблема с сертификатом",
        4: "❌ Ошибка цепочки доверия",
        5: "❌ Ошибка проверки целостности"
    }
    return exit_codes.get(exit_code, f"❌ Неизвестный код ошибки: {exit_code}")

Практические команды для разных сценариев

Сценарий 1: Базовая проверка

cryptcp -verify -cadestype XL "document.pdf.sig" "document.pdf"

Сценарий 2: Детальная проверка с фокусом на TSP

cryptcp -verify -cadestype XL -v -tsp "http://tsp.tensor.ru" "document.pdf.sig" "document.pdf"

Сценарий 3: Проверка с игнорированием просроченных сертификатов подписанта

# К сожалению, cryptcp не имеет прямого параметра для игнорирования просрочки
# Но можно использовать кастомное хранилище сертификатов
cryptcp -verify -cadestype XL -store "My" "document.pdf.sig" "document.pdf"

Полная программа проверки на Python

import subprocess
import os
from datetime import datetime

class SignatureVerifier:
    def __init__(self, cryptcp_path="cryptcp.exe"):
        self.cryptcp_path = cryptcp_path
        
    def verify_signature(self, signature_path, document_path):
        """
        Полная проверка подписи с акцентом на TSP
        """
        print(f"🔍 Проверка подписи: {os.path.basename(signature_path)}")
        print(f"📄 Документ: {os.path.basename(document_path)}")
        print(f"🕒 Время проверки: {datetime.now()}")
        
        # Проверка существования файлов
        if not os.path.exists(signature_path):
            return "❌ Файл подписи не найден"
        if not os.path.exists(document_path):
            return "❌ Файл документа не найден"
        
        # Выполнение проверки
        command = [
            self.cryptcp_path,
            "-verify",
            "-cadestype", "XL",
            "-v",
            signature_path,
            document_path
        ]
        
        try:
            result = subprocess.run(
                command,
                capture_output=True,
                text=True,
                encoding='cp866',
                timeout=30
            )
            
            return self.analyze_result(result)
            
        except subprocess.TimeoutExpired:
            return "❌ Таймаут проверки"
        except FileNotFoundError:
            return "❌ cryptcp.exe не найден"
    
    def analyze_result(self, result):
        """
        Детальный анализ результатов проверки
        """
        analysis = {
            'success': result.returncode == 0,
            'exit_code': result.returncode,
            'tsp_status': 'unknown',
            'signature_status': 'unknown',
            'certificate_status': 'unknown'
        }
        
        output = result.stdout + result.stderr
        
        # Анализ TSP
        if 'timestamp verified' in output.lower() or 'временная метка действительна' in output.lower():
            analysis['tsp_status'] = 'valid'
        elif 'timestamp invalid' in output.lower() or 'временная метка недействительна' in output.lower():
            analysis['tsp_status'] = 'invalid'
        
        # Анализ подписи
        if 'signature verified' in output.lower() or 'подпись действительна' in output.lower():
            analysis['signature_status'] = 'valid'
        elif 'signature invalid' in output.lower() or 'подпись недействительна' in output.lower():
            analysis['signature_status'] = 'invalid'
        
        # Формирование итогового вердикта
        return self.generate_verdict(analysis, output)
    
    def generate_verdict(self, analysis, output):
        """
        Формирование итогового заключения на основе анализа
        """
        # Критически важные проверки
        if analysis['tsp_status'] != 'valid':
            return "❌ ПОДПИСЬ НЕДЕЙСТВИТЕЛЬНА: TSP-метка не прошла проверку"
        
        if analysis['signature_status'] != 'valid':
            return "❌ ПОДПИСЬ НЕДЕЙСТВИТЕЛЬНА: нарушена целостность подписи"
        
        # Если TSP и подпись действительны - подпись считается действительной
        # независимо от статуса сертификата подписанта
        if analysis['success']:
            return "✅ ПОДПИСЬ ДЕЙСТВИТЕЛЬНА"
        else:
            # Даже если cryptcp вернул ошибку, но TSP и подпись действительны,
            # это может быть из-за просроченного сертификата подписанта
            if analysis['tsp_status'] == 'valid' and analysis['signature_status'] == 'valid':
                return "✅ ПОДПИСЬ ДЕЙСТВИТЕЛЬНА (TSP подтвержден, сертификат подписанта мог истечь)"
            else:
                return f"❌ ПОДПИСЬ НЕДЕЙСТВИТЕЛЬНА. Код: {analysis['exit_code']}"

# Использование
if __name__ == "__main__":
    verifier = SignatureVerifier()
    result = verifier.verify_signature("document.pdf.sig", "document.pdf")
    print(result)

Особые случаи и обработка ошибок

Случай 1: Просрочен сертификат подписанта

# cryptcp может вернуть ошибку, но если TSP действителен - подпись сохраняет силу
cryptcp -verify ... 
# Возвращает код 3, но TSP проверен - подпись ДЕЙСТВИТЕЛЬНА

Случай 2: Недействительный TSP

# Любая ошибка TSP делает подпись недействительной
cryptcp -verify ...
# TSP не прошел проверку - подпись НЕДЕЙСТВИТЕЛЬНА

Случай 3: Нарушена целостность

# Изменен документ или подпись
cryptcp -verify ...
# Нарушена целостность - подпись НЕДЕЙСТВИТЕЛЬНА

Выводы:

  1. TSP-метка должна быть действительной ПРИ ПРОВЕРКЕ - это критически важно
  2. Сертификат подписанта может быть просрочен - важно только его состояние на момент подписания
  3. Cryptcp.exe не имеет прямых параметров для игнорирования просрочки сертификатов, но фокус на TSP позволяет корректно оценить юридическую значимость
  4. Алгоритм проверки должен в первую очередь анализировать статус TSP и целостность подписи

Данный алгоритм обеспечивает корректную проверку юридической значимости электронной подписи в соответствии с требованиями законодательства и учетом долгосрочного хранения документов.

2

Алгоритм проверки электронной подписи с акцентом на TSP

flowchart TD
    A[Начало проверки подписи] --> B[Подготовка окружения]
    
    B --> C[Проверка наличия файлов]
    C --> D{Файлы существуют?}
    D -->|Нет| E[❌ Ошибка: файлы не найдены]
    D -->|Да| F[Запуск cryptcp.exe для проверки]
    
    F --> G[Анализ вывода cryptcp]
    
    subgraph G [Анализ результатов]
        H[Проверка TSP-метки]
        I[Проверка целостности подписи]
        J[Проверка сертификата подписанта]
    end
    
    H --> K{TSP действителен?}
    K -->|Нет| L[❌ Подпись недействительна<br>TSP не прошел проверку]
    
    K -->|Да| I
    I --> M{Подпись соответствует документу?}
    M -->|Нет| N[❌ Подпись недействительна<br>Нарушена целостность]
    
    M -->|Да| J
    J --> O{Сертификат был действителен<br>на момент подписания?}
    
    O -->|Нет| P[❌ Подпись недействительна<br>Сертификат был недействителен]
    O -->|Да| Q[✅ Подпись действительна]
    
    style A fill:#e1f5fe
    style L fill:#ffebee
    style N fill:#ffebee
    style P fill:#ffebee
    style Q fill:#e8f5e9
    style H fill:#fff3e0
    style I fill:#fff3e0
    style J fill:#fff3e0

Детализация критических проверок

flowchart TD
    A[Детали проверок] --> B[TSP-метка]
    A --> C[Целостность подписи]
    A --> D[Сертификат подписанта]
    
    subgraph B [Проверка TSP-метки]
        B1[Сертификат TSA действителен]
        B2[Цепочка доверия TSA построена]
        B3[Временная метка корректна]
        B4[Хэш подписи соответствует]
    end
    
    subgraph C [Проверка целостности]
        C1[Подпись соответствует документу]
        C2[Формат CAdES-XL корректен]
        C3[Хэш документа не изменен]
    end
    
    subgraph D [Проверка сертификата подписанта]
        D1[Вложенный OCSP-ответ действителен]
        D2[Сертификат не был отозван<br>на момент подписания]
        D3[Цепочка была полной<br>на момент подписания]
    end
    
    B --> E{✅ TSP действителен?}
    C --> F{✅ Целостность сохранена?}
    D --> G{✅ Сертификат был действителен?}
    
    E & F & G --> H[✅ Все проверки пройдены]
    
    style B fill:#fff3e0
    style C fill:#fff3e0
    style D fill:#fff3e0
    style H fill:#e8f5e9

Процесс работы с cryptcp.exe

sequenceDiagram
    participant П as Программа проверки
    participant C как cryptcp.exe
    participant CSP как КриптоПРО CSP
    participant T как TSA Сервис
    participant Х как Хранилище сертификатов

    П->>C: Запуск: cryptcp -verify -cadestype XL -v signature.sig document.pdf
    C->>CSP: Декодирование CAdES-XL
    C->>CSP: Извлечение TSP-метки
    C->>T: Проверка сертификата TSA
    T-->>C: Статус сертификата TSA
    C->>Х: Поиск корневых сертификатов TSA
    Х-->>C: Корневые сертификаты
    C->>CSP: Проверка TSP-метки
    CSP-->>C: Результат проверки TSP
    C->>CSP: Проверка целостности подписи
    CSP-->>C: Результат проверки целостности
    C->>CSP: Проверка сертификата подписанта
    CSP-->>C: Результат проверки сертификата
    C-->>П: Код возврата и детальный вывод
    
    П->>П: Анализ результатов с акцентом на TSP
    П->>П: Формирование итогового вердикта

Интерпретация результатов

flowchart TD
    A[Анализ вывода cryptcp.exe] --> B[Поиск ключевых фраз]
    
    B --> C[TSP-метка]
    B --> D[Целостность подписи]
    B --> E[Сертификат подписанта]
    
    C --> C1[“timestamp verified”<br>“временная метка действительна”]
    C1 --> C2[✅ TSP действителен]
    
    D --> D1[“signature verified”<br>“подпись действительна”]
    D1 --> D2[✅ Целостность сохранена]
    
    E --> E1[“certificate was valid”<br>“сертификат был действителен”]
    E1 --> E2[✅ Сертификат был действителен]
    
    C2 & D2 --> F[✅ Подпись действительна]
    
    C --> C3[“timestamp invalid”<br>“временная метка недействительна”]
    C3 --> G[❌ Критическая ошибка TSP]
    
    D --> D3[“signature invalid”<br>“подпись недействительна”]
    D3 --> H[❌ Критическая ошибка целостности]
    
    E --> E3[“certificate was invalid”<br>“сертификат был недействителен”]
    E3 --> I[❌ Сертификат был недействителен]
    
    G --> J[❌ Подпись недействительна]
    H --> J
    I --> J
    
    style F fill:#e8f5e9
    style J fill:#ffebee
    style C2 fill:#e8f5e9
    style D2 fill:#e8f5e9
    style E2 fill:#e8f5e9
    style G fill:#ffebee
    style H fill:#ffebee
    style I fill:#ffebee

Критерии юридической значимости

flowchart TD
    A[Критерии юридической значимости] --> B[Критически важные]
    A --> C[Второстепенные]
    
    B --> B1[TSP действителен при проверке]
    B --> B2[Целостность подписи сохранена]
    B --> B3[Сертификат был действителен при подписании]
    
    C --> C1[Корневые сертификаты УЦ действительны]
    C --> C2[Сертификат подписанта действителен сейчас]
    C --> C3[Актуальные OCSP-ответы]
    
    B1 & B2 & B3 --> D[✅ Юридически значимая подпись]
    
    C1 -.->|Не влияет на историческую подпись| D
    C2 -.->|Не влияет на историческую подпись| D
    C3 -.->|Не влияет на историческую подпись| D
    
    style B fill:#fff3e0
    style C fill:#f5f5f5
    style D fill:#e8f5e9

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