Criptografia de dados no java

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

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.

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

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

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 =/

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"
    }
}

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

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 …

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.