Erro Casting Object to SealedObject

Galera do GUJ,

Estou recebendo a seguinte mensgem de erro:

[code]Exception in thread "Chat" java.lang.ClassCastException: java.lang.String cannot be cast to javax.crypto.SealedObject
at DecryptMsg.decrypt(DecryptMsg.java:51)
at GrafClient$Reader.run(GrafClient.java:268)[/code]

A linha do erro (linha 51) está em negrito e marcada como comentário.

Os códigos que estão envolvidos com a mensagem acima estão logo abaixo:

[code]public class Reader extends Thread {

    protected GrafClient cliente;
    private JTextArea OutputArea;
	  
    public Reader(GrafClient c, JTextArea OutputArea) {
	
       super("Chat");
       this.cliente=c;
       this.OutputArea = OutputArea;
    }

    public void run()  {
	
      DataInputStream in = null;
      String line, result = "";		  
      Object objcif;
		  
      try {
	      
         in = new DataInputStream(cliente.clisoc.getInputStream());
	    
         while(true){
	    	  
              line = in.readLine();
   	              objcif = line;
              result = DecryptMsg.decrypt(key2, objcif);
              OutputArea.append(name + "> " +result +"\r\n");
          }

 	      } catch(IOException e) {
           System.out.println("Reader:"+e);
      }
}
       }[/code]



         [code] public static String decrypt(PrivateKey privk, Object objcif) {
	    
    Cipher c;
    String s ="";	
    SealedObject objcifrado;
    	   
    try {
    	
    	c = Cipher.getInstance("RSA");
    	c.init(Cipher.DECRYPT_MODE, privk);
                            // linha do erro (51)
    	[b]objcifrado = (SealedObject) objcif;[/b]
    	s = (String)objcifrado.getObject(c); 
		
	} catch (NoSuchAlgorithmException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (NoSuchPaddingException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (InvalidKeyException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (IllegalBlockSizeException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (BadPaddingException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (ClassNotFoundException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	
	return s;

	 
}[/code]

  Neste caso eu envio um objeto tipo SealedObject criptografado para o Servidor e depois que recebo dele para assim descriptografá-lo e assim compreender a mensagem.

  Raphael

Isso me parece bem simples…

A linha DecryptMsg.decrypt(key2, objcif); grava uma String no seu atributo Object objcif;

Não se pode efetuar casting de String para SealedObject porque String não é (não extende em nenhum nível) SealedObject…

Veja bem de onde vc tirou esse algoritmo pra saber como você coloca a sua String dentro do SealedObject…

:wink:

Haveria alguma outra condição ou opção pra resolver este problema?

No aguardo…

Raphael

Bom, de onde vem a classe DecryptMsg?

[quote=rapha]
Haveria alguma outra condição ou opção pra resolver este problema?

No aguardo…

Raphael[/quote]

A classe DecryptMsg é uma classe separada que implementa o método decrypt, que tem objetivo de : utilizando a chave privada do usuário, fazer a descriptografia do objeto criptografado SealedObject.

Raphael

Então, sem conhecer o método eu não posso te esclarecer o que acontece. Só sei que o método em questão grava uma String na referência recebida!

:wink:

[quote=rapha]
A classe DecryptMsg é uma classe separada que implementa o método decrypt, que tem objetivo de : utilizando a chave privada do usuário, fazer a descriptografia do objeto criptografado SealedObject.

Raphael[/quote]

O que o método realiza está informado no início do tópico. Precisa ver mais alguma coisa?

Amigo, leia a documentação antes de ficar desesperado.

Se tivesse lido adequadamente a documentação de SealedObject, teria visto que há um método getObject que faz exatamente o que você precisa.

SealedObject

E não se esqueça - repita comigo (de preferência usando um terço, para poder contar 100 vezes): cast não faz conversão em Java.

Ahuahuahuahua, lembrei do Bart Simpson na lousa agora…

É verdade… então veja essa linha:

s = (String)objcifrado.getObject(c);

Claramente o objeto devolvido é uma String, somente por isso o casting (String) não causa uma ClassCastingException, vide o que o Thingol disse, mas esse objeto nunca será diferente de uma String (um SealedObject, por exemplo).

Agora veja a linha anterior:

objcifrado = (SealedObject) objcif;

Veja que o SealedObject é o objcif (senão haveria também uma ClassCastingException, vide o que o Thingol disse)… então, somando 1 + 1…

O objcifrado contém uma String. O método está devolvendo essa String, não o próprio SealedObject.

Pense mais um pouco com calma… você está perto de desvendar o mistério!

:wink:

Valeu Thingol… mas não vou rezar não. Já entendi a questão. E não estou desesperado também não. Estou só querendo entender a questão que estou tentando explicar. Eu já tinha lido uma parte da documentação do SealedObject, mas então o método que você cita pode resolver tudo q preciso?
Então… vou pensar mais um pouco Fox McCloud, mas pode me dar uma luz agora?

Eu recebo uma String do servidor e armazeno na variável line como está logo abaixo:

line = in.readLine(); 
Detalhe importante... um dos parâmetros que devo passar para o método decrypt é do tipo SealedObject, que no caso é o objeto que foi encriptado por outro método [i]encrypt[/i]. No caso eu recebo uma String e não um SealedObject.

Podem me dar a luz que preciso?

Raphael

Construtor SealedObject

Como toda String implementa Serializable…

Thingol ainda não está claro por sua explicação. Acredito que entendeu o que expliquei. Seja mais claro e me mostre como posso fazer.

Basicamente você quer saber como é que se chega a uma String, dado um SealedObject, e como se chega a um SealedObject, dada uma String.

A ideia é que um SealedObject é equivalente ao objeto original, só que criptografado. Para tanto, você precisa de uma forma de cifrar ou decifrar os dados.

Quando você usa o construtor de SealedObject que recebe um objeto qualquer que possa ser serializado, o que o tal construtor faz? Ele pega o tal objeto, efetua sua serialização para um array de bytes, cifra-o usando o objeto do tipo Cipher que você passou como parâmetro, e então monta o tal objeto SealedObject.

Quando você usa o método getObject de SealedObject, que recebe um Cipher como parâmetro, ele decifra um array de bytes que ele tem internamente, e então “desserializa” para um objeto equivalente ao objeto original (que seria uma String).

Valeu Thingol. Vou testar aqui.

Qualquer dúvida se não achar ruim, volto a perguntar aqui novamente.

Raphael

O Thingol… aproveitando mais um pouco. Me dá uma luz como posso fazer a nível de código essa parte.

Eu preciso de um objeto tipo SealedObject para enviar para o meu método decrypt e assim retornar o objeto ao estado original (descriptografar).

Valeu

Um exemplo bobo, usando SealedObject. Não posso resolver o seu problema em particular, mas você pode usar isto como referência.


import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SealedObject;


class ExemploGeracaoParChavesRSA {
    public KeyPair generateKeyPair () throws NoSuchAlgorithmException {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance ("RSA");
        kpg.initialize (1024);
        kp = kpg.generateKeyPair ();
        return kp;
    }
    public Cipher getEncryptingCipher () throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException {
        Cipher cipher = Cipher.getInstance ("RSA");
        cipher.init (Cipher.ENCRYPT_MODE, kp.getPublic ());
        return cipher;
    }
    public Cipher getDecryptingCipher () throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
        Cipher cipher = Cipher.getInstance ("RSA");
        cipher.init (Cipher.DECRYPT_MODE, kp.getPrivate ());
        return cipher;
    }
    private KeyPair kp;
}

/**
 *
 */
public class ExemploSealedObject {
    public String decrypt (SealedObject so) throws IOException, ClassNotFoundException, IllegalBlockSizeException, BadPaddingException {
        return (String) so.getObject (decryptingCipher);
    }
    public SealedObject encrypt (String str) throws IOException, IllegalBlockSizeException {
        return new SealedObject (str, encryptingCipher);
    }
    public void setEncryptingCipher (final Cipher encryptingCipher_) {
        encryptingCipher = encryptingCipher_;
    }
    public void setDecryptingCipher (final Cipher decryptingCipher_) {
        decryptingCipher = decryptingCipher_;
    }
    private Cipher encryptingCipher;
    private Cipher decryptingCipher;

    public static void main (String[] args) throws Exception {
        ExemploSealedObject eso1 = new ExemploSealedObject();
        ExemploSealedObject eso2 = new ExemploSealedObject();
        Cipher encryptingCipher;
        Cipher decryptingCipher;
        // Vamos criar um par de chaves RSA, só para ver como é.
        // Você poderia pegar a chave do keystore, por exemplo. 
        ExemploGeracaoParChavesRSA ex = new ExemploGeracaoParChavesRSA();
        ex.generateKeyPair ();
        encryptingCipher = ex.getEncryptingCipher ();
        decryptingCipher = ex.getDecryptingCipher ();
        eso1.setEncryptingCipher (encryptingCipher);
        SealedObject so = eso1.encrypt ("Hello, world!");
        eso2.setDecryptingCipher (decryptingCipher);
        String str = eso2.decrypt (so);
        System.out.println (str);
        // Saída esperada:
        // "Hello, world!"
    }
}

OK Thingol. Mas só pra entender. Porque não pode resolver este meu problema ?

Raphael