Bem gente estou com dúvida de qual classe eu uso para criptografar a senha informada pelo usuário ao execultar o login, qual classe devo usar?
No meu caso, eu tenho uma classe de utilidades para String com a função de criptografar, que chamo no get/set da senha. Não sei se é a forma mais correta de fazer, mas nunca tive problemas.
Mas nesse caso você que criou a classe né?
Para senhas se usa criptografia destrutiva. Isso significa que uma vez encriptado não ha como decifrar. Este tipo de algoritmo se chamam de Hash ou “De uma direção”.
Há vários. O mais famosos é o MD5 que foi muito usado durante anos, mas de fato não é muito seguro. Mas é simples. Tem também o SHA-1.
De qualquer forma nenhum é absolutamente seguro, então a parte mais importante da encriptação não é a encriptação em si, mas uma forma de diferenciar a senha de A da senha de B.
Então é necessário usar o conceito de salt (sal). Isto é uma forma de alterar a mensagem original usando um outro dado conhecido e só depois emcriptar.
E para o sal de passwords é usado o username. Isto significa que mesmo que duas pessoas usem a mesma senha, a encriptação vai resultar em códigos diferentes.
Encriptação trabalha com array de byte.
Uma explicação detalhada aqui
O código é muito simples em java porque java já vem com uma lib básica de encriptação.
Vc vai precisa também de Base64 para converter o array de bytes num string para guardar no banco.
Sim, no meu caso eu tenho uma classe qualquer, pode ter qualquer nome mesmo… no meu caso era: StringUtil.
Segue abaixo o código da classe com as funções de criptografia:
public class StringUtil {
// Classe com funções para trabalho com strings.
public static String Cripto(String senha)
{
//Criptografa a String passada por parâmetro
int contador, tamanho,codigoASCII;
String senhaCriptografada = "";
tamanho = senha.length();
senha = senha.toUpperCase();
contador = 0;
while(contador <tamanho)
{
codigoASCII = senha.charAt(contador)+130;
senhaCriptografada = senhaCriptografada +(char) codigoASCII;
contador++;
}
return senhaCriptografada;
}
public static String Decripto(String senha)
{
//Descriptografa a String passada por parâmetro
int contador, tamanho,codigoASCII;
String senhaCriptografada = "";
tamanho = senha.length();
senha = senha.toUpperCase();
contador = 0;
while(contador <tamanho)
{
codigoASCII = senha.charAt(contador)-130;
senhaCriptografada = senhaCriptografada +(char) codigoASCII;
contador++;
}
return senhaCriptografada;
}
}
E então chamava está classe no local que eu precisava, como no get/set senha do usuario do sistema.
Um ótimo exemplo:
http://sziebert.net/posts/using-bcrypt-with-spring-security/
Basicamente, use o BCrypt (não vem com o Java)
Para senhas se usa criptografia destrutiva. Isso significa que uma vez encriptado não ha como decifrar. Este tipo de algoritmo se chamam de Hash ou “De uma direção”.
Há vários. O mais famosos é o MD5 que foi muito usado durante anos, mas de fato não é muito seguro. Mas é simples. Tem também o SHA-1.
De qualquer forma nenhum é absolutamente seguro, então a parte mais importante da encriptação não é a encriptação em si, mas uma forma de diferenciar a senha de A da senha de B.
Então é necessário usar o conceito de salt (sal). Isto é uma forma de alterar a mensagem original usando um outro dado conhecido e só depois emcriptar.
E para o sal de passwords é usado o username. Isto significa que mesmo que duas pessoas usem a mesma senha, a encriptação vai resultar em códigos diferentes.
Encriptação trabalha com array de byte.
Uma explicação detalhada aqui
O código é muito simples em java porque java já vem com uma lib básica de encriptação.
Vc vai precisa também de Base64 para converter o array de bytes num string para guardar no banco. [/quote]
Qual o motivo de se usar o salt? É um problema ter na base a informação que usuários compartilham a senha?
Salt é feito para dificultar ataques de Rainbow Table, que é uma lista de senhas que já foram quebradas.
Humm… não sabia. Valeu!
Eu uso o Apache Commons Codec http://commons.apache.org/codec/
public static String criptografiaBase64Encoder(String valor) {
return new Base64().encodeToString(valor.getBytes());
}
public static String descriptografiaBase64Decoder(String valorCriptografado) {
return new String(new Base64().decode(valorCriptografado));
}
MD5 ou sha512:
DigestUtils.md5Hex(senha)
DigestUtils.sha512Hex(senha)
Humm… não sabia. Valeu! :D[/quote]
Não é só por isso. Imagine que vc tem a tabela onde estão as senhas assim
admin | #$FWR##%#_)#$%#
usuarioA | ÜYTR¨&%$%TE##THTH
O que acontece se vc fizer update na linha do admin com a senha do usuarioA ?
Pois é, o usuário A pode entrar agora como o admim. ( ou vice-versa)
Se o hash depende do username este ataque não funciona.
É claro que se vc mudar tb o usename, ai funciona, mas o username é chave, não pode haver 2 iguais.
Por coincidencia eu postei um texto hoje sobre cadastro de usuários. O texto não fala explicitamente sobre criptografia de senhas, mas a demo tem uma classe que faz exatamente isso. Roubei de outro cara, mas deixei o link no código da classe.
Código: https://github.com/tveronezi/faceid/blob/master/faceid-web/src/main/java/faceid/service/bean/StringEncryptImpl.java
De onde tirei: http://www.javacodegeeks.com/2012/05/secure-password-storage-donts-dos-and.html
O post: http://buildnplay.blogspot.ca/2013/02/jaas-between-two-jee-applications-with.html
Pessoal, tenha cuidado com os algortimos que usam.
Base64 ou outra base qualquer (hexadecimal, por exemplo) não são formas de criptografia segura. No máximo são ofuscação, mas isso não segura nada.
Algoritmos que possam ser revertidos também não são seguros para senhas. Não é por acaso que o mercado de encriptação existe e movimenta milhões. Realmente é complexo bolar um algoritmo com as propriedades certas.
Então, não percam tempo com receitas caseiras e usem os algortimos de mercado. O JCE vem com alguns básicos, mas quem quiser mais poder de fogo pode usar bibliotecas de terceiro.
O principal aqui é entende o conceito. E o conceito é que é necessáio um algoritmo destrutivo de hash de mão única. Qualquer algoritmo que não seja destrutivo não serve para esta finalidade.
O Base64 é mais um utilitário para representar arrays de bytes como texto. é prático e simples, mas não é uma forma de encriptação. Porque é facilmente reversível (aliás é para isso que ele serve)
Mas gente, não tem tipo uma classe pronta no java para criptografar a senha? com um método para criptografar e outro para descriptografar não? é coisa simples só p um trabalho da faculdade
Só para complementar com uma informação. Tem sugestões de usar um salt aleatório ao invés do username (http://stackoverflow.com/questions/1645161/salt-generation-and-open-source-software/1645190#1645190)
O argumento que achei bom é que se o salt é aleatório não dá para determinar se o usuário usa a mesma senha em mais de um sistema.
[quote=ISegundo]
Só para complementar com uma informação. Tem sugestões de usar um salt aleatório ao invés do username (http://stackoverflow.com/questions/1645161/salt-generation-and-open-source-software/1645190#1645190)
O argumento que achei bom é que se o salt é aleatório não dá para determinar se o usuário usa a mesma senha em mais de um sistema.[/quote]
O salt pode ser puramente aleatorio, e ai vc tem que o gravar junto com a password, ou ele pode ser aleatorio usando o username como semente. E nesse caso não precisa gravar o salt no banco.
Quando digo que a semente é username, quero dizer que é uma função do username. Como esa função é , é diferente de sistema para sistema. Logo não ha problema de coisas repetidas.
Added : Sim, mas lendo o link, parece que a melhor prática é não derivar do nome mesmo e usar um salt aletaorio.
[quote=sergiotaborda][quote=ISegundo]
Só para complementar com uma informação. Tem sugestões de usar um salt aleatório ao invés do username (http://stackoverflow.com/questions/1645161/salt-generation-and-open-source-software/1645190#1645190)
O argumento que achei bom é que se o salt é aleatório não dá para determinar se o usuário usa a mesma senha em mais de um sistema.[/quote]
O salt pode ser puramente aleatorio, e ai vc tem que o gravar junto com a password, ou ele pode ser aleatorio usando o username como semente. E nesse caso não precisa gravar o salt no banco.
Quando digo que a semente é username, quero dizer que é uma função do username. Como esa função é , é diferente de sistema para sistema. Logo não ha problema de coisas repetidas.
Added : Sim, mas lendo o link, parece que a melhor prática é não derivar do nome mesmo e usar um salt aletaorio.[/quote]
Opa Sérgio. Agora eu tava fazendo umas análises e penso que talvez um mix seja interessante. Veja só e me diz o que acha (pode ser até exagero meu).
Se eu tenho um salt aleatório num campo e a senha criptografada em outro e eu tenho acesso ao banco de dados de usuários eu poderia pegar a senha e o salt do meu usuário (por exemplo) e colocar no registro do usuário que eu quero me passar. Aí como eu sei minha senha eu faço login na conta do cara (se bem que o login dele vai ficar bichado)
Para evitar isso eu poderia fazer o salt ser uma combinação de caracteres aleatórios + username(usando alguma derivação).
[quote=ISegundo][quote=sergiotaborda][quote=ISegundo]
Só para complementar com uma informação. Tem sugestões de usar um salt aleatório ao invés do username (http://stackoverflow.com/questions/1645161/salt-generation-and-open-source-software/1645190#1645190)
O argumento que achei bom é que se o salt é aleatório não dá para determinar se o usuário usa a mesma senha em mais de um sistema.[/quote]
O salt pode ser puramente aleatorio, e ai vc tem que o gravar junto com a password, ou ele pode ser aleatorio usando o username como semente. E nesse caso não precisa gravar o salt no banco.
Quando digo que a semente é username, quero dizer que é uma função do username. Como esa função é , é diferente de sistema para sistema. Logo não ha problema de coisas repetidas.
Added : Sim, mas lendo o link, parece que a melhor prática é não derivar do nome mesmo e usar um salt aletaorio.[/quote]
Opa Sérgio. Agora eu tava fazendo umas análises e penso que talvez um mix seja interessante. Veja só e me diz o que acha (pode ser até exagero meu).
Se eu tenho um salt aleatório num campo e a senha criptografada em outro e eu tenho acesso ao banco de dados de usuários eu poderia pegar a senha e o salt do meu usuário (por exemplo) e colocar no registro do usuário que eu quero me passar. Aí como eu sei minha senha eu faço login na conta do cara (se bem que o login dele vai ficar bichado)
Para evitar isso eu poderia fazer o salt ser uma combinação de caracteres aleatórios + username(usando alguma derivação). [/quote]
É. De fato guarda no banco não resolve muito para um ataque ao banco ( que é esse de copiar entre as linhas).
Mas talvez ai o problema seja outro. É evitar que alguem mude o banco sem passar pelo sistema. Isso resolveria com um cecksum da linha guardado num ultima coluna.
O cara teria que alterar a linha inteira para conseguir o ataque, mas ai as chaves únicas não iriam deixar. ( É que outras coisas podem ser mudadas por ataque no banco, como os roles por exemplo, então a solução tem que ser mais geral)
Mas se não quisermos controlar dessa forma , eu acho que resolveria do jeito que falou. guarda user e senha , a senha é feita com hash N vezes e salt. O salt é um numero aleatório baseado em alguma propriedade do username.
Eu faria assim, mas não sei que tipo de ataques isso poderia levar. O cara do link fala que se o salta deriva do username isso permite atacar a a senha, mas ele não fala nada se essa derivação for aleatória…
E pensar que milhares de sistemas no brasil só têm user e senha , sem salt,e às vezes sem hash… :shock:
[quote=Bruna Lima]Mas gente, não tem tipo uma classe pronta no java para criptografar a senha? com um método para criptografar e outro para descriptografar não? é coisa simples só p um trabalho da faculdade [/quote]É nítido que não deu qualquer atenção às informações postadas, caso contrário, nem teria dito “descriptografar”