Criptografar / Descriptografar texto / informação

Pessoal,
Estou criando um programinha para guardar informação importante criptografada e quando eu quiser simplesmente colocar minha senha e decriptografar a informação, porém nao estou encontrando uma forma de decriptografar a informação.

Ja consegui criptografar utilizando md5, porem md5 nao permite que eu decriptografe, ja procurei na net algumas opções, mas os exemplos que eu achei simplesmente nao funcionam e nao consegui entender o motivo.
Alguem poderia me ajudar a montar uma funcao para criptografar / decriptografar uma informação ?

De preferencia fazer a criptografia utilizando uma chave,

ex:

public String criptografar(String info, String chaveCriptografia){

    return stringCriptografada;
}

public String decriptografar(String info, String chaveCriptografia){

    return stringDecriptografada;
}

obrigado !

Completando com mais uma informação, eu gostaria de criptografar da forma mais segura possivel, pois eu tava vendo e tem umas formas de criptografias muito antigar na api java… queria algo tipo 256 bits ou 512 bits

Para usar 256 ou mais bits no Java, use AES e altere os arquivos (procure uns arquivos chamados “Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 6”) no diretório jre\lib\security na sua instalação do JDK:

local_policy.jar
US_export_policy.jar

Nós usamos aqui 256 bits e AES em um sistema desktop+web rodando sob Java 1.4.2_08 e funciona muitíssimo bem. Ele até fecha conexões SSL em 256 bits com o browser Firefox.

Obrigado,

teria como vc postar algum exemplo ou parte de um codigo para eu veisualizar melhor o que eu teria que fazer ?

hoje estou fazendo assim :

