Erro: criptografia + banco dados

17 respostas
H

To tentando criptografar as senhas e gravar no banco, to usando o MD5, mas ta dando erro de incompatibilidade de caracteres. Coloquei o banco como LATIN1. Alguem sabe como soluciono isso? Tipo uma conversao e tals, e ai como faco?

public class Criptografia {
    
    public static String criptografar(String senha) {
        try {
            byte[] senhaCript;
            MessageDigest md = MessageDigest.getInstance("MD5");
            //md.reset();
            senhaCript = md.digest(senha.getBytes());
            char[] senhaConvert = new char[senhaCript.length];
            for (int i=0; i<senhaCript.length; i++)
                senhaConvert[i] = (char)senhaCript[i];
            String senhaConvert2 = String.valueOf(senhaConvert);
            return senhaConvert2;
        } catch (NoSuchAlgorithmException ex) {
            ex.printStackTrace();
            return null;
        }
    }
    
    public static void main(String[] args) {
        String teste = Criptografia.criptografar("heverton");
        System.out.println("Tamanho:" + teste.length() + "\n" + teste);
        Comunicacao.iniciaComunicacao();
        int result = Comunicacao.inserirBanco(teste);
        System.out.println("Resultado: " + result);
    }
}

No metodo main ele tenta gravar no banco atraves do metodo “Comunicacao.inserirBanco(teste);” mas dar o seguinte erro:

Erro: SQL Exception org.postgresql.util.PSQLException: ERROR: character 0xefbeb8 of encoding "UTF8" has no equivalent in "LATIN1" at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryEx ecutorImpl.java:1525) at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutor Impl.java:1309) at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.ja va:188) at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Stat ement.java:452) at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(Abstract Jdbc2Statement.java:340) at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdb c2Statement.java:286) at catalogo_codata_servidor.Persistencia.inserirBanco(Persistencia.java: 148) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl. java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces sorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:294) at sun.rmi.transport.Transport$1.run(Transport.java:153) at java.security.AccessController.doPrivileged(Native Method) at sun.rmi.transport.Transport.serviceCall(Transport.java:149) at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:4 60) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport .java:701) at java.lang.Thread.run(Thread.java:595)

E ai como contorno isso? Vlws…

17 Respostas

H

upa ai

T

Quando for gravar dados binários, tais como os 16 bytes retornados pelo MD5, transforme-os para hexadecimal (use um campo de 32 caracteres no seu banco de dados). Isso evita problemas com bytes fora do intervalo 32 a 126.

H

so tem jeito de gravar passando p hexa? deixando em byte n dar ne? o exemplo de conversao p hexa eh o do tutorial do guj msm ne? vlw…

T

Se você tiver um campo BLOB pode até tentar gravar os dados em binário mesmo, mas acho muito, muito mais fácil usar um campo CHAR ou VARCHAR de 32 caracteres. Se o seu DBA reclamar que está usando muito espaço, você pode:

  • Usar só os primeiros 8 bytes do MD5, e converter para 16 caracteres. O problema é que você vai ter de lembrar que você truncou o MD5 para 16 caracteres.
  • Converter para Base-64 - (como “z0ttKpRp5sO/3u9aEgX2Cg==”), isso dá 24 caracteres, ou como você é esperto e deve ter percebido que os últimos caracteres são sempre “==”, pode usar 22 caracteres, e então negociar com o seu DBA para aumentar o campo para 22.
H

esse negocio d tamanho, no caso dessa app n vai importar mto, ja q n serao mtos usuarios e o campo senha so estará presente nos usuarios, entao a tabela tera no maximo 20 linhas, n sera uma tabela q irá crescer gradativamente, confere? Ou seja, quero uma maneira mais facil de fazer uma conversao e do banco aceitar os dados da senha. Thingol, teria como vc explicar como ocorre essa conversoes, principalmente essa de base 64, achei interessante ela. vlw…

T

Para Base-64 use alguma coisa que já está pronta (no Jakarta Commons existe uma. )
Muita gente usa sun.misc.BASE64Encoder e BASE64Decoder, mas aí você pode ter o problema de seu código só funcionar na JVM da Sun, não da IBM (WebSphere)ou da BEA (WebLogic).

H

puts, pensei q so existia jvm da sun. mas n eh empecilio tb, pois aki eh td da sun, vo fundo nesse basse 64 msm.

so umas duvidas:

1- passando p esse base 64, o banco n dara incompatibilidade de caracteres c o latin1 ne?

2- p converter p base 64, eu vo converter direto a string q foi pega no textfiled ou terei q converter a string ja codificada do md5?

T
  • Não. Base-64 usa apenas os seguintes caracteres:
    0-9, A-Z, a-z, +, =, /


2- p converter p base 64, eu vo converter direto a string q foi pega no textfiled ou terei q converter a string ja codificada do md5?

Não, base-64 converte bytes para string, e string para bytes.
Tire esse troço que você criou (“new String”).
new String” é a fonte e a raiz de todos os males (pelo menos de seu código :stuck_out_tongue: )

H

new String” onde? n seria new char[]?

coloca ai q eu n vi, ou to c a cabeca mto cheia q passou despercebido :smiley:

T

