Pergunta

Estou trabalhando em um aplicativo onde os usuários precisam fazer uma chamada e digitar um número de verificação com o teclado do telefone.

Gostaria de poder detectar se o número digitado está correto ou não.O sistema telefônico não tem acesso a uma lista de números válidos, mas em vez disso, validará o número em relação a um algoritmo (como um número de cartão de crédito).

Aqui estão alguns dos requisitos:

  • Deve ser difícil digitar um código aleatório válido
  • Deve ser difícil ter um código válido se eu cometer um erro de digitação (transposição de dígitos, dígito errado)
  • Devo ter um número razoável de combinações possíveis (digamos 1 milhão)
  • O código deve ser o mais curto possível, para evitar erros do usuário

Dados esses requisitos, como você geraria esse número?

EDITAR:

@Haaked:O código deve ser numérico porque o usuário o digita com o telefone.

@matt b:Na primeira etapa o código é exibido em uma página Web, a segunda etapa é ligar e digitar o código.Não sei o número de telefone do usuário.

Seguir :Eu encontrei vários algoritmos para verificar a validade dos números (veja este projeto interessante do Google Code: verificarDígitos).

Foi útil?

Solução

Depois de alguma pesquisa, acho que vou com o ISO 7064 Mod 97,10 Fórmula.Parece bastante sólido, pois é usado para validar o IBAN (Número Internacional de Conta Bancária).

A fórmula é muito simples:

  1. Pegue um número: 123456
  2. Aplique a seguinte fórmula para obter a soma de verificação de 2 dígitos: mod(98 - mod(number * 100, 97), 97) => 76
  3. Número Concat e soma de verificação para obter o código => 12345676
  4. Para validar um código, verifique se mod(code, 97) == 1

Teste :

  • mod(12345676, 97) = 1 => BOM
  • mod(21345676, 97) = 50 => RUIM!
  • mod(12345678, 97) = 10 => RUIM!

Aparentemente, esse algoritmo detecta a maioria dos erros.

Outra opção interessante foi a Algoritmo de Verhoeff.Possui apenas um dígito de verificação e é mais difícil de implementar (em comparação com a fórmula simples acima).

Outras dicas

Para combinações de 1 milhão, você precisará de 6 dígitos.Para ter certeza de que não há códigos acidentalmente válidos, sugiro 9 dígitos com 1/1000 de chance de que um código aleatório funcione.Eu também sugeriria usar outro dígito (10 no total) para realizar uma verificação de integridade.No que diz respeito aos padrões de distribuição, o aleatório será suficiente e o dígito de verificação garantirá que um único erro não resultará em um código correto.

Editar: Aparentemente não li completamente o seu pedido.Usando um número de cartão de crédito, você pode realizar um hash nele (MD5 ou SHA1 ou algo semelhante).Em seguida, você trunca em um local apropriado (por exemplo, 9 caracteres) e converte para a base 10.Em seguida, você adiciona o(s) dígito(s) de verificação e isso deve funcionar mais ou menos para seus propósitos.

Você deseja segmentar seu código.Parte dele deve ser um CRC de 16 bits do restante do código.

Se tudo o que você deseja é um número de verificação, basta usar um número de sequência (assumindo que você tenha um único ponto de geração).Dessa forma, você sabe que não está recebendo duplicatas.

Em seguida, você prefixa a sequência com um CRC-16 desse número de sequência E alguma chave privada.Você pode usar qualquer coisa para a chave privada, desde que a mantenha privada.Faça algo grande, pelo menos um GUIA, mas poderia ser o texto a ser Guerra e Paz do projeto Gutenberg.Só precisa ser secreto e constante.Ter uma chave privada impede que as pessoas falsifiquem uma chave, mas usar um CR de 16 bits torna mais fácil quebrá-la.

Para validar basta dividir o número em duas partes e depois pegar um CRC-16 do número de sequência e a chave privada.

Se você quiser obscurecer mais a parte sequencial, divida o CRC em duas partes.Coloque 3 dígitos na frente e 2 atrás da sequência (bloco de zeros para que o comprimento do CRC seja consistente).

Este método também permite que você comece com teclas menores.As primeiras 10 chaves terão 6 dígitos.

Tem que ser apenas números?Você poderia criar um número aleatório entre 1 e 1 milhão (sugiro ainda mais alto) e então Base32 codifica-o.A próxima coisa que você precisa fazer é hash desse valor (usando um valor salt secreto) e codificar o hash em base32.Em seguida, anexe as duas strings, talvez separadas pelo travessão.

