Identidad digital: un núcleo ISO/IEC 39794-5 en Eskiu
El contexto
La empresa hace un SDK web de captura biométrica para el alta de clientes: captura de rostro con prueba de vida y captura de identificaciones oficiales y pasaportes. El SDK corre en el navegador del usuario. Las imágenes y las mediciones se quedan en el dispositivo; nada se manda a un servidor para procesarse.
Su salida sigue ISO/IEC 39794-5, el estándar para intercambiar datos de imagen facial. Producirla es más que guardar una foto: el SDK arma el registro y sus formas JSON y XML, lo codifica en ASN.1 y lo envuelve en un bloque CBEFF, mide la calidad y la iluminación de la imagen, extrae la geometría del rostro y la apertura de los ojos a partir de los landmarks, revisa el resultado contra perfiles configurables y escribe un reporte de validación. Todo esto era TypeScript, y los SDK nativos para Android e iOS lo habrían necesitado otra vez en Kotlin y en Swift.
Por qué encajó Eskiu
- Una sola fuente para la web y el teléfono. Eskiu compila los mismos
archivos a WebAssembly con emscripten y a bibliotecas estáticas con ABI de C para
aarch64-linux-androidyarm64-apple-ios, así que el registro que produce el navegador y el que produce una app nativa salen del mismo código. - Sin runtime que cargar. El módulo WebAssembly no lleva recolector de basura ni máquina virtual, y las bibliotecas nativas son objetos comunes para el linker de cada plataforma.
- Buffers de entrada y de salida. El núcleo recibe imágenes y peticiones como buffers de bytes y devuelve sus resultados igual. Un JPEG no se expande a un arreglo de números para entrar al módulo, y las revisiones de cada cuadro reciben unos cuantos números, no la malla facial de 478 puntos.
- Memoria con límites. Cada resultado pertenece al núcleo y se libera exactamente una vez, y los límites son explícitos: una memoria máxima del módulo, una imagen máxima y una petición máxima, y lo que los rebasa se rechaza con un error.
Qué pasó a Eskiu
| Área | En el núcleo |
|---|---|
| Registro | El registro público y su serialización en JSON y XML |
| Codificaciones | El escritor ASN.1 TLV y el bloque CBEFF |
| Análisis de imagen | Calidad e iluminación, calculadas sobre los píxeles RGBA |
| Rostro | Geometría, apertura de ojos y confianza de la detección |
| Política | Perfiles, reglas de cumplimiento y reportes de validación |
El núcleo son unas 2,500 líneas de Eskiu en 18 archivos, divididos por responsabilidad. TypeScript conserva la API pública y sus tipos, y queda como adaptador de lo que es del navegador: la cámara, Canvas y la lectura de píxeles, los relojes, el parser XML de la plataforma, Web Crypto, la caché y los workers. El worker de calidad carga el mismo núcleo y los mismos perfiles que el hilo principal. El módulo WebAssembly va dentro de un chunk de JavaScript con hash, así que quien integra el SDK lo despliega igual que antes.
Cómo se verificó
La migración conservó el comportamiento existente donde era correcto y los bytes
existentes donde estaban definidos: los registros coinciden con las muestras golden del
encoder anterior, y las mediciones de imagen coinciden con la implementación anterior en
TypeScript sobre fixtures de píxeles deterministas. 210 pruebas cubren el registro, las
codificaciones, el worker, las revisiones de la captura final y las mediciones de ojos;
otras 81 cargan cada bundle que distribuye el SDK, y la compilación nativa se prueba a
través de su ABI de C, sin navegador de por medio. Reformatear las fuentes con
eskiuc fmt deja el objeto compilado idéntico byte por byte, y el equipo lo
usa para que un cambio de estilo no esconda un cambio de comportamiento.
Las mismas fuentes se compilan en cruzado a objetos ARM64 para Android e iOS. Enlazarlas dentro de las apps nativas es el siguiente paso de la integración.
Los números
| Imagen | Operación | Mediana | Percentil 95 |
|---|---|---|---|
| 640×800 | Calidad | 3.07 ms | 3.34 ms |
| 640×800 | Iluminación | 2.45 ms | 2.46 ms |
| 1920×2400 | Calidad | 27.15 ms | 27.29 ms |
| 1920×2400 | Iluminación | 22.19 ms | 22.72 ms |
Iniciar el módulo WebAssembly toma 2 ms, y la memoria que deja reservada después de un análisis completo bajó de 52.9 MiB a 23.1 MiB, porque la pasada de iluminación ya no guarda un double por píxel y lo recalcula. Son mediciones sintéticas en una Mac con Apple Silicon bajo Node, que incluyen copiar los píxeles hacia el módulo y leer el resultado; faltan las mediciones en teléfonos de gama de entrada.
La verificación de identidad es un terreno donde un registro tiene que ser el mismo sin importar dónde se produce. Con la lógica escrita una vez en Eskiu, el navegador y las apps nativas la comparten en lugar de mantener tres implementaciones al día.
eskiu