Conversão String para byte[] (Hexadecimal para byte[]) [RESOLVIDO]

Pessoal,

Não estou querendo os bytes de uma String através do “string”.getBytes()…

Utilizo a classe BigInteger para fazer uma conversão de bytes[] para uma representação dela em String na base16 (hexadecimal), porém estou tendo problemas para retornar essa String que foi gerada de volta para o byte[]… olha como estou fazendo:

[code]
byte[] byteSenha = “é1234”.getBytes();
System.out.println(“tamanho do byte da senha : “+ byteSenha.length);
System.out.println(”\nBytes da senha”);
for(int i=0; i<byteSenha.length; i++)
System.out.println("BYTE “+i+” : " + byteSenha[i]);

BigInteger hash = new BigInteger( 1, byteSenha);
String retornaSenha = hash.toString(16);
System.out.println("Convertendo em Hex : " + retornaSenha);[/code]

Saída:
tamanho do byte da senha : 5

Bytes da senha
BYTE 0 : -23
BYTE 1 : 49
BYTE 2 : 50
BYTE 3 : 51
BYTE 4 : 52
Convertendo em Hex : e931323334

Para retornar a senha de hex para a original, faço da seguinte forma:

[code]
byte[] byteHex = new BigInteger(senhaHexadecimal, 16).toByteArray();
System.out.println("TAMANHO BYTE HEX : " + byteHex.length);
System.out.println("Conversão para Decimal : " + new BigInteger(1, byteHex).toString(10));
byte[] byteDec = new BigInteger(new BigInteger(1, byteHex).toString(10), 10).toByteArray();
System.out.println("TAMANHO BYTE DEC : " + byteDec.length);

System.out.println("\nBytes da senha revertida");
for(int j=0; j><byteDec.length; j++)
System.out.println("BYTE “+j+” : " + byteDec[j]);[/code]

Saída
TAMANHO BYTE HEX : 6
Conversão para Decimal : 1001552753460
TAMANHO BYTE DEC : 6

Bytes da senha revertida
BYTE 0 : 0
BYTE 1 : -23
BYTE 2 : 49
BYTE 3 : 50
BYTE 4 : 51
BYTE 5 : 52

Ou seja, a reversão está me adicionando um byte 0 no inicio dela, por que?
Eu consegui visualizar que isto só acontece quando a senha convertida para hexadecimal começa com letra… caso ela comece com um número, isto não acontece… por exemplo, teste ao inves da senha é1234 uma e1234… funciona normal o processo de reversão.

OBS: Caso esteja procurando processo de conversão de senha para hexadecimal, NUNCA utilize desta forma q utilizei, fiz esse exemplo acima apenas para teste… leia sobre os algoritmos de criptografia SHA-1 ou MD5 e faça esse processo acima sobre os códigos gerados nos algoritmos de criptografia.>

Não use BigInteger para efetuar esse tipo de conversão. É que ele tem de pôr um byte zero na frente do número, se o número for positivo em vez de negativo e o bit mais significativo do primeiro byte for 1.

Hum… não entendi muito bem… olhando para os bytes que eu utilizei qual foi o critério para ele adicionar esse 0?

Que outra forma eu posso utilizar para fazer a conversão?

Valew!

É assim. Um BigInteger é um número, só que representado com bytes. O sinal é posto no bit mais significativo do primeiro byte - se for positivo, o bit é zero, e se for negativo, o bit é 1.

Por exemplo, para representar o número -1, os bytes do BigInteger correspondente são “FF” (em hexadecimal); em binário, seria 11111111.

Para representar o número +1, os bytes do BigInteger são “01”, ou seja, em binário, 00000001.

No seu caso (em que você passou alguns bytes, sendo que o primeiro tem o bit mais significativo igual a 1), então ele tentou considerar como um número, só que por algum motivo ele disse que era um número positivo, e então ele pôs o tal do byte 0 que está lhe incomodando. Esse byte 0 serve para tornar o número positivo.

Putz… Entendi!!

Pior q eu não posso fazer uma validação no byte do BigInteger do tipo: Se o byte[0] == 0 e o byte[1] == negativo = remove o byte[0] né… pois pode ser que a o byte da senha começe realmente dessa forma…

como eu posso resolver esse problema? o q eu utilizo?

Eu normalmente uso o seguinte método (hex) para converter o array de bytes para uma string - ele é rápido e eficiente, e não tem esse problema de “tascar um zero onde não deve”.

import java.util.*;
import java.io.*;
import java.security.*;

class TesteMD5 {
    private static char[] hexDigits = "0123456789ABCDEF".toCharArray();
    private static String hex (byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append (hexDigits[(b & 0xF0) >>> 4]).append (hexDigits[b & 0x0F]);
        }
        return sb.toString();
    }

    public static String calcMD5 (File f) {
        try {
            MessageDigest md = MessageDigest.getInstance ("MD5");
            InputStream is = null;
            try {
                is = new BufferedInputStream (new FileInputStream (f));
                byte[] buf = new byte[8192];
                for (int nBytes = is.read (buf, 0, buf.length); nBytes > 0; nBytes = is.read (buf, 0, buf.length)) {
                    md.update (buf, 0, nBytes);
                }
            } catch (IOException ex) {
                if (is != null) try { is.close(); } catch (IOException ex2) { }
            }
            byte[] digest = md.digest();
            return hex (digest);
        } catch (NoSuchAlgorithmException ex) {
            // MD5 sempre está disponível
            throw new RuntimeException ("Can't happen", ex);
        }
    }
    public static void main (String[] args) {
        System.out.println (calcMD5 (new File ("teste.bin")));
    }
}

Então, mas dessa forma que vc faz vc ta recebendo um byte[] e retornando uma String, no método “private static String hex (byte[] bytes)”.
Porém eu preciso fazer o processo inverso desse método… receber uma String e retornar o byte[]. Só que não é utilizar o “string”.getBytes()

Por exemplo… Chamei seu método passando um byte[] (10, 20, 30) e vamos supor q ele me retornou uma String “abc”
Supondo q eu só tenha o “abc” eu preciso achar uma forma q passando esse “abc” me retorne byte[] (10, 20, 30).

tem alguma ideia?

Você quer “abc” -> new byte {0x61, 0x62, 0x63} ou “abcd” -> new byte {0xAB, 0xCD} ?

No primeiro caso, basta usar “abc”.getBytes(). No segundo, eu devo tar alguma coisa pronta.

Assim, vamos supor que eu tenha apenas o hexadecimal: “746573746573656e6861” gerado através da sua rotina.

Como vc faria para fazer o processo inverso desse hexadecimal? ou seja, voltar ele para o byte[] e voltar para o texto que esse byte[] representa.

    public static byte[] fromHex (final String s) {
        if (s.length() % 2 != 0) throw new IllegalArgumentException ("O comprimento da string hexadecimal deve ser par");
        byte[] ret = new byte [s.length() / 2];
        for (int i = 0; i < ret.length; ++i) {
            try {
                ret[i] = (byte) Integer.parseInt (s.substring (i * 2, i * 2 + 2), 16);
            } catch (NumberFormatException ex) {
                throw new IllegalArgumentException ("A string contém algum caracter fora de 0-9 e A-F");
            }
        }
        return ret;
    }

Opa! serviu como uma luva…

É isso q o BigInteger faz, mas ele coloca aquele maldito byte 0 rsrs…

Valew mano!! obrigadão

Valeu … Me ajudou também.