lecture.md 15,6 КБ
Newer Older
lagutinakv's avatar
lagutinakv включено в состав коммита
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# QCA

Copyright © 2025 ООО «Открытая мобильная платформа».
Этот документ предоставляется в соответствии
с [Публичной лицензией Creative Commons с указанием авторства версии 4.0 Международная](../../LICENSE.CC-BY-4.0.ru.md).

## Криптографическая архитектура Qt

QCA стремится предоставить простой и кроссплатформенный криптографический API, использующий типы данных и соглашения Qt.
QCA отделяет API от реализации, используя плагины, называемые криптопровайдерами.
Преимущество этой модели состоит в том, чтобы позволить приложениям избегать сопряжения или явной зависимости от какой-либо конкретной криптографической библиотеки.

Базовая функциональность плагинов предоставляется "из коробки".
Разработчики могут создавать собственные плагины (например, для SSL, SASL, TLS) или интегрировать сторонние.
Сторонние плагины должны проходить валидацию и поставляться в составе приложения.

## Функциональность QCA

QCA предоставляет простой API для следующей функциональности:

*	Безопасные массивы байтов (QCA::SecureArray).
*	Целые числа произвольной точности (QCA::BigInteger).
*	Генерация случайных чисел (QCA::Random).
*	Сертификаты X509 (QCA::Certificate и QCA::CertificateCollection).
*	Списки отозванных сертификатов X509 (QCA::CRL).
*	Встроенная поддержка корневого хранилища сертификатов операционной системы (QCA::systemStore).
*	Подсистема управления смарт-картами (QCA::KeyStore).
*	Простая, но гибкая система ведения журнала (QCA::Logger).
*	RSA (QCA::RSAPrivateKey и QCA::RSAPublicKey).
*	ECDH и ECDSA (QCA::ECPrivateKey и QCA::ECPublicKey).
*	Хеширование (QCA::Hash).
*	Шифрование (QCA::Cipher).
*	Код аутентификации сообщения (QCA::MessageAuthenticationCode).
*	Кодирование и декодирование шестнадцатеричных (QCA::Hex) и Base64 (QCA::Base64) строк.

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

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

Приложение просто включает <QtCrypto> и ссылки на libqca, которая предоставляет «оболочку API» и загрузчик плагинов.
Криптографическая функциональность определяется во время выполнения, а подключаемые модули загружаются из подкаталога «crypto» путей к библиотеке Qt.

Использование QCA во многом похоже на использование Qt, и при опыте работы с Qt работа с QCA должна казаться «естественной».
Однако для создания надёжных приложений необходимо знать несколько особенностей:

*	QCA необходимо инициализировать перед использованием любого класса, который требует поддержки плагинов или использует безопасную память.
Это большая часть QCA, поэтому следует обязательно предполагать, что нужно выполнить инициализацию.
Самый простой способ сделать это — создать экземпляр объекта QCA::Initializer и убедиться, что он не удалён (или не может выйти за пределы области видимости), пока не закончится использование QCA.
*	Большинство функциональности/алгоритмов предоставляется плагинами/криптопровайдерами.
Необходимо убедиться, что требуемая функция действительно доступна (QCA::isSupported()), прежде чем пытаться её создать.
Если приложение попытается создать класс, а поддержка подходящего криптопровайдера недоступна, оно вернётся к нулевому объекту, а когда попытается использовать один из методов — получит ошибку сегментации.
Кроме того, для функциональности, которая использует имена алгоритмов (например, QCA::Hash, который принимает на вход имя алгоритма хеширования, например «md5» или «sha256»), имя ищется во время выполнения, поэтому при опечатке (например, «md56») всё будет компилироваться правильно, но во время выполнения произойдёт ошибка сегментации.

## Список криптопровайдеров

Объект Initializer настраивает элементы, а также выполняет очистку, когда они больше не требуются.

Загрузка всех доступных криптопровайдеров.
Обычно она не нужна (потому что тестирование проходит с помощью isSupported()), но это особый случай.

Эта инструкция даёт список всех плагинов-криптопровайдеров.
У каждого криптопровайдера есть имя, которое можно отобразить, а также список возможностей.
Список строк превращается обратно в одну строку, и она также отображается.

