
Biblioteca de Módulo de Seguridad de Hardware Zig para tokens PIV, CAC y YubiKey a través de PC/SC. Soporta certificados, gestión de PIN, firma y descifrado.
Una biblioteca Módulo de Seguridad de Hardware (HSM) para Zig que proporciona acceso PC/SC a tokens PIV, CAC y YubiKey.
| Aspecto | Información |
|---|---|
| Estabilidad de API | Desarrollo |
| Versión de Zig | 0.16.0 |
| Plataformas | Linux, macOS, Windows |
| Licencia | MIT |
Soporte PIV (NIST SP 800-73-4)
Soporte CAC (Common Access Card)
Soporte YubiKey
Seguridad
anyerror)Operaciones paralelas (mediante thread_pool)
-Denable_tp=true); desactivar con -Denable_tp=falselibpcsclite-dev (Debian/Ubuntu) o pcsc-lite-devel (Fedora)# Debian/Ubuntu
sudo apt-get install libpcsclite-dev pcscd
# Fedora/RHEL
sudo dnf install pcsc-lite-devel pcsc-lite
# Iniciar el daemon PC/SC
sudo systemctl start pcscd
sudo systemctl enable pcscd
# Compilar y ejecutar pruebas unitarias
make
# O usando zig directamente
zig build test
# Ejecutar pruebas de integración con simulador
zig build test -Dintegration_sim=true
# Compilar ejemplos (requiere la biblioteca PC/SC instalada)
zig build examples -Dlink_pcsc=true
| Opción | Valor por defecto | Descripción | Impacto en seguridad |
|---|---|---|---|
integration_sim | false | Ejecutar pruebas de integración con simulador | Ninguno |
hsm_hil | false | Ejecutar pruebas con hardware real (requiere token real) | Ninguno |
link_pcsc | false | Enlazar biblioteca PC/SC para ejemplos | Ninguno |
include_simulator | Debug: trueRelease: false | Incluir simulador PIV con claves de prueba | CWE-321: Claves de prueba en producción |
allow_pcsc_env_override | false | RIESGO DE SEGURIDAD: Permitir variable de entorno HSM_PCSC_LIB_PATH | CWE-427: Carga de bibliotecas no confiables |
fips | false | Enrutar criptografía de seguridad a través del proveedor FIPS-140-3 enlazado (sin sobrecarga cuando está desactivado) | Ninguno cuando está desactivado |
openssl_path | (sin establecer) | Prefijo de instalación de OpenSSL para instalaciones no estándar (ej. /usr/local/ssl) | Ninguno |
Con -Dfips=true, cada primitiva criptográfica relevante para la seguridad
se enruta a través de un proveedor FIPS de OpenSSL 3.x enlazado y validado mediante
la interfaz crypto_backend, y el simulador obtiene operaciones de token PIV
postcuánticas (firma ML-DSA-65, encapsulamiento/desencapsulamiento ML-KEM-768) que
están disponibles solo en modo FIPS. La bandera está desactivada por defecto con
cero sobrecarga; la dependencia fips se resuelve solo con -Dfips=true.
# Compilación por defecto — backend std.crypto, sin enlace OpenSSL
zig build test
# Compilación FIPS — proveedor FIPS de OpenSSL (ejecutar `make deps` desde fips primero)
OPENSSL_CONF=/usr/local/ssl/ssl/openssl.cnf \
zig build test -Dfips=true -Dopenssl_path=/usr/local/ssl
# Ambos modos en un solo comando
make test-dual
Consulte docs/FIPS.md para el diseño de la interfaz, la
política de exención FIPS y las operaciones de token PQC.
Nota de seguridad: La opción allow_pcsc_env_override está desactivada por defecto para evitar ataques de inyección de bibliotecas maliciosas (CWE-427). Actívela solo para desarrollo/pruebas:
# Compilación de producción (segura, la variable de entorno se ignora)
zig build
# Compilación de desarrollo (permite HSM_PCSC_LIB_PATH)
zig build -Dallow_pcsc_env_override=true
Cuando está activada, las bibliotecas se validan antes de cargarse:
const std = @import("std");
const hsm = @import("hsm");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
// Listar tokens disponibles
const tokens = try hsm.listTokens(allocator, false);
defer {
for (tokens) |*t| t.deinit();
allocator.free(tokens);
}
if (tokens.len == 0) {
std.debug.print("No se encontraron tokens\n", .{});
return;
}
// Abrir el primer token
var token = try hsm.openToken(allocator, tokens[0].id, .{});
defer token.close();
// Verificar PIN
try token.verifyPin("123456");
// Leer certificado
const cert = try token.getCertificate(.authentication);
defer allocator.free(cert);
std.debug.print("Certificado: {} bytes\n", .{cert.len});
// Firmar un digest
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("Firma: {} bytes\n", .{signature.len});
}
| Tipo | Descripción |
|---|---|
TokenKind | Tipo de token: .piv, .cac, .yubikey, .unknown |
TokenInfo | Metadatos del token descubierto |
Token | Manejador de token abierto para operaciones |
Slot | Slot de clave: .authentication (9A), .signature (9C), .key_management (9D), .card_auth (9E) |
Algorithm | Algoritmo criptográfico: .ecdsa_p256, .ecdsa_p384, .rsa2048_pkcs1v15, etc. |
Capabilities | Banderas de capacidades del token |
PcscScope | Ámbito del contexto PC/SC: .user (por defecto), .system |
| Función | Descripción |
|---|---|
listTokens(allocator, use_sim) | Listar tokens disponibles |
openToken(allocator, id, opts) | Abrir un token por ID |
token.reconnect() | Reconectar al token y restablecer estado de autenticación |
token.verifyPin(pin) | Verificar PIN |
token.changePin(old, new) | Cambiar PIN |
token.unblockPin(puk, new_pin) | Desbloquear PIN con PUK |
token.getCertificate(slot) | Obtener certificado codificado en DER |
token.sign(slot, alg, digest) | Firmar un digest |
token.decrypt(slot, alg, ciphertext) | Descifrar datos |
token.capabilities() | Obtener capacidades del token |
token.close() | Cerrar conexión del token |
Todas las operaciones devuelven errores de HsmError:
PcscUnavailable, ReaderGone, CardRemoved, TimeoutPinIncorrect, PinLocked, PinLengthInvalidNotSupported, SlotNotFound, AlgorithmNotSupportedInvalidTlv, CertificateNotFound, InvalidDigestLengthSecurityConditionNotSatisfied, AuthenticationFailed