4 pontos por GN⁺ 2024-04-24 | 3 comentários | Compartilhar no WhatsApp
  • Em processos nos quais pessoas precisam ler e repassar um ID, como relatórios de bug, digitação de cupons de desconto e rastreamento de entregas, a ambiguidade visual de pares como O/0 e I/l/1/7 facilmente leva a erros de digitação
  • A confusão aumenta conforme a fonte e a caligrafia, e combinações com distinção pouco nítida como 5/S, 2/Z, 8/B, 6/G e 9/q/g aparecem repetidamente
  • Em IDs que pessoas manipulam diretamente, como suporte ao cliente, IDs de erro e IDs de produto, escolher um conjunto de caracteres fácil de ler é mais importante para a qualidade de uso real do que simplesmente usar um conjunto de caracteres maior
  • Fazendo distinção entre maiúsculas e minúsculas, é possível criar 418,195,493 combinações com um ID de 5 caracteres, mas sem essa distinção o total cai para 5,153,632, exigindo um equilíbrio entre comprimento e segurança
  • IDs com distinção entre maiúsculas e minúsculas ajudam a mantê-los curtos, mas alguns sistemas ou protocolos de terceiros podem funcionar de forma case-insensitive, o que pode causar problemas na etapa de integração

Confusão de caracteres em IDs lidos por pessoas

  • Ao escrever ou transmitir IDs em interações de sistema como relatório de bugs, entrada de cupons de desconto e rastreamento de entregas, confusões de caracteres evitáveis podem arruinar a experiência do usuário
  • As combinações mais representativas de caracteres visualmente ambíguos são as seguintes
    • O / 0: em zeros sem barra ou ponto, a letra O e o número 0 podem parecer semelhantes
    • I / l / 1 / 7: a letra maiúscula I, a letra minúscula l, o número 1 e o número 7 podem ser difíceis de distinguir em vários impressos e em caligrafia
    • 5 / S, 2 / Z, 8 / B, 6 / G, 9 / q / g: podem causar confusão em certas fontes, fontes estilizadas e escrita à mão
  • A string de exemplo 9qg6G8B2Z5SIl170O é usada como comparação em várias fontes de sistema, como Arial, Helvetica, Courier, Times, Verdana, Georgia, Tahoma, Impact e Comic Sans
  • Algumas combinações, como I e l, podem continuar ambíguas em várias fontes, e outras, como 9qg, podem ficar ainda mais confusas quando escritas à mão
    • Tipos de ID em que o problema se agrava especialmente

    • cupons de desconto trocados no suporte ao cliente
    • códigos de rastreamento usados em entregas ou logística
    • IDs de erro necessários para reproduzir problemas e tratar atendimentos
    • IDs de produto usados para identificação de produtos

Equilíbrio entre diferenciação de maiúsculas/minúsculas e conjunto de caracteres

  • Ao definir as regras de geração, também é preciso decidir se o sistema tratará abc e ABC como o mesmo valor ou não
  • Excluindo caracteres visualmente ambíguos e diferenciando maiúsculas de minúsculas, restam 53 caracteres disponíveis
  • Sem diferenciar maiúsculas de minúsculas, o número de caracteres disponíveis cai para 22
  • O número de combinações possíveis conforme o comprimento do ID é o seguinte
    • 5 caracteres, com distinção entre maiúsculas e minúsculas: 53^5 = 418,195,493
    • 5 caracteres, sem distinção entre maiúsculas e minúsculas: 22^5 = 5,153,632
    • 8 caracteres, com distinção entre maiúsculas e minúsculas: 53^8 = 62,259,690,411,361
    • 8 caracteres, sem distinção entre maiúsculas e minúsculas: 22^8 = 54,875,873,536
  • No fim, a escolha é um equilíbrio entre IDs curtos, mas mais propensos a confusão e IDs mais longos, porém mais fáceis de ler
  • Se você usar maiúsculas e minúsculas, em algum momento pode encontrar comportamentos inesperados em sistemas ou protocolos de terceiros que tratam IDs sem diferenciar maiúsculas de minúsculas
    • Um sistema comercial permitia que usuários escolhessem iD e id como IDs diferentes, mas ao consultar um ID inexistente fazia correspondência sem diferenciar maiúsculas de minúsculas e retornava dados incorretos
    • A resposta para esse bug foi que se tratava de um comportamento por “conveniência”

