Criptografia de dados no java

8 respostas
R

Bom, minha dúvida pode ser simples para alguns mas apesar de dar uma olhada na parte de criptografia do site do java ainda não entendi como funciona (http://java.sun.com/j2se/1.5.0/docs/guide/security/CryptoSpec.html#SimpleEncrEx) …
Estou precisando criar uma classe genérica com dois métodos, 1 pra criptografar e outro pra descriptografar, o método de criptografar irá ser chamado quando antes de setar o dado no banco e o de descriptografar quando recuperar …

Esse lance de Secret key, Cipher e etc ficou muito complicado … a solução que achei para meu problema era setar uma senha como uma string constante na classe genérica e usaria ela tanto para cript como decript … Alguém pode me ajudar a respeito? Se alguem tiver algum exemplo para criptografar e descriptografar dados tb agradeceria …
Abraços

8 Respostas

T

Você não vai fazer “criptografia” mas sim “esconder os dados” - já que qualquer carinha que tem acesso à seu .class pode obter os dados.

A palavra-mágica é PBE; vou ver se tenho um exemplo pronto para isso.

R

correto, só que esse .class ficará no lib do framework que uso aqui na empresa =), ninguem tem acesso …

R

e ai thingol, achou esse exemplo seu para salvar minha pele? =)

R
Andei pesquisando o PBE que vc me aconselhou e percebi que existem dois métodos para ajudar, que são:

int	getIterationCount()

Returns the iteration count or 0 if not specified.	

byte[]	getSalt()

Returns the salt or null if not specified.

A minha dúvida não é somente no caso do que utilizar, mas sim como utilizar a criptografia no java, até mesmo usando essa solução que sugeriu … Usar o Cipher e etc … nunca fiz nada quanto a criptografia =/

T

Vamos lá.

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.*;
import java.security.spec.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.KeySpec;
import sun.misc.BASE64Encoder; // para simplificar o exemplo. Use alguma outra classe para converter
import sun.misc.BASE64Decoder; // para Base-64.
public final class PWSec {
    private static SecretKey skey;
    private static KeySpec ks;
    private static PBEParameterSpec ps;
    private static final String algorithm = "PBEWithMD5AndDES";
    private static BASE64Encoder enc = new BASE64Encoder();
    private static BASE64Decoder dec = new BASE64Decoder();
    static {
        try {
            SecretKeyFactory skf = SecretKeyFactory.getInstance(algorithm);
            ps = new PBEParameterSpec (new byte[]{3,1,4,1,5,9,2,6}, 20);

            ks = new PBEKeySpec ("EAlGeEen3/m8/YkO".toCharArray()); // esta é a chave que você quer manter secreta.
            // Obviamente quando você for implantar na sua empresa, use alguma outra coisa - por exemplo,
            // "05Bc5hswRWpwp1sew+MSoHcj28rQ0MK8". Nao use caracteres especiais (como ç) para nao dar problemas.

            skey = skf.generateSecret (ks);
        } catch (java.security.NoSuchAlgorithmException ex) {
            ex.printStackTrace();
        } catch (java.security.spec.InvalidKeySpecException ex) {
            ex.printStackTrace();
        }
    }
    public static final String encrypt(final String text)
        throws
        BadPaddingException,
        NoSuchPaddingException,
        IllegalBlockSizeException,
        InvalidKeyException,
        NoSuchAlgorithmException,
        InvalidAlgorithmParameterException {
            
        final Cipher cipher = Cipher.getInstance(algorithm);
        cipher.init(Cipher.ENCRYPT_MODE, skey, ps);
        return enc.encode (cipher.doFinal(text.getBytes()));
    }
    public static final String decrypt(final String text)
        throws
        BadPaddingException,
        NoSuchPaddingException,
        IllegalBlockSizeException,
        InvalidKeyException,
        NoSuchAlgorithmException,
        InvalidAlgorithmParameterException {
            
        final Cipher cipher = Cipher.getInstance(algorithm);
        cipher.init(Cipher.DECRYPT_MODE, skey, ps);
        String ret = null;
        try {
            ret = new String(cipher.doFinal(dec.decodeBuffer (text)));
        } catch (Exception ex) {
        }
        return ret;
    }
    public static void main(String[] args) throws Exception {
        String password = "3p6/Lsbp+MIK8zqK"; // esta é a tal senha do banco de dados que você quer criptografar
        String encoded = PWSec.encrypt (password);
        System.out.println (encoded);  // imprime "4fWCjTdEhMPEluqE2n8ci4FiqWeb+DXc"
        System.out.println (PWSec.decrypt (encoded).equals (password)); // imprime "true"
        // Vamos alterar um caracter, só para ver o que ocorre
        char[] enc = encoded.toCharArray();
        enc[2] = (char) (enc[2] + 1);
        encoded = new String (enc);
        System.out.println (encoded); // imprime "4fXCjTdEhMPEluqE2n8ci4FiqWeb+DXc"
        System.out.println (password.equals (PWSec.decrypt (encoded))); // imprime "false"
    }
}
R

