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.