Ir ao conteúdo
  • Cadastre-se

Javascript Bcrypt retornando false mesmo com resposta correta


Posts recomendados


Estou tendo problemas com o BCrypt. 
Estou querendo usa-lo para encriptar as respostas de uma aplicação de "Perguntas e Respostas", que estou implementando. 
A autenticação da minha aplicação, está OK, o BCrypt encripta e desencripta normalmente, porém estou tendo dificuldade para usar a mesma lógica do sistema de autenticação, para verificação das respostas corretas.
Eu consigo entrar com a resposta encriptada no db, (estou usando MongoDB , mongoose, e o BCryptjs), porém quando vou comparar as hashes, sempre retorna false, mesmo a resposta estando correta.
Se alguém puder me ajudar solucionar esse problema...agradeço !  

**OBS :**
 Salientando, que já verifiquei o Buffer.byteLength() do valor digitado e do valor armazenado no db, ambos retornam 60. 
 Também já tentei usar o compare, ao invés do compareSync, e também só retorna false.
 Já tentei fazer o compare dentro do verificar, também não funcionou.  
 Meu db está configurado para receber respostas com até 100 caracteres, para não encurtar a hash.  
 Já substitui const por var, e já experimentei tirar o await delas, porém, continua retornando false. 
 Já tentei tirar o toLowerCase e o Trim , entrando com as strings originais tanto no db quanto na resposta digitada, porém, continuou com o  mesmo problema. 
SEGUE OS CÓDIGOS

 

ESQUEMA DO BANCO DE DADOS

image.png.6adb1ce9082312dba98f3cf7b80dda49.png

 

 

ENTRADA DA RESPOSTA ENCRIPTADA NO BANCO DE DADOS

image.png.9b09dbbe736b6e4ca7eb8acc7c5271d9.png

 

VERIFICANDO RESPOSTA 

 

image.png.fc5eff1b5b13daed5baac42bc071cdd7.png

 

 

Link para o comentário
Compartilhar em outros sites

Deixa eu ver se entendi...

Pergunta: O que significa PC?
Hash da resposta: $2y$12$SrBbwDllVGknilhPSg91A.Fgbl1bI.gZiVcaazbG3fzItzYUh/I7W (Personal Computer)

 

A pessoa vai entrar com a resposta, a resposta precisa ser EXATAMENTE igual à resposta quando foi feito o hash.

Se a pessoa digitar: Personal computer, personal Computer, personal computer, Personal  Computer(dois espaços na separação) ou afins vai falhar na hora de comparar... Em tese o compare era para resolver seu problema, sem problemas... :D

Minha recomendação é que na hora de encriptar e comparar a resposta seja feita usando alguns padrões.
1º) Remoção de qualquer caractere especial e que esteja fora do alfabeto, isso é do aA-zZ;

// Exemplo false: string = 'Personal Computer@'
// Exemplo true: string = 'Personal Computer'
/^[a-zA-Z]*$/g.test(string)

 

2º) Remoção de TODOS os espaços.(Não use o trim() porque ele não remove espaços do meio)

//Entrada: 'Personal Computer';
//Saida: 'PersonalComputer'
string.replace(/\s/g,'')

 

3º) Use o toLowerCase() ~ (você já está fazendo isso hehe)

//Entrada: 'PersonalComputer'
//Saida: 'personalcomputer'
string.toLowerCase()

 

Resultado:

Pergunta: O que significa PC?
Hash da resposta: $2y$12$l2QCTolDyb9/7tvsXyMREOMkeBHiJtiB88hnpm2m4K1rR2KJ/LCNe (personalcomputer)

 

Nesse caso, mesmo se a pessoa digitar alguns desses exemplos: Personal computer, personal Computer, personal computer, Personal  Computer(dois espaços na separação) você vai conseguir comparar as strings sem problemas

 

 

Edit: Porém essa solução não é a ideal, na verdade, ela me parece que vai resultar em mt dor de cabeça quando a aplicação começar a ser usada. O ideal é mandar a resposta para o BACK-END e lá ser feito a tratativa se está certo ou errado, sem usar hash e sem se preocupar com o usuário vendo a resposta certa, dai é só retornar se está certo ou não para o front-end.

