Gente, estou precisando de um código que leia o MD5 de uma senha que o usuario escrever.
Esse era o problema inicial, mas vi que tem melhores criptografias por aí.
Acho que por Começo vou de MD5 mesmo.
Vi esse tópico :
[code]package net.viralpatel.java.md5;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class JavaMD5Hash {
public static void main(String[] args) {
String password = "MyPassword123";
System.out.println("MD5 in hex: " + md5(password));
System.out.println("MD5 in hex: " + md5(null));
//= d41d8cd98f00b204e9800998ecf8427e
System.out.println("MD5 in hex: "
+ md5("The quick brown fox jumps over the lazy dog"));
//= 9e107d9d372bb6826bd81d3542a419d6
}
public static String md5(String input) {
String md5 = null;
if(null == input) return null;
try {
//Create MessageDigest object for MD5
MessageDigest digest = MessageDigest.getInstance("MD5");
//Update input string in message digest
digest.update(input.getBytes(), 0, input.length());
//Converts message digest value in base 16 (hex)
md5 = new BigInteger(1, digest.digest()).toString(16);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return md5;
}
}[/code]
O que acham ?
Usa o apache codecs. http://commons.apache.org/codec/ e usa a criptografia SHA-2
OK! Valeu !!! ja instalei e coloquei a API , ja esta rodando. Mas qual método que uso pra gerar esse SHA-2 ?
Estou nessa página :
http://commons.apache.org/codec/api-release/index.html
Se quiser fazer em Java puro, esse enum que montei pode te ajudar:
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public enum Hash {
MD5("MD5"), SHA1("SHA-1"), SHA256("SHA-256");
private String algo;
private Hash(String algo) {
this.algo = algo;
}
public byte[] diggest(byte[] dados) {
try {
MessageDigest algorithm = MessageDigest.getInstance(algo);
return algorithm.digest(dados);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Unable to generate password!", e);
}
}
public String diggest(String valor) {
return byteArrayToString(diggest(stringToByteArray(valor)));
}
private String byteArrayToString(byte[] byteArray) {
StringBuilder sb = new StringBuilder();
for (byte b : byteArray) {
int value = b & 0xFF;
if (value < 16)
sb.append("0");
sb.append(Integer.toString(value, 16));
}
return sb.toString();
}
private byte[] stringToByteArray(String valor) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (DataOutputStream dos = new DataOutputStream(bos)) {
dos.writeUTF(valor);
} catch (Exception e) {
assert (false); // Nunca ocorre com ByteArrays
}
return bos.toByteArray();
}
}
[quote=ViniGodoy]Se quiser fazer em Java puro, esse enum que montei pode te ajudar:
[code]
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public enum Hash {
MD5("MD5"), SHA1("SHA-1"), SHA256("SHA-256");
private String algo;
private Hash(String algo) {
this.algo = algo;
}
public byte[] diggest(byte[] dados) {
try {
MessageDigest algorithm = MessageDigest.getInstance(algo);
return algorithm.digest(dados);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Unable to generate password!", e);
}
}
public String diggest(String valor) {
return byteArrayToString(diggest(stringToByteArray(valor)));
}
private String byteArrayToString(byte[] byteArray) {
StringBuilder sb = new StringBuilder();
for (byte b : byteArray) {
int value = b & 0xFF;
if (value < 16)
sb.append("0");
sb.append(Integer.toString(value, 16));
}
return sb.toString();
}
private byte[] stringToByteArray(String valor) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (DataOutputStream dos = new DataOutputStream(bos)) {
dos.writeUTF(valor);
} catch (Exception e) {
assert (false); // Nunca ocorre com ByteArrays
}
return bos.toByteArray();
}
}[/code][/quote]
Obrigado Professor.
Só uma pergunta, tem alguma diferenca do “java-puro” para a API da apache ?
[quote=Andre Lopes]Obrigado Professor.
Só uma pergunta, tem alguma diferenca do “java-puro” para a API da apache ?
[/quote]
Não precisa incluir a API do Apache.
E é um pouco mais difícil de usar.
[quote=ViniGodoy][quote=Andre Lopes]Obrigado Professor.
Só uma pergunta, tem alguma diferenca do “java-puro” para a API da apache ?
[/quote]
Não precisa incluir a API do Apache.
E é um pouco mais difícil de usar.
[/quote]
Professor, muito Obrigado.
Ja implementei a classe e criptografei o nome de um amigo meu para testar.
Como ainda não li o livro do deitel, não sei se esta correto.
O sr, poderia verificar pra mim ,por favor?
package Security;
import com.mysql.jdbc.PreparedStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Validate {
private String emailInserted,passwordInserted,codeInserted;
protected String driverName,serverName,myDataBase;
private Connection conn = null;
public static void main(String args[])
{
Validate v1 = new Validate();
//v1.Validate();
v1.setStrongHash("Weiner");
}
public boolean Validate()
{
boolean valid = false; //If valid == true, permitir acesso; Se valid == false, travar acesso;
String order = null;
try {
conn = DriverManager.getConnection("URL","username of database", "password of database");
order = "Select * From Validator Where email = ? and password = ? and code = ? ";
PreparedStatement stmt = (PreparedStatement) conn.prepareStatement("Select * From Validator Where email = ? and password = ? and code = ? ");
// Coluna 0 = ID
stmt.setString(0,emailInserted); // Coluna 1
stmt.setString(1,passwordInserted); // Coluna 2
stmt.setString(2,codeInserted); // Coluna 3
ResultSet queryAnswer = stmt.executeQuery();
String idFromDb = null;
idFromDb = queryAnswer.getString(0);
String emailFromDb = null;
emailFromDb = queryAnswer.getString(1);
String passwordFromDb = null;
passwordFromDb = queryAnswer.getString(2);
String codeFromDb = null;
codeFromDb = queryAnswer.getString(3);
conn.commit();
conn.close();
//Compara os Dados
if(idFromDb != null)
{
if (emailFromDb.equals(emailInserted))
{
if(passwordFromDb.equals(passwordInserted))
{
if (codeFromDb.equals(codeInserted))
{
valid = true;
}
}
}
} else valid = false;
if ((valid == true) && (idFromDb != null) && (emailFromDb != null) && (passwordFromDb != null) && (codeFromDb != null)) return valid;
} catch (SQLException ex) {System.out.println(ex.getMessage());}
return false;
}
public String setStrongHash(String code)
{ String hashCode = null;
Hash h = null;
String hashcode = h.SHA256.diggest(code);
System.out.println("" + hashcode);
return hashCode;
}
[quote]
run:
8415c1bf09e34f7577a50414a7683aaa4f579fcbda392b89d45fd7ccbcc1e9e0
CONSTRUÍDO COM SUCESSO (tempo total: 2 segundos)
[/quote]
}
É bem simples de usar com a API do apache.
Só chamar assim:
onde text é uma String com o que você quer criptografar em sha2 =). Esse método retorna uma string sha2
DigestUtils.sha256Hex(text)
A parte do Hash em si me parece ser isso mesmo. Faltou apenas algumas boas práticas.
Substitua essa linha:
import com.mysql.jdbc.PreparedStatement;
Por essa:
import java.sql.PreparedStatement;
Além de remover a dependência ao mysql, isso vai te permitir eliminar o cast da linha 34.
PreparedStatement stmt = conn.prepareStatement("Select * From Validator Where email = ? and password = ? and code = ? ");
Evite usar SELECT *. Descreva o nome das colunas no SELECT.
Não tem porque fazer essas declarações em duas linhas:
String idFromDb = null;
inFromDb = queryAnswer.getString(0);
Faz em uma só que fica mais legível, além disso, use a coluna por nome, não por índice (isso evita que seu código quebre caso o banco mude):
String idFromDb = queryAnswer.getString("email");
Pode usar o enum diretamente, evitando a criação da variável:
String hashcode = Hash.SHA256.diggest(code);
Use o try with resources para garantir que seu Statement e Connection sejam fechados, mesmo no caso de uma exceção ou de um return.
Professor, fiz o que o senhor me disse.
Ainda vou estudar o try-with-resources pra entender melhor.Aí em seguida ja posto o resultado.
Segue o Código :
[code]package Security;
import java.sql.PreparedStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Validate {
private String emailInserted,passwordInserted,codeInserted;
protected String driverName,serverName,myDataBase;
private Connection conn = null;
public static void main(String args[])
{
Validate v1 = new Validate();
//v1.Validate();
v1.setStrongHash("Weiner");
}
public boolean Validate()
{
boolean valid = false; //If valid == true, permitir acesso; Se valid == false, travar acesso;
String order = null;
try {
conn = DriverManager.getConnection("URL","username of database", "password of database");
order = "Select id,email,password,code from validator where email = ? and password = ? and code = ? ";
PreparedStatement stmt = conn.prepareStatement("Select * From Validator Where email = ? and password = ? and code = ? ");
// Coluna 0 = ID
stmt.setString(0,emailInserted); // Coluna 1
stmt.setString(1,passwordInserted); // Coluna 2
stmt.setString(2,codeInserted); // Coluna 3
ResultSet queryAnswer = stmt.executeQuery();
String idFromDb = queryAnswer.getString("id");
String emailFromDb = queryAnswer.getString("email");
String passwordFromDb = queryAnswer.getString("password");
String codeFromDb = queryAnswer.getString("code");
conn.commit();
conn.close();
//Compara os Dados
if(idFromDb != null)
{
if (emailFromDb.equals(emailInserted))
{
if(passwordFromDb.equals(passwordInserted))
{
if (codeFromDb.equals(codeInserted))
{
valid = true;
}
}
}
} else valid = false;
if ((valid == true) && (idFromDb != null) && (emailFromDb != null) && (passwordFromDb != null) && (codeFromDb != null)) return valid;
} catch (SQLException ex) {System.out.println(ex.getMessage());}
return false;
}
public String setStrongHash(String code)
{
Hash h = null;
String hashcode = h.SHA512.diggest(code);
System.out.println("" + hashcode);
return hashcode;
}
}
[/code]
[quote=rafaelob]É bem simples de usar com a API do apache.
Só chamar assim:
onde text é uma String com o que você quer criptografar em sha2 =). Esse método retorna uma string sha2
DigestUtils.sha256Hex(text)
Depois eu vou tentar valeu
[quote=ViniGodoy]Se quiser fazer em Java puro, esse enum que montei pode te ajudar:
[code]
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public enum Hash {
MD5("MD5"), SHA1("SHA-1"), SHA256("SHA-256");
private String algo;
private Hash(String algo) {
this.algo = algo;
}
public byte[] diggest(byte[] dados) {
try {
MessageDigest algorithm = MessageDigest.getInstance(algo);
return algorithm.digest(dados);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Unable to generate password!", e);
}
}
public String diggest(String valor) {
return byteArrayToString(diggest(stringToByteArray(valor)));
}
private String byteArrayToString(byte[] byteArray) {
StringBuilder sb = new StringBuilder();
for (byte b : byteArray) {
int value = b & 0xFF;
if (value < 16)
sb.append("0");
sb.append(Integer.toString(value, 16));
}
return sb.toString();
}
private byte[] stringToByteArray(String valor) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (DataOutputStream dos = new DataOutputStream(bos)) {
dos.writeUTF(valor);
} catch (Exception e) {
assert (false); // Nunca ocorre com ByteArrays
}
return bos.toByteArray();
}
}[/code][/quote]
Professor, tenho uma dúvida, li um tópico aqui no fórum, e o rapaz informou no post mais ou menos isso :
“”
Se o S.O estiver usando outra coisa além de UNICODE, o hash será diferente …
“”
Verdade isso ?
[quote=Andre Lopes]
“”
Se o S.O estiver usando outra coisa além de UNICODE, o hash será diferente …
“”
Verdade isso ? [/quote]
Qual outra coisa??
[quote=josue carrecon][quote=Andre Lopes]
“”
Se o S.O estiver usando outra coisa além de UNICODE, o hash será diferente …
“”
Verdade isso ? [/quote]
Qual outra coisa??[/quote]
UTF-8, UTF-16…
Mas acredito que não tem nada a ver visto que o mesmo hash pra mim, é o mesmo hash que alguem vai utilizar em qualquer pc do mundo… senao, isso de hashs seria totalmente um enorme problema.
Imagina voce fazer o backup de um banco de dados e passar para um outro SO em que a codificação seja diferente? Todos hashs bem dizer seriam diferentes do que foi gerado anteriormente no outro sistema…
Abraços
oyama
Setembro 20, 2012, 6:39am
#15
O problema de Message Digest (MD) por causa de charset/encoding ocorre na maneira que você representa o byte array, pois geralmente o que se faz é transformar uma representação em hexa ou uma codificação tipo base64. Se usar o default do sistema opracional (SO), o seu programa pode não funcionar se gerar o MD em um SO e verificar em outro SO (tipo Linux e Windows).
oyama:
O problema de Message Digest (MD) por causa de charset/encoding ocorre na maneira que você representa o byte array, pois geralmente o que se faz é transformar uma representação em hexa ou uma codificação tipo base64. Se usar o default do sistema opracional (SO), o seu programa pode não funcionar se gerar o MD em um SO e verificar em outro SO (tipo Linux e Windows).
Valeu gente!
O que eu devo mudar na classe para não ter esse problema?
package Security;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import sun.security.rsa.RSASignature;
public enum Hash {
MD5("MD5"), SHA1("SHA-1"), SHA256("SHA-256"),SHA512("SHA-512");
private String algo;
private Hash(String algo) {
this.algo = algo;
}
public byte[] diggest(byte[] dados) {
try {
MessageDigest algorithm = MessageDigest.getInstance(algo);
return algorithm.digest(dados);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Unable to generate password!", e);
}
}
public String diggest(String valor) {
return byteArrayToString(diggest(stringToByteArray(valor)));
}
private String byteArrayToString(byte[] byteArray) {
StringBuilder sb = new StringBuilder();
for (byte b : byteArray) {
int value = b & 0xFF;
if (value < 16)
sb.append("0");
sb.append(Integer.toString(value, 16));
}
return sb.toString();
}
private byte[] stringToByteArray(String valor) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (DataOutputStream dos = new DataOutputStream(bos)) {
dos.writeUTF(valor);
} catch (Exception e) {
assert (false); // Nunca ocorre com ByteArrays
}
return bos.toByteArray();
}
}
Gente,Alguns usuários meus de outros países nao estao conseguindo logar com o programa. Estou achando que o Erro é nesse HASH.
Da erro de login.
O que voces me sugerem fazer?
Mostra o hash com um JOptionPane e compare com o do db para ver se está diferente…
Mas se aqui do brasil está ok, provavelmente está com problema mesmo.
Usa um charset que seja universal.
http://www.w3.org/International/articles/definitions-characters/#unicode
Abraços
[quote=Gleidson Henrique]Mostra o hash com um JOptionPane e compare com o do db para ver se está diferente…
Mas se aqui do brasil está ok, provavelmente está com problema mesmo.
Usa um charset que seja universal.
http://www.w3.org/International/articles/definitions-characters/#unicode
Abraços[/quote]
Vou fazer o teste com um jOptionPane e ja posto o resultado pra voce.
Valeu rapaz!!!