Muito obrigado thingol … qualquer coisa estamos ai … =))

R

Thingol, achei uma resposta sua a tempos aqui no fórum sobre o uso do “salt” e do “iteration count” que é essa:

"O “salt” deve ser diferente para cada mensagem criptografada com a mesma senha (tipicamente é um dado aleatório).
Esse “salt” deve ser enviado com a mensagem criptografada, em claro. É que esse “salt” ajuda a evitar alguns problemas que ocorreriam se você sempre produzisse a mesma mensagem criptografada para a mesma mensagem em claro, com a mesma senha. (É parecido com o conceito do “initialization vector” do modo CBC, CFB e OFB; na verdade, o IV é função desse salt.).
Se puder, use um salt com o mesmo tamanho do IV para o algoritmo em questão (16 bytes para AES, 8 bytes para DES).

O “iteration count” é a contagem de iterações de um algoritmo que recebe como parâmetros a senha e o salt, para produzir a chave e o IV. A idéia é que se o “iteration count” for muito grande (da ordem de 1000), demore muito para você obter a senha se por acaso você descobrir a chave."

Pois bem, o código que me enviou passa dados específicos como parâmetro do PBEParameterSpec para o “salt” e o “iteration count”, tentei procurar na API mas não está bem comentado e não consegui entender …
Será que tem como me explicar quando que preciso gerar dados aleatórios para o “salt”? O “iteration count” eu entendi … mas essa parte do “salt” está um pouco dificil pois estou precisando documentar o porque utilizei … Percebi que devido ao algoritmo DES utilizado tenho que gerar um salt de byte 8, só nao sei o que ele faz especificamente … poderia me ajudar?
Grato …

T

O uso do “salt” é opcional (se você não tiver como armazenar esse “salt” para cada mensagem criptografada, você pode fixá-lo, como fiz no código acima).

Usar o salt é interessante se você quiser proteção contra o seguinte ataque: a pessoa mal-intencionada pegou seu arquivo de senhas criptografadas, e conhece as senhas de alguns usuários. Só que ela descobriu que há várias senhas que, criptografadas, geram o mesmo resultado. Isso quer dizer que essas senhas são iguais. Por exemplo, o usuário “parreira”, “zagalo” e “tele” têm a mesma senha, que criptografada dá “qjl2IlSjWashTdaJq//BYg==”. Se você souber que a senha para o usuário “parreira” é “ronaldo”, então você vai descobrir que a senha para “zagalo” e “tele” é “ronaldo”.
Se usar o salt, você precisa gerar (e armazenar) um “salt” diferente para cada usuário. Digamos: “Ne5Wx5fmqdQ=”, “tz0Ga6E7Oo=” e “psPHVnBF86A=”. Mesmo que a senha seja igual para os três (“ronaldo”), ela será criptografada para resultados diferentes (“iGaCLw6XSHpEORO3L9J1rw==”, “iOmjvTsw9aG/l+kSM3Em1Q==” e “mXa6R6v0z77fwuJyU3x6jg==”) e você não vai conseguir descobrir a senha do Zagalo e do Telê dessa forma simples.

Criado 20 de junho de 2006
Ultima resposta 23 de jun. de 2006
Respostas 8
Participantes 2