Dessa forma, você pode verificar o código recebido por meio de algoritmos.Basta pegar o lado esquerdo do código, fazer o hash usando seu salt secreto e comparar esse valor com o lado direito do código.

  • Devo ter um número razoável de combinações possíveis (digamos 1 milhão)
  • O código deve ser o mais curto possível, para evitar erros do usuário

Bem, se você quiser que tenha pelo menos um milhão de combinações, precisará de pelo menos seis dígitos.Isso é curto o suficiente?

Ao criar o código de verificação, você tem acesso ao número de telefone do chamador?

Nesse caso, eu usaria o número de telefone do chamador e o executaria por meio de algum tipo de função de hash para que você possa garantir que o código de verificação fornecido ao chamador na etapa 1 é o mesmo que ele está inserindo na etapa 2 (para ter certeza eles não estão usando o código de validação de um amigo ou simplesmente deram um palpite de muita sorte).

Sobre o hash, não tenho certeza se é possível pegar um número de 10 dígitos e obter um resultado de hash que seria <10 dígitos (acho que você teria que conviver com uma certa quantidade de colisão), mas acho isso ajudaria a garantir que o usuário seja quem diz ser.

É claro que isso não funcionará se o número de telefone usado na etapa 1 for diferente daquele de onde eles estão ligando na etapa 2.

Supondo que você já saiba como detectar qual tecla o usuário pressionou, isso deve ser feito com bastante facilidade.No mundo da segurança, existe a noção de uma senha “única”.Às vezes, isso é chamado de "senha descartável". Normalmente, eles são restritos aos valores (facilmente digitáveis) ASCII.Então, [a-zA-z0-9] e vários símbolos facilmente digitáveis.como vírgula, ponto final, ponto e vírgula e parênteses.No seu caso, porém, você provavelmente desejaria limitar o intervalo a [0-9] e possivelmente incluir * e #.

Não consigo explicar todos os detalhes técnicos de como esses códigos únicos são gerados (ou funcionam) adequadamente.Há alguma matemática intermediária por trás disso, que eu eliminaria sem primeiro revisá-la.Basta dizer que você usa um algoritmo para gerar um fluxo de senhas de uso único.Não importa quantos códigos anteriores você conheça, o próximo deve ser impossível de adivinhar!No seu caso, você simplesmente usará cada senha da lista como o código aleatório do usuário.

Em vez de falhar em explicar os detalhes da implementação, vou direcioná-lo para um artigo de 9 páginas onde você mesmo poderá ler: https://www.grc.com/ppp.htm

Parece que você tem a exigência tácita de que seja determinado rapidamente, por meio de algoritmo, que o código é válido.Isso excluiria a possibilidade de você simplesmente distribuir uma lista de números de teclado únicos.

Existem várias maneiras pelas quais as pessoas fizeram isso no passado.

  1. Faça uma chave pública e uma chave privada.Codifique os números de 0 a 999.999 usando a chave privada e distribua os resultados.Você precisará inserir alguns números aleatórios para fazer o resultado sair na versão mais longa e terá que converter o resultado da base 64 para a base 10.Ao inserir um número, converta-o novamente para base64, aplique a chave privada e veja se os números interessantes estão abaixo de 1.000.000 (descarte os números aleatórios).
  2. Use um função hash reversível
  3. Use o primeiro milhão de números de um PRN propagado em um valor específico.A função de "verificação" pode obter a semente e saber que o próximo milhão de valores é bom.Ele pode gerá-los a cada vez e verificar um por um quando um código é recebido ou, na inicialização do programa, armazená-los todos em uma tabela, classificados e, em seguida, usar a pesquisa binária (máximo de comparações), já que um milhão de números inteiros não é um lote inteiro do espaço.

Existem várias outras opções, mas são comuns e fáceis de implementar.

-Adão

Você se vinculou ao dígitos de verificação projeto, e usar a função "encode" parece uma boa solução.Diz:

encode pode lançar uma exceção se dados 'ruins' (por exemplonão numérico) é passado para ele, enquanto verify apenas retorna verdadeiro ou falso.A ideia aqui é que o encode normalmente obtém seus dados de fontes internas 'confiáveis' (uma chave de banco de dados, por exemplo), então deve ser bastante comum, na verdade, excepcional que dados ruins estejam sendo transmitidos.

Parece que você poderia passar para a função de codificação uma chave de banco de dados (5 dígitos, por exemplo) e obter um número que atendesse aos seus requisitos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top