Ah, é verdade - você criou um array de caracteres. Vou explicar o que pode ter ocorrido para dar aquele erro esquisito:

  • O MD5 pode gerar bytes de 0 a 255 (ou melhor, de -128 a +127 - afinal de contas estamos falando em Java)
  • Quando você efetuou o cast de byte para char, então ele converteu os bytes de 0 a 127 para os caracteres de 0 a 127 (OK), e os bytes de -128 a -1 para os caracteres de 65408 até 65535.
  • Vários daqueles caracteres (0 a 31, 127, 65408 a 65535) não podem ser diretamente inseridos em bancos de dados, já que não representam caracteres válidos ASCII (no caso 65408 a 65535) ou então são caracteres de controle (0 a 31).
H

eu vo tirar essa conversao, mas eu so fiz isso pq eu precisava converter os byter p String p salvar no banco, como n dar p converter diretamente byter -> String (pelo menos eu n achei solucao p convresao direta), ai eu fiz Byte-> char[] -> String e passei p banco, mas vo tirar qnd refazer. Entendeu?

H

tu tens 1 exemplo de uso desse Base64? Vo ve se faco isso logo.

T

Use o Jakarta Commons, para evitar que você use a tal classe sun.misc. BASE64Encoder e BASE64Decoder. É só baixar e ver os exemplos que deve haver no tal pacote.

(Para exemplos com as mal-fadadas classes BASE64Encoder e Decoder, é só procurar no Google - acho que no próprio Java Almanac, ou então no java2s, deve haver um exemplo.

H

eh essa classe aki ne?
org.apache.commons.codec.binary.Base64

tipo, to dando uma olhada na api, e vi q ele criptografa(encode) e descriptografa(decode), n precisa definir chave publica nem privada, ne isso? Como n tem uso de chaves, se alguem pegar as senhas criptografadas no banco e tacar um decode nelas, ja vai ter a sanha do povo ne isso?

T

Acho que você não entendeu como funciona o MD5.

Digamos que você seja fanático pela Gisele Bündchen e use como senha:

GiseleBundchen2007

Se você for calcular o MD5 dos bytes que compõem essa senha, vai obter os seguintes bytes (imprimo em hexadecimal para facilitar):

515723cd1e9ebe6442e52c96a7b649fe

Agora pegue o seu colega, que sabe que você é fanático pela dona Gisele mas não acompanhou você digitando direito a sua senha. Ele acha que sua senha é:

giselebundchen2007

O MD5 é 4bc817a4af67ead0e4e402e46b5c72b9, que não se parece nem um pouquinho com o MD5 de sua senha.
A sua colega, aquela que você acha que é uma mala total e quer ver trancada com o Agostinho do Big Brother 6 para ver se ela deixa de ser xarope, é menos analfabeta que você e sabe que Bündchen se escreve com trema. Ela acha que sua senha é GiseleBündchen2007

O MD5 é 9a2bd5ad559bb4c92cce381ff70659b5.

Você viu que o MD5 nunca bate, exceto se você digitar corretamente sua senha.

Mas não é possível recuperar a senha a partir do MD5, a menos que você já a saiba de antemão.

H

eu saquei, eh pq eu vo usar o md5 + base 64 p passar p banco, confere?

eh pq pensei q ia usar so o base 64, mas ele eh meramente 1 encoding e n 1 “criptografador” (inventei isso agora, ehehe), eh +ou- isso ne?

H

AE thingol, vlw a ajuda finalmente resolvi, o problema era c conversao d byte -> char msm, qnd converti de byte -> string pegou blz. vo dx o codigo, caso alguem tenha msm problema:

public class Criptografia {
    
    public static byte[] criptografar(String senha) {
        try {
            byte[] senhaCript;
                                   
            MessageDigest md = MessageDigest.getInstance("MD5");
            //md.reset();
            senhaCript = md.digest(senha.getBytes());           
            //String senhaConvertida = txt2Hexa(senhaCript);
            return senhaCript;
        } catch (NoSuchAlgorithmException ex) {
            ex.printStackTrace();
            return null;
        }
    }
    
    public static String toBase64 (byte[] senhaBytes) {
        String senhaStr = new String(Base64.encodeBase64(senhaBytes));
        return senhaStr;
    }
    
    public static String txt2Hexa(byte[] bytes) {
        if( bytes == null ) return null;
        String hexDigits = "0123456789abcdef";
        StringBuffer sbuffer = new StringBuffer();
        for (int i = 0; i < bytes.length; i++) {
             int j = ((int) bytes[i]) & 0xFF;
             sbuffer.append(hexDigits.charAt(j / 16));
             sbuffer.append(hexDigits.charAt(j % 16));
        }
        return sbuffer.toString();
    }
    
    public static void main(String[] args) {
        byte[] teste2 = Criptografia.criptografar("heverton");
        String teste = Criptografia.toBase64(teste2);
        System.out.println("Tamanho:" + teste.length() + "\n" + teste);
        //Comunicacao.iniciaComunicacao();
        //int result = Comunicacao.inserirBanco(teste3);
        //System.out.println("Resultado: " + result);
    }
}

converte tanto d md5 -> base64, qto md5 -> hexa, bem util :D

Criado 9 de janeiro de 2007
Ultima resposta 12 de jan. de 2007
Respostas 17
Participantes 2