MessageDigest md5=null;
		try {
			md5 = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		md5.update("Elvis esta vivo".getBytes());
		md5.
		String elvis = new String(md5.digest());
		md5.update("Beatles esta vivo".getBytes());
		String beatles = new String(md5.digest());
		System.out.println(elvis + " >> "+ beatles );
		System.out.println("\n iguais ? " + MessageDigest.isEqual(elvis.getBytes(),elvis.getBytes() ));

mas o problema é que nao consigo decriptografar com md5,
tentei utilizar um exemplo que peguei na web, mas esta dando um erro que nao consegui resolver, Ainda, segue codigo abaixo

private static PBEParameterSpec ps = null; 
	private static final String algorithm = "PBEWithMD5AndDES";  
	private static BASE64Encoder enc = new BASE64Encoder();  
	private static BASE64Decoder dec = new BASE64Decoder();
	static {
		ps = new PBEParameterSpec (new byte[]{3,1,4,1,5,9,2,6}, 20);
	}
	public static String criptografa(String texto, String senhaCriptografia)throws BadPaddingException,NoSuchPaddingException,IllegalBlockSizeException,InvalidKeyException,NoSuchAlgorithmException,InvalidAlgorithmParameterException, InvalidKeySpecException {
		
		PBEKeySpec ks = new PBEKeySpec (senhaCriptografia.toCharArray()); // esta é a chave que você quer manter secreta.  
		
		SecretKeyFactory skf = SecretKeyFactory.getInstance(algorithm);
		SecretKey skey = skf.generateSecret(ks);
		
		Cipher cipher = Cipher.getInstance(algorithm);
		cipher.init(Cipher.ENCRYPT_MODE, skey);  
		
		return enc.encode (cipher.doFinal(texto.getBytes()));  
	}  
	public static String decriptografa(String texto, String senhaCriptografia) throws BadPaddingException,NoSuchPaddingException,IllegalBlockSizeException,InvalidKeyException,NoSuchAlgorithmException,InvalidAlgorithmParameterException, InvalidKeySpecException {  
		 
		PBEKeySpec ks = new PBEKeySpec (senhaCriptografia.toCharArray()); // esta é a chave que você quer manter secreta.  
		
		SecretKeyFactory skf = SecretKeyFactory.getInstance(algorithm);
		SecretKey skey = skf.generateSecret(ks);
		
		Cipher cipher = Cipher.getInstance(algorithm);
		  
		cipher.init(Cipher.DECRYPT_MODE, skey);  
		String ret = null;  
		try {  
			ret = new String(cipher.doFinal(dec.decodeBuffer (texto)));  
		} catch (Exception ex) {  
		}  
		return ret;  
	}  

mas nao sei qual o nivel de seguranca desta criptografia e o codigo de decriptografia nao funciona.

Pessoal,

Foi burrice minha mesmo.
Passei a string nao criptografada para o metodo descriptografar
ai tava dando erro pois encontrava caracteres estranhos no lugar …
o metodo esta funcionando.

abraços e obrigado pela atencao.

Olá mackalister!

md5 não tem como descriptografar.
e a explicação resumida é mais ou menos esta:
se vc tem uma msg: ‘37’,
3+7 = 10
seu md5 seria 10.
se vc sabe que sua msg tem 2 letras, não
dá pra saber qual era a sua msg original.
ela poderia ser:
19 ou 28 ou 37 ou 46 … e assim por diante
imagina uma msg com 400 letras…

Já ouviu falar de RSA?

Ela é baseada em numeros primos muito grandes.

a explicação matematica está em:
http://pajhome.org.uk/crypt/rsa/rsa.html

o tempo computacional para criptografar a msg é x
para descriptografar, SE VC TIVER a chave é por exemplo 50x
não tendo a chave, dependendo do seu PC, levaria milhares
de anos para quebrar a criptografia.

um code de criptografia e decriptografia em java:
http://julian.com.br/dokuwiki/rsa
Mas neste code o numero maior é de tipo long

O ideal é contruir seu code com bigInteger.
para isso é necessario conhecimento sobre algumas funções como :
Biginteger (principalmente esta);
isPrime…

Outro site onde existe um code é em:
http://ohdave.com/rsa/
mas está em JavaScript.
Nele dá pra entender como é feito um bigInt.

Como você demonstrou preocupação com o algoritmo de criptografia, eu não recomendaria usar “PBEWithMD5andDES”.
Aqui tem uma lista de algoritmos que podem ser usados para PBE. Siga a dica do thingol e use AES que é considerado um dos algoritmos mais seguros e “rápidos” atualmente. Mude o algoritmo de digest para SHA1.

pessoal,
com a ajuda de voces fiz esta classe utilitaria, vou postar aqui pois pode ajudar mais alguem no futuro,
caso encontrem formas de melhorar este codigo agradecerei muito com mais essa ajuda.
segue abaixo:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class CriptografiaUtil {
	//private static SecretKey skey;  
	/**
	 * CHAVE DEVE CONTER ATE 24 CARACTERES
	 */
	public static final String ALGORITMO_TRIPLE_DES = "DESede";
	/**
	 * CHAVE DEVE CONTER ATE 8 CARACTERES
	 */
	public static final String ALGORITMO_DES = "DES";
	/**
	 * CHAVE DEVE CONTER ATE 16 CARACTERES
	 */
	public static final String ALGORITMO_BLOWFISH = "Blowfish";
	/**
	 * CHAVE DEVE CONTER ATE 16 CARACTERES
	 */
	public static final String ALGORITMO_AES = "AES";
	
	private static Map tamanhosChaves = new HashMap();
	
	private static BASE64Encoder enc = new BASE64Encoder();  
	private static BASE64Decoder dec = new BASE64Decoder();  

	static {
		tamanhosChaves.put(ALGORITMO_TRIPLE_DES, new Long(24));
		tamanhosChaves.put(ALGORITMO_DES, new Long(8));
		tamanhosChaves.put(ALGORITMO_BLOWFISH, new Long(16));
		tamanhosChaves.put(ALGORITMO_AES, new Long(16));
		
	}
	public static String encrypt(String text, String chave, String algoritmo) throws  BadPaddingException,NoSuchPaddingException,IllegalBlockSizeException,InvalidKeyException,NoSuchAlgorithmException,InvalidAlgorithmParameterException, UnsupportedEncodingException, InvalidKeySpecException {  
			SecretKey skey = getSecretKey(chave,algoritmo);
			Cipher cipher = Cipher.getInstance(algoritmo);  
			cipher.init(Cipher.ENCRYPT_MODE, skey);  
			return enc.encode (cipher.doFinal(text.getBytes()));
	}
	
	
	public static String decrypt(String text, String chave, String algoritmo) {  
		StringBuffer ret = new StringBuffer();  
		try{
			SecretKey skey = getSecretKey(chave, algoritmo);
			Cipher cipher = Cipher.getInstance(algoritmo);  
			cipher.init(Cipher.DECRYPT_MODE, skey);  
			
			byte[] b = dec.decodeBuffer (text);
			ret.append(new String(cipher.doFinal(b)));
		}catch(Exception e){
			return "Chave Incorreta";
		} 
		return ret.toString();  
	}  
	public static void encryptFile(String pathAqruivoOriginal, String pathArquivoDestino, String chave, String algoritmo) throws Exception{
		FileInputStream fis;
		FileOutputStream fos;
		CipherInputStream cis;
		SecretKey skey = getSecretKey(chave,algoritmo);
		Cipher cipher = Cipher.getInstance(algoritmo);  
		cipher.init(Cipher.ENCRYPT_MODE, skey);
		
		fis = new FileInputStream(pathAqruivoOriginal);
		cis = new CipherInputStream(fis, cipher);
		fos = new FileOutputStream(pathArquivoDestino);
		byte[] b = new byte[8];
		int i = cis.read(b);
		while (i != -1) {
			fos.write(b, 0, i);
			i = cis.read(b);
		}
		fos.close();
		cis.close();
		fis.close();
	}
	public static void decryptFile(String pathAqruivoOriginal, String pathArquivoDestino, String chave, String algoritmo) throws Exception{
		FileInputStream fis;
		FileOutputStream fos;
		CipherInputStream cis;
		SecretKey skey = getSecretKey(chave,algoritmo);
		Cipher cipher = Cipher.getInstance(algoritmo);  
		cipher.init(Cipher.DECRYPT_MODE, skey);
		
		fis = new FileInputStream(pathAqruivoOriginal);
		cis = new CipherInputStream(fis, cipher);
		fos = new FileOutputStream(pathArquivoDestino);
		byte[] b = new byte[8];
		int i = cis.read(b);
		while (i != -1) {
			fos.write(b, 0, i);
			i = cis.read(b);
		}
		fos.close();
		cis.close();
		fis.close();
	}
	/**
	 * Utiliza MD5, este metodo de criptografia nao pode serdesfeito, 
	 * uma vez a senha criptografada, ela nao pode ser recuperada 
	 * @param password
	 * @return senha criptografada com MD5
	 */
	public static String encriptaSenha(String password){
		MessageDigest md5=null;
		try {
			md5 = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		md5.reset();
		md5.update(password.getBytes());
		return new String(md5.digest());
	}
	/**
	 * verifica se uma senha em texto claro é igual a uma senha criptografada com md5.
	 * @return true se for iigual , false se for diferente
	 */
	public static boolean comparaSenhaCriptografada(String passwordClear, String passwordEncriptado){
		MessageDigest md5=null;
		try {
			md5 = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			return false;
		}
		md5.reset();
		md5.update(passwordClear.getBytes());
		String senha1 = new String(md5.digest());
		return MessageDigest.isEqual(senha1.getBytes(), passwordEncriptado.getBytes()); 
	}
	public static SecretKey getSecretKey(String chave, String algoritmo) {
		String keyString =chave;
		int tam = new Long(tamanhosChaves.get(algoritmo).toString()).intValue();
		byte[] keyB = new byte[tam]; 
		for (int i = 0; i < keyString.length() && i < keyB.length; i++) {
			keyB[i] = (byte) keyString.charAt(i);
		}
		
		SecretKey skey = new SecretKeySpec(keyB, algoritmo);
		return skey;
	}  
}

Algumas observações:

  • Cuidado com encoding: como os métodos encrypt e decrypt estão trabalhando com String, pode dar problema se você criptografar em uma máquina (Windows) e decriptografar em outra (Linux/Unix).
  • Você está gerando chaves iguais para senhas diferentes: por exemplo “senha12” vai gerar a mesma chave para “senha12345678” no caso do algoritmo DES.
  • Em encryptFile, você está lendo blocos de 8 bytes. Dependendo do algoritmo e do tamanho do arquivo (não ser multiplo de 8 bytes) você vai precisar um padding senão vai dar problema.
  • Acho que o parâmetro algoritmo que é usado em encrypt/decrypt/encryptFile/decryptFile geralmente não pode ser o mesmo para o getSecretKey. Em Cypher.getInstance o ideal é passar o padrão “algoritmo/mode/padding”, pois pode dar problema se for usado outra implementação do algoritmo ou o problema de padding que eu citei acima.
  • Não use mais o algoritmo MD5 para MessageDigest. Prefira SHA1 ou superior.
  • Na minha opinião, é melhor usar PBE para criptografar arquivo com senha. Evita vários dos problemas que eu citei acima.