Problemas com getByte()

Pessoal, estou usando a criptografia DES.
No cliente eu passo a Chave e o texto para a funcao que vai criptografar e me retorna em byte o resultado, assim transmito para o servidor.

Já no servidor recebe o texto criptografado, e para descriptografar é necessário passar em byte. Mas o texto transmitido é em formato de string, e se uso a funcao:

byte [] byte_ex1 = (new String(buff.toString())).getBytes();

pega outro bytes e não do texto transmitido.

Vou mostrar o cliente:

  Encryptor teste = new Encryptor(Key);
              String txt = null;
              byte[] valor = null;
                try {

                    valor = teste.encryptString(message);
                    System.out.println("Crip. Cli: "+valor);
                    System.out.println("Crip_getBytes. Cli: "+valor.toString());
                    txt = valor.toString();
                    System.out.println("txt Cli: "+txt.toString());
                    System.out.println("txt getbytes: "+txt.getBytes());
                    
                } catch (CryptoException ex) {
                    ex.printStackTrace();
                }
              
              //envia
              //OS.write(valor);
              OS.write(txt.getBytes());
              OS.write("\n".getBytes());[quote]

Agora o Servidor:

[code]
SocketConnection client = (SocketConnection) Connector.open(“socket://localhost:5000”);
InputStream Is = client.openInputStream();

            StringBuffer buff = new StringBuffer();
            
            
         
            int dadosEntrada = 0;
        
                        
              while (((dadosEntrada = Is.read()) != '\n') && (dadosEntrada != -1)) {
                    buff.append((char) dadosEntrada);
                   System.out.println("dadosEntrada: "+ dadosEntrada);
                }

                        
            
               System.out.println("buff entrada: "+buff.toString());
               System.out.println("buff  valor: "+ buff);   
               
               
               

                textBox.setString(buff.toString());
                
             
           
          //Descriptografar
         
                                  
                Encryptor teste1 = new Encryptor(Key_serv);
             
                                               
                byte [] byte_ex1 = (new String(buff.toString())).getBytes(); 
                System.out.println("Desc: " + byte_ex1);
              
              try {   
                String desc = teste1.decryptString(byte_ex1);
                System.out.println("Desc: " + desc);
            } catch (CryptoException ex) {
                ex.printStackTrace();
            }
                [/code]

String != array de bytes

Ao converter bytes para uma string, alguns dos bytes são perdidos (a conversão é irreversível).
Portanto, é necessário codificar os bytes (usando hexadecimal, base-64 ou base-85) antes de convertê-los para uma string.
Vou dar um exemplo:

class StringNaoEhArrayDeBytes {
    public static void main(String[] args) throws Exception {
        byte[] bytes = new byte[256];
        // Primeiramente estamos preenchendo o array "bytes" com 
        // os valores de 0 até 255
        for (int i = 0; i < bytes.length; ++i) {
            bytes[i] = (byte) i;
        }
        // Agora vamos converter ingenuamente esse array de bytes para uma string. 
        // Vamos usar o "encoding" Windows-1252 porque é o que dá menos problemas
        String s = new String (bytes, "Windows-1252");
        // Vamos desconverter a string para um array de bytes.
        byte[] bytes2 = s.getBytes ("Windows-1252");
        // Agora vamos conferir para ver quais dos bytes foram convertidos erroneamente.
        for (int i = 0; i < bytes.length; i++) {
            byte b = (byte) i;
            if (bytes2[i] != b) {
                System.out.printf ("O byte 0x%02X foi perdido e transformado em 0x%02X (%c) %n",
                    (byte) i, 
                    bytes2[i],
                    (char) bytes2[i]);
            }
        }
    }
}

A saída desse programa é:

O byte 0x81 foi perdido e transformado em 0x3F (?)
O byte 0x8D foi perdido e transformado em 0x3F (?)
O byte 0x8F foi perdido e transformado em 0x3F (?)
O byte 0x90 foi perdido e transformado em 0x3F (?)
O byte 0x9D foi perdido e transformado em 0x3F (?)

Não adianta mudar o encoding (que nesse caso é Windows-1252). Vai dar problema com algum byte. (Teste, por exemplo, com "ASCII" e "UTF-8"). No caso "ISO-8859-1" parece que funciona, mas veja se isso também vale para outras versões do Java.

thingol,

acho que esse problema ele vai ter mais pra frente. para mim o problema agora é outro (linha 9 do cliente):

byte[] valor = null; (...) txt = valor.toString(); (...) OS.write(txt.getBytes());

Ou seja, quando ele faz um toString de um array, o retorno não vai ser os bytes trasformados num objeto String e sim algo como B@1a2b3c4d5e6f.

obrigado thingol,

Chego a conclusão que usar a criptografia simetrica DES de cliente para servidor numa aplicação J2me parece ser impossível.

A criptografia peguei do org.bouncycastle e me parece que funciona só para uma aplicação e nao para cliente servidor.

[quote=alerocha19]obrigado thingol,

Chego a conclusão que usar a criptografia simetrica RSA de cliente para servidor numa aplicação J2me parece ser impossível.

A criptografia peguei do org.bouncycastle e me parece que funciona só para uma aplicação e nao para cliente servidor.

[/quote]

Aham - RSA não é simétrica e deve ser usada com cuidados.
Um dos principais cuidados é que ela é bem lenta em ambiente Mobile devido à grande capacidade de processamento que ela exige; mas acho que esse é o único problema.
Outra coisa é que RSA só é útil para criptografar chaves, não os dados em si.
A terceira coisa é que ela trabalha com BigIntegers, não com arrays de bytes, então você precisa especificar um “padding” adequado se for usá-la para criptografar uma chave.

Mas ela poderia ser usada em ambiente Mobile; acho só que você está se confundindo todo com RSA, que não é para amadores.

[quote=bobmoe]thingol,

acho que esse problema ele vai ter mais pra frente. para mim o problema agora é outro (linha 9 do cliente):

byte[] valor = null; (...) txt = valor.toString(); (...) OS.write(txt.getBytes());

Ou seja, quando ele faz um toString de um array, o retorno não vai ser os bytes trasformados num objeto String e sim algo como B@1a2b3c4d5e6f.[/quote]

Para converter um array de bytes em uma string, NÃO USE toString e sim new String (byte[], String) onde o primeiro parâmetro é o array a ser convertido e o segundo é o encoding adequado. (Não sei se isso existe em JavaME).

[quote=thingol][quote=bobmoe]thingol,

acho que esse problema ele vai ter mais pra frente. para mim o problema agora é outro (linha 9 do cliente):

byte[] valor = null; (...) txt = valor.toString(); (...) OS.write(txt.getBytes());

Ou seja, quando ele faz um toString de um array, o retorno não vai ser os bytes trasformados num objeto String e sim algo como B@1a2b3c4d5e6f.[/quote]

Para converter um array de bytes em uma string, NÃO USE toString e sim new String (byte[], String) onde o primeiro parâmetro é o array a ser convertido e o segundo é o encoding adequado. (Não sei se isso existe em JavaME).

[/quote]

eu não disse para ele fazer isso, mas sim apontei o erro.

OK.

Pessoal,

Então se eu tenho uma variável String que o conteúdo dela é bytes, assim por exemplo:

Variável texto com conteúdo: [B@f828ed68

Não tem como passar esse conteúdo: [B@f828ed68 para um array de bytes ??

Já que quando uso o comando:

byte[] val = (new String(texto.toString())).getBytes();

Esse comando joga para val outros bytes e nao o [B@f828ed68

“[B@f828ed68” quer dizer: “O array de bytes (”[B") que tem o default hash code 0xf828ed68". Isso não serve para absolutamente nada, exceto para você perceber que não é para usar “toString” para um array de bytes.

O que você deve fazer para converter um array de bytes para uma string (e aceitando que pode haver perdas) é

String s = new String (texto); // onde texto é um array de bytes, não criptografados

ou se isto estiver disponível,

String s = new String (texto, "ISO-8859-1"); // onde texto é um array de bytes.

valeu enantiomero, vou vê o que dá para fazer.

Pessoal finalmente consegui fazer funcionar cliente/servidor para J2me com a criptografia simetrica do Bouncy Castle.
Onde eu passo o texto que quero criptografar para o método que me retorna um array de bytes e para descriptografar passo o array de bytes que me devolve o texto em string. Obrigado pela atenção de todos. Qualquer dúvida meu email é alerocha19@ig.com.br

Para quem um dia alguém precisar me comunique.

O algoritmo DES que usei é:

[code]import org.bouncycastle.crypto.;
import org.bouncycastle.crypto.engines.
;
import org.bouncycastle.crypto.modes.;
import org.bouncycastle.crypto.params.
;

// A simple example that uses the Bouncy Castle
// lightweight cryptography API to perform DES
// encryption of arbitrary data.

public class Encryptor {

private BufferedBlockCipher cipher;
private KeyParameter key;

// Initialize the cryptographic engine.
// The key array should be at least 8 bytes long.

public Encryptor( byte[] key ){
    /*
    cipher = new PaddedBlockCipher(
             new CBCBlockCipher(
             new DESEngine() ) );
     */
    
    cipher = new PaddedBlockCipher(
            new CBCBlockCipher(
            new BlowfishEngine() ) );
    
    this.key = new KeyParameter( key );
}

// Initialize the cryptographic engine.
// The string should be at least 8 chars long.

public Encryptor( String key ){
    this( key.getBytes() );
}

// Private routine that does the gritty work.

private byte[] callCipher( byte[] data )
throws CryptoException {
    int    size =
            cipher.getOutputSize( data.length );
    byte[] result = new byte[ size ];
    int    olen = cipher.processBytes( data, 0,
            data.length, result, 0 );
    olen += cipher.doFinal( result, olen );
    
    if( olen < size ){
        byte[] tmp = new byte[ olen ];
        System.arraycopy(
                result, 0, tmp, 0, olen );
        result = tmp;
    }
    
    return result;
}

// Encrypt arbitrary byte array, returning the
// encrypted data in a different byte array.

public synchronized byte[] encrypt( byte[] data )
throws CryptoException {
    if( data == null || data.length == 0 ){
        return new byte[0];
    }
    
    cipher.init( true, key );
    return callCipher( data );
}

// Encrypts a string.

public byte[] encryptString( String data )
throws CryptoException {
    if( data == null || data.length() == 0 ){
        return new byte[0];
    }
    
    return encrypt( data.getBytes() );
}

// Decrypts arbitrary data.

public synchronized byte[] decrypt( byte[] data )
throws CryptoException {
    if( data == null || data.length == 0 ){
        return new byte[0];
    }
    
    cipher.init( false, key );
    return callCipher( data );
}

// Decrypts a string that was previously encoded
// using encryptString.

public String decryptString( byte[] data )
throws CryptoException {
    if( data == null || data.length == 0 ){
        return "";
    }
    
    return new String( decrypt( data ) );
}

}[/code]

Para rodar e executar crie um arquivo midlet:

[code]/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.
    */

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.Reader;
import javax.microedition.midlet.;
import javax.microedition.lcdui.
;
import org.bouncycastle.crypto.CryptoException;

/**

  • @author usuario
    */
    public class Midlet extends MIDlet {
    public void startApp() {

     String key = "asdf";
     
     Encryptor obj = new Encryptor(key); 
     
     String txt = "cuiabá";
     
     byte[] res = null;
         try {
             res = obj.encryptString(txt);
         } catch (CryptoException ex) {
             ex.printStackTrace();
         }
     
     System.out.println("Crip: "+res);
     
    
    String str = null; 
     try {
         str = obj.decryptString(res);
     } catch (CryptoException ex) {
         ex.printStackTrace();
     }
      
     
     System.out.println("Descrip: "+str);
    

    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
    }
    }
    [/code]

Sabe me dizer se é possivel usar o bouncycastle com Jsp ? Preciso na verdade criptografar um arquivo de texto e depois ler pela minha Midlet

Cara, eu sei que existe uma biblioteca especifica para trabalhar com Criptografia no JSP, da uma olhada neste link:

http://jcetaglib.sourceforge.net/