Evitar caracteres visualmente ambiguos en los ID
(gajus.com)- En procesos donde una persona tiene que leer y comunicar un ID, como reportes de bugs, ingreso de códigos de descuento o seguimiento de envíos, la ambigüedad visual de caracteres como
O/0oI/l/1/7puede convertirse fácilmente en errores de captura - La confusión aumenta según la tipografía y la escritura a mano, y aparecen repetidamente combinaciones difíciles de distinguir como
5/S,2/Z,8/B,6/G,9/q/g - En ID que las personas manejan directamente, como atención al cliente, ID de errores o ID de producto, suele ser más importante para la calidad real de uso elegir un conjunto de caracteres fácil de leer que simplemente usar un conjunto grande de caracteres
- Si se distingue entre mayúsculas y minúsculas, un ID de 5 caracteres puede generar
418,195,493combinaciones, pero si no se distingue, baja a5,153,632, así que hace falta un equilibrio entre longitud y seguridad - Los ID sensibles a mayúsculas y minúsculas ayudan a hacerlos más cortos, pero algunos sistemas o protocolos de terceros pueden funcionar de forma insensible a mayúsculas y minúsculas, lo que puede causar problemas en la integración
Confusión de caracteres en ID leídos por personas
- Cuando un ID se escribe o se transmite en interacciones del sistema, como reportes de bugs, ingreso de códigos de descuento o seguimiento de envíos, la confusión entre caracteres que se puede evitar puede arruinar la experiencia de usuario
- Las combinaciones representativas de caracteres visualmente ambiguos son las siguientes
O/0: en un 0 sin barra ni punto, la letraOy el número0pueden verse parecidosI/l/1/7: laImayúscula, lalminúscula, el1y el7pueden ser difíciles de distinguir en muchos impresos y en escritura a mano5/S,2/Z,8/B,6/G,9/q/g: pueden confundirse en ciertas tipografías, fuentes estilizadas o escritura a mano
- La cadena de ejemplo
9qg6G8B2Z5SIl170Ose usa como referencia de comparación en varias fuentes del sistema, como Arial, Helvetica, Courier, Times, Verdana, Georgia, Tahoma, Impact y Comic Sans - Algunas combinaciones, como
Iyl, pueden seguir viéndose ambiguas en muchas fuentes, y otras como9qgpueden resultar todavía más confusas al escribirlas a mano -
Tipos de ID donde el problema se agrava especialmente
- códigos de descuento intercambiados por atención al cliente
- códigos de seguimiento usados en envíos o logística
- ID de errores necesarios para reproducir problemas y atender consultas
- ID de producto usados para identificación de productos
Equilibrio entre sensibilidad a mayúsculas y minúsculas y conjunto de caracteres
- Al definir las reglas de generación, también hay que decidir si un ID como
abcyABCse considerará el mismo valor o no - Si se distingue entre mayúsculas y minúsculas y además se excluyen los caracteres visualmente ambiguos, quedan 53 caracteres disponibles
- Si no se distingue entre mayúsculas y minúsculas, los caracteres disponibles se reducen a 22
- La cantidad de combinaciones posibles según la longitud del ID es la siguiente
- 5 caracteres, sensible a mayúsculas y minúsculas:
53^5 = 418,195,493 - 5 caracteres, insensible a mayúsculas y minúsculas:
22^5 = 5,153,632 - 8 caracteres, sensible a mayúsculas y minúsculas:
53^8 = 62,259,690,411,361 - 8 caracteres, insensible a mayúsculas y minúsculas:
22^8 = 54,875,873,536
- 5 caracteres, sensible a mayúsculas y minúsculas:
- Al final, la decisión es un equilibrio entre ID cortos pero con más riesgo de confusión e ID más largos pero más fáciles de leer
- Si se usan tanto mayúsculas como minúsculas, tarde o temprano puede aparecer un comportamiento inesperado en sistemas o protocolos de terceros que no distinguen mayúsculas de minúsculas
- Un sistema comercial permitía que el usuario eligiera
iDeidcomo ID distintos, pero al consultar un ID inexistente hacía una coincidencia insensible a mayúsculas y minúsculas y devolvía datos incorrectos - La respuesta a ese bug fue que era un comportamiento pensado “por conveniencia”
- Un sistema comercial permitía que el usuario eligiera
A veces hay que evitar no solo caracteres, sino también combinaciones
- También hay casos en los que una combinación de caracteres se ve como si fuera otro carácter
rnpuede verse comomvvpuede verse comow
- Excluir demasiados caracteres solo por este motivo puede reducir demasiado el conjunto disponible, así que puede ser más realista evitar solo combinaciones específicas en la etapa de generación
- En situaciones donde el ID se transmite verbalmente, también se puede considerar la similitud fonética
- Por ejemplo,
byppueden sonar parecidos al decirlos en voz alta
- Por ejemplo,
Enfoques existentes que vale la pena revisar
- Base32 de Crockford decodifica caracteres ambiguos como si fueran el mismo valor y también considera el problema de expresiones obscenas accidentales
- Open Location Code usa el conjunto de caracteres
23456789CFGHJMPQRVWX- Este conjunto fue elegido para evitar caracteres visualmente ambiguos y también la ortografía de palabras de lenguas comunes
- Aun así, incluye tanto
6yGcomo9yQ
3 comentarios
Esto también se ve bien: https://stackoverflow.com/a/58098360/8556340
Es realmente asombroso que incluso hayan tenido en cuenta la pronunciación.
Opiniones en Hacker News
En el trabajo enviamos millones de dispositivos con números de serie, pero no excluimos ningún carácter ni número confuso, y los clientes tuvieron muchísimos problemas para leerlos correctamente.
Tuve que crear un script con expresiones regulares que generaba todas las combinaciones posibles de errores tipográficos a partir del valor que decía el cliente y mostraba solo las que coincidían con la base de datos de la fábrica; luego comparábamos otra información, como la fecha, para inferir el número de serie real.
Lo más irónico es que algunos dígitos nunca cambiaban, y en cierta posición solo hacía falta usar 0, 1 o 2 para distinguir la fábrica, así que desde el principio no necesitábamos todo el conjunto de caracteres. Era como si hubiéramos creído que íbamos a fabricar 8 cuatrillones de unidades.
Por ejemplo, si numeras los productos de forma secuencial como 1, 2, 3, con una muestra pequeña es bastante fácil estimar las ventas totales. Hacer que sea difícil adivinar números de serie válidos también puede ayudar a evitar abusos, como fraudes en reembolsos.
Claro que, aun con esas preocupaciones, se puede tomar la medida de evitar caracteres difíciles de leer; de hecho, si eso significa que alguien está pensando qué sistema de numeración usar, debería haber sido más consciente de estos problemas. En la práctica, parece más probable que alguien lo haya pensado unos 30 segundos y haya dicho: “si usamos esta cantidad de posiciones, nunca se nos van a acabar, listo”.
Parece que en los números de serie de los dispositivos solo usan consonantes y números.
La codificación debería depender del usuario. Base32, en especial Crockford y RFC 4648, es buena para representar de forma breve y tiene alfabetos no ambiguos y buenas razones para ello.
Pero si el usuario tiene que decirlo en voz alta, quizá convenga más una representación con lista de palabras como s/key RFC 1751: “TIDE ITCH SLOW REIN RULE MOT”.
No hagas tu propia lista de palabras. Hay una cantidad interminable de trampas ocultas: modismos, homófonos, dialectos, etc. No quieras crear sin querer un desastre tipo “wet clam butterfly”.
El RFC 1751 [0], de donde sale este ejemplo, no estaba pensado como una codificación para transmisión oral, sino para que a los usuarios les resultara más fácil “leer, recordar e ingresar” los datos.
Si la transmisión oral es entre expertos, tiene sentido usar solo las 26 mayúsculas y apoyarse en el alfabeto fonético de la OTAN. Pero lograr que usuarios sin entrenamiento reciban un código en un entorno oral con mucho ruido sigue siendo un problema sin resolver.
[0] https://datatracker.ietf.org/doc/html/rfc1751
Ya da risa desde la parte que dice que “debe usarse el algoritmo de resumen de mensajes con clave MD5, y es suficientemente fuerte”.
Venía bien hasta “a la mayoría de las personas les resulta difícil leerlos, recordarlos e ingresarlos”, pero luego pasa a “las palabras en inglés son mucho más fáciles de recordar e ingresar para las personas”. Está el problema de que la mayoría de las personas no sabe inglés; pensé que tal vez bastaría con cambiar la lista de palabras, pero dice que “por interoperabilidad, no es deseable tener diccionarios separados por idioma”.
Al final es como decir que, como todo el mundo ya aprendió las 26 letras del alfabeto inglés, agregar unas cuantas palabras no pasa nada, pero dentro de
char Wp[2048][4] = […]no hay palabras comunes adecuadas para principiantes, sino cosas como “WAD, BESS, MERT…”. Incluso aparecen “ORR? AGEE EGAN HAAS!!” y “GAUL FLAM! DRAB!”.Esto me recuerda algo de hace tiempo. Un día que estaba enfermo hice, para distraerme del malestar, un módulo de juguete para aritmética en bases arbitrarias; como era sencillo, lo subí a CPAN.
Ese módulo es https://metacpan.org/pod/Math::Fleximal.
De todas las cosas triviales que hice, pensé que esta jamás recibiría una solicitud de soporte, pero sí ocurrió. La razón fue que había incluido un ejemplo para convertir hexadecimal en códigos alfanuméricos, y a alguien se le ocurrió la brillante idea de usarlo tal cual para convertir números largos en códigos legibles.
El módulo funcionaba bien, pero fue bastante absurdo enterarme de que eso había terminado en producción en algún lugar.
El artículo enfatiza que hay que evitar caracteres difíciles de distinguir incluso escritos a mano, pero en la tabla de ejemplo incluye el número 7. He tenido incontables situaciones en las que era difícil distinguir el 7 y el 1 de alguien.
Ponerle una barra horizontal al 7 ayuda, pero mucha gente no lo escribe así, así que a veces cuesta saber si es un 7 o un 1 con serif.
A veces casi no se distinguen. Se podría usar el alfabeto estándar OTAN/aeronáutico (Alpha, Bravo, Charlie, Delta...), pero si tu base de clientes no está extremadamente acotada, no ayuda demasiado. También conviene evitar estas combinaciones.
Aunque la cadena de ID se vuelva un poco más larga, es mucho mejor maximizar la capacidad de leer, decir y escuchar los caracteres; ahorra mucho más tiempo y frustración.
Me pregunto en qué estilo de escritura a mano el 1 se parece al 7. Con solo el trazo horizontal superior del 7 debería bastar para distinguirlo.
Si usas tanto mayúsculas como minúsculas, tarde o temprano te va a afectar algún sistema o protocolo de terceros sin distinción entre mayúsculas y minúsculas.
De hecho, he visto un sistema comercial que permitía a los usuarios elegir ID que distinguían mayúsculas y minúsculas, aceptando
iDeidcomo valores distintos, pero que al consultar un ID inexistente hacía una coincidencia ignorando mayúsculas y minúsculas y devolvía datos equivocados.Cuando reporté este bug, respondieron que era una “función de conveniencia”.
Al ingresar un número de serie de DLC en Nintendo Switch, las teclas de caracteres ambiguos estaban desactivadas en el teclado en pantalla, y me pareció una experiencia de usuario bastante buena
Eso significa que, desde un principio, los números de serie se generan sin caracteres ambiguos. No sé bien si esta UX está integrada en el sistema operativo o si solo estaba en el juego que estaba jugando, Mario + Rabbids Sparks of Hope
El gestor de contraseñas open source KeepassXC usa colores para que las contraseñas sean más legibles. La idea es usar un color distinto para cada tipo de carácter, como mayúsculas, minúsculas, números y símbolos
Es una idea muy simple, pero ayuda mucho, especialmente con contraseñas aleatorias, incluso si ya se usa una fuente muy legible
Me cuesta entender que software centrado en contraseñas permita renderizar caracteres con una fuente ambigua y sin ninguna diferenciación por color
Me da tanta rabia cuando estoy ingresando una contraseña larga en una interfaz como la de un control remoto de TV y me doy cuenta de que confundí
l1|I, que directamente los excluyoFue una buena lectura porque trata un problema que me encuentro a menudo
Cada vez que escribo en papel códigos de respaldo de autenticación de dos factores, me pongo nervioso al pasar por caracteres como
o/0,v/u,5/S. Por eso empecé a escribir esos caracteres con pequeños adornos a propósito, para que se vean distintosLa parte de la “similitud fonética” me recordó a cuando elijo una contraseña de wifi. Quería una palabra común que no fuera ambigua al compartirla en una sola oración, que hasta un niño de tercer grado de primaria pudiera deletrear y que tuviera varias consonantes, y al final elegí “vacation”
5/S,0/O,8/B. En la práctica, los pares problemáticos dependen de la letra manuscrita de cada quienSi de verdad no estoy seguro, también agrego el alfabeto NATO/aeronáutico [1]. Por ejemplo, si hay una
U, escriboUniformen diagonal empezando desde laUSolo hace falta un poco de disciplina. Llevo más de 10 años haciendo esto y nunca he perdido un código de autenticación de dos factores
[1] Las objeciones quisquillosas sobre la diferencia real entre el código NATO y el aeronáutico pueden enviarse tranquilamente a
/dev/nullEl cuello de botella es la cabeza
Me gustan estas conversaciones. Quizá no sean temas de vanguardia ni emocionantes, pero tienen bastante significado y fuerza para hacerles la vida más fácil tanto a las personas como a las máquinas
Estas cosas también pertenecen al ámbito de las mejores prácticas, donde, si se hacen bien, más bien nadie las nota. Es una lástima que el cuidado y la sinceridad por los detalles se agrupen bajo “así debe ser” y no reciban elogios especiales
Para señalar un error del artículo: en
9qg6G8B2Z5SIl170O (ariel), el nombre de la fuente no es Ariel, sino Arial. La sirenita no aparece por aquíEn Linux, la mayoría de las líneas se ven iguales
https://github.com/gajus/gajus-com/blob/main/src/blogPosts/2...
Ya corregí el typo