Usei o https://bcrypt-generator.com/ para gerar os Hash's e fazer as comparações.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

14 horas atrás, Rui Guilherme disse:

Olá Rui Guilherme, obrigado pela ajuda.

 Implementei a sua ideia.

Mudei, a entrada e captura dos valores a serem  comparados, colocando a expressões regular  (/[^a-z0-9]/gi,"), que restringe caracteres especiais e permite somente alfanuméricos. 

const salt =  await   bcrypt.genSaltSync(10);

 var resp1 =  await  bcrypt.hashSync (req.body.resposta1.toLowerCase().replace(/[^a-z0-9]/gi,") , salt);

 var  rV =    await   bcrypt.hashSync (req.query['resposta'].toLowerCase().replace(/[^a-z0-9]/gi,") , salt);

E quando entrava com o valor no input, ele retirava os caracteres especiais, como o esperado.

Porém quando fui comparar , continuou retornando false; 

A única diferença , que agora no bcrypt.compare retornava undefined e somente no bcrypt.compareSync ficou retornando - false. Anteriormente os dois retornavam false.

 As senhas que inseri, pra teste, foram três  -   "abc" , "abcdefg", 123456 , pra não ter erro.

 

sobre o que você disse :

 "O ideal é mandar a resposta para o BACK-END e lá ser feito a tratativa se está certo ou errado, sem usar hash e sem se preocupar com o usuário vendo a resposta certa"

Sim !  Minha aplicação estava funcionando assim, e sem o bcrypt, funciona normalmente...as respostas somente eram comparadas e verificadas normalmente. Eu quis colocar o bcrypt para melhorar a questão da segurança e diminuir risco de trapaças.

Mas sei que isso não é tão preocupante, já que é um jogo comum.

Não sei...Mas caso eu não consiga resolver. Talvez siga sem o bcrypt, ou  use outra ferramenta para fazer esse trabalho. Talvez troque a versão.

 

 

 

14 horas atrás, Rui Guilherme disse:

 

 

Link para o comentário
Compartilhar em outros sites

2 minutos atrás, Diego72Marinho disse:

Minha aplicação estava funcionando assim, e sem o bcrypt, funciona normalmente...as respostas somente eram comparadas e verificadas normalmente. Eu quis colocar o bcrypt para melhorar a questão da segurança e diminuir risco de trapaças.

Você não precisa se preocupar com trapaças nesse caso, caso as respostas estejam do lado do servidor não tem como o usuário acessar.

A rota 127.0.0.1/verificarRespostas é uma API, certo? Ela recebe a id da questão e a resposta digitada pelo usuário, pela id da questão você consegue puxar do banco de dados a resposta certa, dai você vai ter a resposta do usuário e a do banco de dados, dai é só retornar true/false e nada mais, desde que a resposta não saia do lado do servidor tá 10/10.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

18 horas atrás, Rui Guilherme disse:

Você não precisa se preocupar com trapaças nesse caso, caso as respostas estejam do lado do servidor não tem como o usuário acessar.

A rota 127.0.0.1/verificarRespostas é uma API, certo? Ela recebe a id da questão e a resposta digitada pelo usuário, pela id da questão você consegue puxar do banco de dados a resposta certa, dai você vai ter a resposta do usuário e a do banco de dados, dai é só retornar true/false e nada mais, desde que a resposta não saia do lado do servidor tá 10/10.

 

Obrigado pela ajuda !

Sim.. exatamente! Só retorna o true ou false ! 

Não ia comentar , mas, só para demonstrar que há necessidade da encriptação.

A aplicação em questão, se baseia em um jogo de perguntas e respostas, estilo "Perguntados", porém haverá uma moeda no jogo. Essa moeda poderá ser trocada por reais, caso o usuário ganhe um evento. O evento se baseia na competição entre os 30 melhores do mês. Mais ou menos, os usuários poderão ganhar ,em dinheiro, nesses eventos - até 5000 mil reais. Vai depender do quanto de moeda do jogo ele acumulou, no mês. Estimamos a média de 2200 a 5000 mil.

Vamos supor que a aplicação "dê certo" , e cresça. Agora, a equipe, sou eu e mais dois , mas, "dando certo" , a equipe aumentará. Meu medo é que quem tem o acesso ao banco de dados, futuramente, vaze o banco de dados, ou se beneficie, de alguma forma, do acesso privilegiado. Quando passa a valer dinheiro, é complicado.

Nos eventos, as perguntas serão inéditas, não podendo ser repetidas, só podendo ser usadas uma vez, logo, elas no db, serão etiquetadas de uma forma diferente, facilmente filtradas por quem tem acesso ao banco. 

As respostas teriam que ser encriptadas pelo motivo acima.  As perguntas também serão, mas de forma diferente, o sistema de encriptação das perguntas já está pronto. Quando a pergunta entrar no banco, será encriptada, quando sair e forem exibidas, a string impressa será a original. 

Mas na verdade, só estou antecipando as preocupações .

Esse problema será sanado, agora ou depois...

 

 

Link para o comentário
Compartilhar em outros sites

@Diego72Marinho

4 horas atrás, Diego72Marinho disse:

Meu medo é que quem tem o acesso ao banco de dados, futuramente, vaze o banco de dados, ou se beneficie, de alguma forma, do acesso privilegiado. Quando passa a valer dinheiro, é complicado.

Eu entendo esse seu medo, realmente transformar em hash não reversível é uma excelente forma para evitar vazamento de dados. Porém, ainda não vejo tanto sentido nisso, especialmente se considerar o surgimento de perguntas sem respostas onde ninguém sabe a resposta, dai o jogo vai ser com os desenvolvedores. kkkkkk

 

Vou te dar algumas sugestões de possíveis problemas/situações na sua regra de negócio:

 

Primeira situação:

Instrutor 1: Eu vou fazer uma questão complicada, a resposta precisa vai ser de 5 palavras.
Nessa situação, como é esperado que a pessoa consiga responder? Considerado que a pessoa pode colocar um acento errado ou uma vírgula, ou até mesmo o instrutor ter cometido esse erro, e após ter feito o hash da resposta, exceto que o instrutor saiba EXATAMENTE a resposta, inclusive dos erros essa solução de transformar em hash pode ser tornar uma grande dor de cabeça, ainda mais considerado um grande uso.

Certo, eu entendo que esse problema pode ser contornado com resposta simples de uma ou duas palavras, e vai por mim, não vai ser cuidado extra que vai evitar isso (experiência própria haha).

 

Segunda situação:

Como você vai lidar com sinônimo?

Terceira situação:

Como você vai lidar com palavras regionais? Exemplo: Aipim, Mandioca, Cassava e Macaxeira. (isso é só um exemplo)

 

Bom, não estou dizendo que você esteja errado em usar hash até porque n tenho conhecimento total de aplicação, talvez de fato seja a melhor solução só estou enfiando meu dado onde não deveria... 😕

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

@Rui Guilherme

Em 03/03/2021 às 00:33, Rui Guilherme disse:

@Diego72Marinho

Eu entendo esse seu medo, realmente transformar em hash não reversível é uma excelente forma para evitar vazamento de dados. Porém, ainda não vejo tanto sentido nisso, especialmente se considerar o surgimento de perguntas sem respostas onde ninguém sabe a resposta, dai o jogo vai ser com os desenvolvedores. kkkkkk

 

Vou te dar algumas sugestões de possíveis problemas/situações na sua regra de negócio:

 

Primeira situação:

Instrutor 1: Eu vou fazer uma questão complicada, a resposta precisa vai ser de 5 palavras.
Nessa situação, como é esperado que a pessoa consiga responder? Considerado que a pessoa pode colocar um acento errado ou uma vírgula, ou até mesmo o instrutor ter cometido esse erro, e após ter feito o hash da resposta, exceto que o instrutor saiba EXATAMENTE a resposta, inclusive dos erros essa solução de transformar em hash pode ser tornar uma grande dor de cabeça, ainda mais considerado um grande uso.

Certo, eu entendo que esse problema pode ser contornado com resposta simples de uma ou duas palavras, e vai por mim, não vai ser cuidado extra que vai evitar isso (experiência própria haha).

 

Segunda situação:

Como você vai lidar com sinônimo?

Terceira situação:

Como você vai lidar com palavras regionais? Exemplo: Aipim, Mandioca, Cassava e Macaxeira. (isso é só um exemplo)

 

Bom, não estou dizendo que você esteja errado em usar hash até porque n tenho conhecimento total de aplicação, talvez de fato seja a melhor solução só estou enfiando meu dado onde não deveria... 😕

 

Entendo sua questão, mas quando uma pergunta for inserida pelo o administrador, haverá uma série de possíveis respostas. Agora, para teste, estamos colocando só uma, mas por exemplo.

Vamos supor que a resposta para uma pergunta seja, "Jesus Cristo" ... Quando for inserir essa pergunta no sistema , haverá diversas previsões de respostas para a questão- "Jesus", "Cristo" ou "Jesus Cristo", todas essa possibilidades serão prevista pelo sistema.  Haverá no db, um array que comportará resposta1 , resposta2, resposta3 etc...

sobre:

"Nessa situação, como é esperado que a pessoa consiga responder? Considerado que a pessoa pode colocar um acento errado ou uma vírgula, ou até mesmo o instrutor ter cometido esse erro, e após ter feito o hash da resposta, exceto que o instrutor saiba EXATAMENTE a resposta, inclusive dos erros essa solução de transformar em hash pode ser tornar uma grande dor de cabeça, ainda mais considerado um grande uso."

Usando expressões regulares na inserção do db e no campo de entrada em que o usuário estará entrando com a resposta, ajudará na questão de acentuação e caracteres especiais, se ele entrar com a resposta "ambulância vermelha", "âmbulancia vermelha" ou "ambulancia vermelha" não fará diferença, pois em todas as situações a saída será "ambulanciavermelha"  o que não seria aceito, são respostas do tipo - "ambulância vermelia"  esse tipo de erro ortográfico  não seria tolerado.

 

Também as perguntas usadas serão de respostas objetivas

Em qual ano foi a tomada da Bastilha ? R = 1789 ou R= Mil Setecentos e Oitenta e Nove

Quem, segundo a tradição franco-brasileira, inventou o avião ? R= Alberto Santos Dumont /ou/ R= Santos Dumont /ou/ R= Santos Dumon /ou/ R=  Santos  Dumonte (No caso de nomes próprios uma colher de chá)

Qual é a maior pirâmide do Egito ? R= Queops R= Gizé /ou/R= pirâmide de Quéops R= pirâmide de Gizé 

Tem que ter uma previsão para possíveis respostas ...claro. 

[observando nos exemplos acima, que o sistema retirará os caracteres especiais]

Também poderá ser criado um campo recomendações no db  , para ser exibido acima do input que será inserido a resposta. 

Vamos supor que a resposta seja Tiradentes ou Joaquim José da Silva Xavier-  Ao fazer tal pergunta...a recomendação será : "insira somente o nome completo ou apelido". Isso já ajudaria ao usuário na resposta.  

Para casos de uma resposta malfeita ou uma inserção ao banco de dados com qualquer erro, as perguntas terão uma espécie de curadoria dos usuário. Os usuários poderão opinar

sobre a questão. Vamos supor que o usuário tenha 20 segundo para responder e ele ache que respondeu correto e mesmo assim retornou incorreto, após o sistema exibir "você errou" , terá uma espécie de campo para ele reclamar em caso de possível erro. Com isso perguntas que possuírem um número elevado de reclamações serão excluídas. 

 

Mas concordo com você, que pra um aumento da segurança usando criptografia, nas respostas e perguntas, aumentará as dificuldades para a implementação do sistema. 


 

 

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...