
Библиотека аппаратного модуля безопасности на Zig для токенов PIV, CAC и YubiKey через PC/SC. Поддерживает сертификаты, управление PIN-кодом, подпись и расшифровку.
Библиотека модуля аппаратной безопасности (HSM) для Zig, обеспечивающая доступ через PC/SC к токенам PIV, CAC и YubiKey.
| Аспект | Информация |
|---|---|
| Стабильность API | Разработка |
| Версия Zig | 0.16.0 |
| Платформы | Linux, macOS, Windows |
| Лицензия | MIT |
Поддержка PIV (NIST SP 800-73-4)
Поддержка CAC (Common Access Card)
Поддержка YubiKey
Безопасность
anyerror)Параллельные операции (через thread_pool)
-Denable_tp=true); отключить с помощью -Denable_tp=falselibpcsclite-dev (Debian/Ubuntu) или pcsc-lite-devel (Fedora)# Debian/Ubuntu
sudo apt-get install libpcsclite-dev pcscd
# Fedora/RHEL
sudo dnf install pcsc-lite-devel pcsc-lite
# Запуск демона PC/SC
sudo systemctl start pcscd
sudo systemctl enable pcscd
# Сборка и запуск модульных тестов
make
# Или напрямую через zig
zig build test
# Запуск интеграционных тестов с симулятором
zig build test -Dintegration_sim=true
# Сборка примеров (требуется установленная библиотека PC/SC)
zig build examples -Dlink_pcsc=true
| Опция | По умолчанию | Описание | Влияние на безопасность |
|---|---|---|---|
integration_sim | false | Запуск интеграционных тестов с симулятором | Нет |
hsm_hil | false | Запуск тестов с реальным оборудованием (требуется настоящий токен) | Нет |
link_pcsc | false | Линковка библиотеки PC/SC для примеров | Нет |
include_simulator | Debug: trueRelease: false | Включение симулятора PIV с тестовыми ключами | CWE-321: Тестовые ключи в продакшене |
allow_pcsc_env_override | false | ОПАСНО: Разрешить переменную окружения HSM_PCSC_LIB_PATH | CWE-427: Загрузка ненадёжной библиотеки |
fips | false | Направлять криптографию безопасности через связанный FIPS-140-3 провайдер (нулевые накладные расходы при выключении) | Нет при выключении |
openssl_path | (не задано) | Префикс установки OpenSSL для нестандартных путей (например, /usr/local/ssl) | Нет |
С параметром -Dfips=true все критически важные криптографические примитивы
направляются через связанный валидированный FIPS-провайдер OpenSSL 3.x через
прослойку crypto_backend, а симулятор получает пост-квантовые операции PIV-токена
(подпись ML-DSA-65, инкапсуляция/декапсуляция ML-KEM-768), доступные только в
режиме FIPS. Флаг выключен по умолчанию с нулевыми накладными расходами;
зависимость fips подключается только при -Dfips=true.
# Стандартная сборка — бэкенд std.crypto, без линковки OpenSSL
zig build test
# Сборка FIPS — провайдер OpenSSL FIPS (сначала выполните `make deps` из fips)
OPENSSL_CONF=/usr/local/ssl/ssl/openssl.cnf \
zig build test -Dfips=true -Dopenssl_path=/usr/local/ssl
# Оба режима за один проход
make test-dual
См. docs/FIPS.md — описание прослойки, политика исключений из FIPS
и операции PQC-токена.
Примечание по безопасности: Параметр allow_pcsc_env_override отключён по умолчанию для предотвращения атак внедрения вредоносных библиотек (CWE-427). Включайте только для разработки/тестирования:
# Продакшн-сборка (безопасно, переменная окружения игнорируется)
zig build
# Сборка для разработки (разрешает HSM_PCSC_LIB_PATH)
zig build -Dallow_pcsc_env_override=true
При включении библиотеки проверяются перед загрузкой:
const std = @import("std");
const hsm = @import("hsm");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
// Получение списка доступных токенов
const tokens = try hsm.listTokens(allocator, false);
defer {
for (tokens) |*t| t.deinit();
allocator.free(tokens);
}
if (tokens.len == 0) {
std.debug.print("Токены не найдены\n", .{});
return;
}
// Открытие первого токена
var token = try hsm.openToken(allocator, tokens[0].id, .{});
defer token.close();
// Проверка PIN
try token.verifyPin("123456");
// Чтение сертификата
const cert = try token.getCertificate(.authentication);
defer allocator.free(cert);
std.debug.print("Сертификат: {} байт\n", .{cert.len});
// Подпись дайджеста
var digest: [32]u8 = undefined;
std.crypto.hash.sha2.Sha256.hash("Hello, PIV!", &digest, .{});
const signature = try token.sign(.authentication, .ecdsa_p256, &digest);
defer allocator.free(signature);
std.debug.print("Подпись: {} байт\n", .{signature.len});
}
| Тип | Описание |
|---|---|
TokenKind | Тип токена: .piv, .cac, .yubikey, .unknown |
TokenInfo | Метаданные обнаруженного токена |
Token | Дескриптор открытого токена для операций |
Slot | Ключевой слот: .authentication (9A), .signature (9C), .key_management (9D), .card_auth (9E) |
Algorithm | Криптографический алгоритм: .ecdsa_p256, .ecdsa_p384, .rsa2048_pkcs1v15 и др. |
Capabilities | Флаги возможностей токена |
PcscScope | Область контекста PC/SC: .user (по умолчанию), .system |
| Функция | Описание |
|---|---|
listTokens(allocator, use_sim) | Получение списка доступных токенов |
openToken(allocator, id, opts) | Открытие токена по идентификатору |
token.reconnect() | Переподключение к токену и сброс состояния аутентификации |
token.verifyPin(pin) | Проверка PIN |
token.changePin(old, new) | Изменение PIN |
token.unblockPin(puk, new_pin) | Разблокировка PIN с помощью PUK |
token.getCertificate(slot) | Получение сертификата в DER-кодировке |
token.sign(slot, alg, digest) | Подпись дайджеста |
token.decrypt(slot, alg, ciphertext) | Расшифровка данных |
token.capabilities() | Получение возможностей токена |
token.close() | Закрытие соединения с токеном |
Все операции возвращают ошибки из HsmError:
PcscUnavailable, ReaderGone, CardRemoved, TimeoutPinIncorrect, PinLocked, PinLengthInvalidNotSupported, SlotNotFound, AlgorithmNotSupportedInvalidTlv, CertificateNotFound, InvalidDigestLengthSecurityConditionNotSatisfied, AuthenticationFailed