Instabilidade na criptografia RSA

3 respostas
M

Boa tarde pessoal. Estou com um probleminha com um codigo para criptografia, voces poderiam me ajudar?

O problema é o seguinte. Estou fazendo um codigo para trabalhar com criptografia RSA usando a classe Cipher. Eu vou usar o RSA para criptografar um blocos de textos grandes. Já sei que não é recomentado para isto, mas quero fazer mesmo assim. E de qualquer forma e meu erro aconteceu com o AES que seria o mais recomendado neste caso.

Vou criptografar um texto e joga-lo em um textArea para mostrar para o usuário. Entao eu tranformo o texto criptografado em String para jogar para o textArea depois pegar esta String transformar em bytes para porder descriptografar.

Neste ponto que acontece o problema. As vezes funciona, as vezes da um erro que vou postar mais no fim deste post.

Percebi tambem que a o byte da String que é o byte criptografado quando tranformado em byte novamente nao é igual ao primeiro.

Acho que o problema esta relacionado com a codificacao da String, mas ja usei UTF-8 e ISO-8859-1 mas nao deu certo.

Vi em uns topicos falando de uma classe chamada BASE64Encoder que é do Bouce Castle que acho que resolveria, mas nao gostaria de usa-la. Queria usar somente os recursos disponibilizados originalmente com o NetBeans.

Cipher cifra = Cipher.getInstance("RSA");
        KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA");
        KeyPair keys = keygen.generateKeyPair();
        
        cifra.init(Cipher.ENCRYPT_MODE, keys.getPublic());
        
        String txtToCrypt = "testetestetestetestetestetestetestetestetestetestetestetestetestetestetestetestetestetestetestetestemjnhbgvfcdxszawer" ; // limite de bytes para criptografia
        byte[] byteTxt = txtToCrypt.getBytes();
        byte[] txtCrypted = cifra.doFinal(byteTxt);
        
        System.out.println("tamanho string em byte, byteTxt = " + byteTxt.length);
        System.out.println("tamanho texto criptado em byte, txtCrypted = " + txtCrypted.length);
        
        String strTxtCrypted = new String(txtCrypted);
        // esta parte acontece porque preciso jogar o txt criptado em um textArea 
        // e voltar para descriptografalo
        byte[] newByteTxtCrypted = strTxtCrypted.getBytes();

        System.out.println("tamanho string de texto criptado, strTxtCrypted = " + strTxtCrypted.length());
        System.out.println("tamanho da string em bytes, newByteTxtCrypted = " + newByteTxtCrypted.length);
        System.out.println("newByteTxtCrypted e igual a txtCrypted = " + newByteTxtCrypted.equals(txtCrypted)); // teria qu ser igual
        
        cifra.init(Cipher.DECRYPT_MODE, keys.getPrivate());
        
        byte[] txtDecrypted = cifra.doFinal(newByteTxtCrypted);
        String strTxtDecrypted = new String(txtDecrypted);
        System.out.println("texto decriptografado = " + strTxtDecrypted);
        // da erro aqui mas acho que e por causa da codificacao da string

O erro que aparece é o seguinte:

init:

deps-jar:

compile-single:

run-single:

tamanho string em byte, byteTxt = 117

tamanho texto criptado em byte, txtCrypted = 128

tamanho string de texto criptado, strTxtCrypted = 128

tamanho da string em bytes, newByteTxtCrypted = 128

newByteTxtCrypted e igual a txtCrypted = false

Exception in thread main javax.crypto.BadPaddingException: Data must start with zero

at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:308)

at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:255)

at com.sun.crypto.provider.RSACipher.a(DashoA13*)

at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*)

at javax.crypto.Cipher.doFinal(DashoA13*)

at criptografia.Main.main(Main.java:133)

Java Result: 1

EXECUTADO COM SUCESSO (tempo total: 1 segundo)

Ate mais,

Mario Jose

3 Respostas

marciocamurati

Vi que você citou no post que já tentou usar o encode e que não resolveu mas como isso me parecia ser problema de encode mesmo que não está sendo setado resolvi fazer um teste com seu código e setando os encodes corretamente resolveu a questão nos meus testes, segue abaixo os trechos onde adicionei o encode para que você possa replicar meu teste utilizei o ISO-8859-1:

...
byte[] byteTxt = txtToCrypt.getBytes("ISO-8859-1");

...
String strTxtCrypted = new String(txtCrypted, "ISO-8859-1");
...
byte[] newByteTxtCrypted = strTxtCrypted.getBytes("ISO-8859-1");
...

Tendo como out:

--- RSA ---
tamanho string em byte, byteTxt = 117
tamanho texto criptado em byte, txtCrypted = 128
tamanho string de texto criptado, strTxtCrypted = 128
tamanho da string em bytes, newByteTxtCrypted = 128
newByteTxtCrypted e igual a txtCrypted = false
texto decriptografado = testetestetestetestetestetestetestetestetestetestetestetestetestetestetestetestetestetestetestetestemjnhbgvfcdxszawer
--- RSA ---

[]s

O

mariojose:
O erro que aparece é o seguinte:

init:

deps-jar:

compile-single:

run-single:

tamanho string em byte, byteTxt = 117

tamanho texto criptado em byte, txtCrypted = 128

tamanho string de texto criptado, strTxtCrypted = 128

tamanho da string em bytes, newByteTxtCrypted = 128

newByteTxtCrypted e igual a txtCrypted = false

Exception in thread main javax.crypto.BadPaddingException: Data must start with zero

at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:308)

at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:255)

at com.sun.crypto.provider.RSACipher.a(DashoA13*)

at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*)

at javax.crypto.Cipher.doFinal(DashoA13*)

at criptografia.Main.main(Main.java:133)

Java Result: 1

EXECUTADO COM SUCESSO (tempo total: 1 segundo)</blockquote>

O erro que está ocorrendo é em função de você não ter definido um “padding” para a sua mensagem. O “padding” completa a sua mensagem, pois um algoritmo de criptografia geralmente trabalha com um tamanho de mensagem proporcional ao tamanho da chave. Duas maneiras de você fazer isto: usar algum mecanismo de “padding” (Não lembro se o provider que vem com o JDK 1.5 suporta algum mecanimso de padding) ou você mesmo garante que sua mensagem tenha o tamanho correto (Não lembro qual era o default de tamanho de chave para RSA, mas acho que era 1024).

M

Olá pessoal.

Valeu pela ajuda Marcio, deu certo agora. Eu mexe tanto e fiz tantas alterações para fazer o codigo funcionar que acabou passando o esquema que voce me passou. Obrigado novamente

Valeu Oyama, eu tinha lido sobre o padding no material mas nao tinha endendido. Isso vai ser muito util para mim tambem. O tamanho do texto para mensagem com chave de 1024 é de 117 bytes. No meu codigo eu estou pegando o tamanho maximo que suporta para nao dar problema e evitar um loop maior no for. Obrigado novamente

Ate mais pessoal, obrigado por responderem tao prontamente.

Ate mais

Mario Jose

Criado 25 de novembro de 2007
Ultima resposta 27 de nov. de 2007
Respostas 3
Participantes 3