Talvez seja preciso evitar combinações, não apenas caracteres isolados

  • Em alguns casos, a própria combinação de caracteres pode parecer outro caractere
    • rn pode parecer m
    • vv pode parecer w
  • Excluir muitos caracteres apenas por esse motivo pode reduzir demais o conjunto disponível, então pode ser mais realista evitar apenas combinações específicas na etapa de geração
  • Em situações de transmissão por voz, também vale considerar a semelhança sonora
    • Por exemplo, b e p podem soar parecidos quando pronunciados

Abordagens existentes que valem como referência

  • Base32 de Crockford decodifica caracteres ambíguos como o mesmo valor e também considera o problema de formar expressões obscenas acidentalmente
  • Open Location Code usa o conjunto de caracteres 23456789CFGHJMPQRVWX
    • Esse conjunto foi escolhido para evitar caracteres visualmente ambíguos e também evitar a formação de palavras de idiomas comuns
    • Ainda assim, inclui tanto 6 e G quanto 9 e Q

3 comentários

 
roxie 2025-01-29
 
roxie 2025-01-29

É realmente impressionante que tenham levado em conta até a pronúncia.

 
GN⁺ 2024-04-24
Comentários no Hacker News
  • No trabalho, já enviamos milhões de dispositivos com números de série, mas sem excluir nenhum caractere ou número confuso, e os clientes tiveram muita dificuldade para lê-los corretamente
    Tive de criar um script de regex que gerava todas as combinações possíveis de erros de digitação a partir do valor informado pelo cliente e mostrava apenas as que batiam com o banco de dados da fábrica; depois, cruzávamos outras informações, como a data, para inferir o número de série real
    O mais irônico é que alguns dígitos nunca mudavam e, em certa posição, bastava usar 0, 1 e 2 para identificar a fábrica, então nem era necessário usar o conjunto inteiro de caracteres. Era como se acreditassem que iríamos fabricar 8 quatrilhões de unidades

    • Muitas vezes é útil, ou pelo menos considerado útil, evitar que informações de negócio vazem por meio dos números de série
      Por exemplo, se você numera produtos sequencialmente como 1, 2, 3, é bem fácil estimar o total de vendas com uma amostra pequena. Tornar difícil adivinhar números de série válidos também pode ajudar a evitar coisas como abuso de reembolsos
      Claro que, mesmo com essas preocupações, ainda dá para evitar caracteres difíceis de ler; aliás, se isso significa que alguém está pensando em que esquema de numeração usar, a pessoa deveria ter percebido melhor esse problema. Na prática, parece bem provável que alguém tenha pensado por uns 30 segundos e dito: “se usarmos tantos dígitos, nunca vai acabar, pronto”
    • Pensando bem, esse também pode ser o motivo, ou pelo menos um dos fatores, de os números de série da Apple não terem vogais
      Parece que os números de série dos dispositivos usam apenas consoantes e números
  • A codificação deve variar conforme o usuário. Base32, especialmente Crockford e RFC 4648, é bom para uma representação curta e tem alfabetos não ambíguos bem definidos, com boas justificativas
    Mas, se o usuário precisar falar em voz alta, uma representação por lista de palavras como no s/key RFC 1751, do tipo “TIDE ITCH SLOW REIN RULE MOT”, pode ser melhor
    Não crie sua própria lista de palavras. Há infinitas armadilhas escondidas, como expressões idiomáticas, homófonos, dialetos etc. Não crie sem querer um desastre do tipo “wet clam butterfly”

    • Infelizmente, esse exemplo também pode ser ouvido como “TIED HITCH SLOE REIGN RULE MOW”. Com apenas 2 bits de paridade, nem dá para ter certeza de que essa decodificação está errada
      A RFC 1751 [0], de onde vem esse exemplo, não pressupunha uma codificação para transmissão oral; o objetivo era tornar mais fácil para o usuário “ler, lembrar e inserir”
      Se a transmissão oral for entre especialistas, faz sentido usar apenas as 26 letras maiúsculas e se apoiar no alfabeto fonético da OTAN. Mas obter um código de usuários sem treinamento em um ambiente oral com muito ruído continua sendo um problema em aberto
      [0] https://datatracker.ietf.org/doc/html/rfc1751
    • É de 1994, então dá para relevar até certo ponto, mas ainda assim é uma RFC quase comicamente ruim
      Já dá para rir no trecho “deve-se usar o algoritmo de digest de mensagem com chave MD5, que é suficientemente forte”
      Até “é difícil para a maioria das pessoas ler, lembrar e inserir” estava bom, mas aí passa para “palavras em inglês são muito mais fáceis para as pessoas lembrarem e digitarem”. Há o problema de que a maioria das pessoas não sabe inglês, mas pensei que talvez bastasse trocar a lista de palavras; então vem “por interoperabilidade, não é desejável ter dicionários separados por idioma”
      No fim, a lógica é que o mundo inteiro aprendeu as 26 letras do alfabeto inglês, então acrescentar algumas palavras deve ser aceitável, mas dentro de char Wp[2048][4] = […] não há palavras comuns adequadas para iniciantes, e sim coisas como “WAD, BESS, MERT…”. Aparecem até “ORR? AGEE EGAN HAAS!!” e “GAUL FLAM! DRAB!”
    • Fico curioso para saber como se chamam IDs desse tipo
  • Essa discussão me lembrou de algo antigo. Em um dia em que eu estava doente, para esquecer a dor no corpo, criei um módulo de brinquedo para fazer aritmética em bases arbitrárias; como era simples, coloquei no CPAN
    O módulo é https://metacpan.org/pod/Math::Fleximal
    Entre as coisas triviais que criei, achei que essa jamais receberia pedido de suporte, mas recebeu. O motivo foi que eu tinha incluído um exemplo de conversão de hexadecimal para um código alfanumérico, e alguém teve a brilhante ideia de usá-lo exatamente assim para transformar números longos em códigos mais legíveis
    O módulo funcionava bem, mas foi bem absurdo descobrir que isso tinha entrado em produção em algum lugar

  • O texto enfatiza evitar caracteres difíceis de distinguir até na escrita à mão, mas a tabela de exemplos inclui o número 7. Já passei por incontáveis situações em que era difícil distinguir o 7 e o 1 de alguém
    Colocar um traço horizontal no 7 ajuda, mas muita gente não escreve assim, então às vezes é difícil ter certeza se é um 7 ou um 1 com serifa

    • O texto também menciona “B” (Bravo) e “P” (Papa), que são difíceis de distinguir pelo som, mas deixa de fora “F” (Foxtrot) e “S” (Sierra), que soam muito mais parecidos
      Às vezes os dois são quase indistinguíveis. Dá para usar o alfabeto padrão da OTAN/aviação (Alpha, Bravo, Charlie, Delta...), mas isso não ajuda muito se o público de clientes não for muito estritamente delimitado. É melhor evitar esse tipo de combinação também
      Mesmo que a string de ID fique um pouco mais longa, é muito melhor maximizar a capacidade de ler, falar e ouvir os caracteres, e isso economiza muito mais tempo e irritação
    • Nunca passei por um caso em que um 1 escrito à mão parecesse um 7. Normalmente I ou l é que se confundem com 1
      Fico curioso para saber em que estilo de escrita manual o 1 fica parecido com 7. Só o traço superior do 7 já me parece suficiente para diferenciá-los
    • Embora tenha ficado de fora no começo, a seção “dicionário visualmente ambíguo” não inclui nem 1 nem 7
  • Se você usa maiúsculas e minúsculas, em algum momento vai acabar sendo atingido por algum sistema ou protocolo de terceiros case-insensitive
    Já vi um sistema comercial que permitia ao usuário escolher IDs com distinção entre maiúsculas e minúsculas, aceitando iD e id como valores diferentes, mas, ao consultar um ID inexistente, fazia correspondência ignorando maiúsculas/minúsculas e retornava os dados errados
    Quando relatei esse bug, responderam que era um “recurso de conveniência”

  • Ao inserir um número de série de DLC no Nintendo Switch, as teclas de caracteres ambíguos ficavam desativadas no teclado na tela, e achei isso uma experiência de usuário bem boa
    Isso significa que os números de série já são gerados, desde o início, sem caracteres ambíguos. Não tenho certeza se essa UX é integrada ao sistema operacional ou se existia apenas no jogo que eu estava jogando, Mario + Rabbids Sparks of Hope

  • O gerenciador de senhas open source KeepassXC usa cores para tornar as senhas mais legíveis. A ideia é usar cores diferentes para cada tipo de caractere, como maiúsculas, minúsculas, números e símbolos
    É uma ideia muito simples, mas ajuda bastante, especialmente em senhas aleatórias, mesmo quando já se usa uma fonte de alta legibilidade

    • O Bitwarden também usa uma fonte sem ambiguidade e três cores. Caracteres ficam na cor padrão, números em azul e símbolos em vermelho, e isso é realmente ótimo
      É difícil entender como softwares centrados em senhas permitem renderizar caracteres com uma fonte ambígua sem nenhuma diferenciação por cor
    • No gerador de senhas do KeepassXC, também é fácil adicionar uma lista de caracteres excluídos
      É tão irritante estar digitando uma senha longa por uma interface como a de um controle remoto de TV e perceber que confundiu l1|I, que eu mesmo acabo excluindo esses caracteres
    • Como pessoa com daltonismo, não gosto dessa ideia
  • Gostei de ler o texto porque trata de um problema que encontro com frequência no dia a dia
    Sempre que escrevo em papel códigos de backup de autenticação em duas etapas, fico inseguro ao passar por caracteres como o/0, v/u, 5/S. Por isso passei a escrever esses caracteres de propósito de um jeito um pouco ornamentado para que pareçam diferentes
    A parte sobre “semelhança fonética” me lembrou de quando escolhi uma senha de Wi-Fi. Eu queria uma palavra comum, com várias consoantes, que não fosse ambígua mesmo compartilhada em uma frase, e que até uma criança do 3º ano do ensino fundamental conseguisse soletrar; no fim escolhi “vacation”

    • Minha regra é colocar um ponto embaixo de todos os números. Isso resolve problemas como 5/S, 0/O, 8/B. Na prática, os pares problemáticos variam conforme a caligrafia de cada um
      Se eu realmente não tiver certeza, também acrescento o alfabeto NATO/aeronáutico [1]. Por exemplo, se houver um U, escrevo Uniform na diagonal a partir do U
      Só é preciso um pouco de disciplina. Faço isso há mais de 10 anos e nunca perdi um código de autenticação em duas etapas
      [1] Picuinhas sobre a diferença real entre os códigos NATO e aeronáuticos podem ser enviadas com segurança para /dev/null
    • Não acredito que existam pessoas que escrevem esse tipo de coisa à mão no papel
      A cabeça vira o gargalo
  • Gosto desse tipo de conversa. Pode não ser um tema de ponta nem empolgante, mas tem bastante significado e força para tornar a vida tanto das pessoas quanto das máquinas mais fácil
    Essas coisas também pertencem ao campo das boas práticas, em que, quando são bem feitas, ninguém sequer percebe. É uma realidade triste que o cuidado e a sinceridade com os detalhes acabem agrupados como “é assim que deveria ser” e não recebam elogios especiais

  • Para apontar um erro do texto: em 9qg6G8B2Z5SIl170O (ariel), o nome da fonte não é Ariel, e sim Arial. A Pequena Sereia não aparece aqui