Следует обратить внимание, что криптопровайдер по умолчанию не включается в результат QCA::providers().
Однако всё ещё можно узнать про функциональность, поддерживаемую криптопровайдером по умолчанию.

## Работа с сертификатами

Работа будет происходить с несколькими сертификатами, а QList — отличный шаблонный класс для решения данной задачи.

Используются системные сертификаты.
Эта инструкция превращает CertificateCollection в QList объектов сертификата.

Серийный номер сертификата — QCA::BigInteger, но можно просто преобразовать его в строку, а затем вывести.

Информация о субъекте показывает свойства того, к кому применяется сертификат.
Информация об издателе показывает свойства того, кем был подписан сертификат.

Далее выполняется проверка, можно ли использовать сертификат в качестве центра сертификации.
Далее выполняется проверка, является ли сертификат самоподписанным.

Сертификат действителен только в определённые даты.
Можно получить даты (как QDateTime) с помощью пары вызовов.

Можно получить сертификат в кодировке PEM простым вызовом метода toPEM().

## Хэширование

Hash — это класс для различных алгоритмов хеширования в QCA.
SHA256, SHA1 или RIPEMD160 рекомендуются для новых приложений, хотя MD2, MD4 или MD5 могут быть применимы (по причинам совместимости) для некоторых приложений.

В примере в качестве исходных данных используется первый аргумент программы, если он предоставлен, или используется «привет», если нет аргументов.

Всегда нужно проверять, поддерживается ли алгоритм, прежде чем его использовать.

Эта инструкция демонстрирует подход к хэшированию «всё в одном».

## Шифрование

Cipher — это класс для различных алгоритмов, выполняющих низкоуровневое шифрование и дешифрование в рамках QCA.

В примере в качестве исходных данных используется первый аргумент, если он предоставлен, или используется «привет», если нет аргументов.

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

Создаётся 128-битный объект шифрования AES в режиме сцепления блоков шифротекста (CBC).
Используется заполнение по умолчанию, что эквивалентно PKCS7 для CBC.
Этот объект будет зашифрован.

Используется зашифрованный объект, чтобы зашифровать аргумент, который был передан, после чего возвращается результат.
Следует обратить внимание, что если данных меньше 16 байт (1 блок), то ничего не будет возвращено.
Данные буферизуются, можно вызвать update() столько раз, сколько потребуется.

Следует обратить внимание, что всегда нужно вызывать final() даже без дополнения, чтобы провести очистку.
QCA::SecureArray f = cipher.final();

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

Текст расшифровывается.
Снова нужно вызвать final(), чтобы получить последний блок (с удалённым дополнением).
Вместо update() и final() можно сделать всё за один шаг, используя process().

## Код аутентификации сообщения

MessageAuthenticationCode— это класс для доступа к различным алгоритмам аутентификации сообщений в QCA.
Для новых приложений рекомендуется HMAC с использованием SHA1 ("hmac(sha1)") или HMAC с использованием SHA256 ("hmac(sha256)").

Первый аргумент используется как данные для аутентификации, если аргумент предоставлен.
В противном случае используется строка «hello».
 
Второй аргумент используется как ключ для аутентификации, если предоставлены два аргумента.
«Секрет» используется в качестве ключа, если число аргументов менее двух.

Создаётся требуемый объект с использованием HMAC с SHA-1 и пустым ключом.
Создаётся ключ, устанавливается объект HMAC для использования ключа. 
Он разбивается на две части, чтобы показать инкрементное обновление: три символа — "hel", остаток — "lo".
 
После вызова final обновления невозможны.
Результат конвертируется в шестнадцатеричный для печати.

## Кодирование и декодирование строк

Используется первый аргумент в качестве данных для кодирования, если аргумент предоставлен.
В противном случае используется строка «hello».

Создаётся объект, который по умолчанию использует алгоритм кодировки QCA::Base64 encoder(QCA::Encode).

В примере демонстрируется фактическое преобразование (кодирование).
Можно предпочесть использовать encoder.encode(); и пусть он вернёт QCA::SecureArray, в зависимости от потребностей.
Создаётся объект для декодирования base64.
Также можно повторно использовать существующий объект, вызвав для него clear(); и setup(QCA::Decode).
QString конвертируется в QString.