Criptografia, MD5

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. :slight_smile:
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. :slight_smile:
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.

  1. 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 = ? ");    
  1. Evite usar SELECT *. Descreva o nome das colunas no SELECT.

  2. 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");  
  1. Pode usar o enum diretamente, evitando a criação da variável:
String hashcode = Hash.SHA256.diggest(code); 
  1. 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 :stuck_out_tongue: 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

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!!!