DES (Data Encryption Standard) - ECB: Duvida em guardar a keygen

6 respostas
tRuNkSnEt

Olá

Construi um algoritmo para criptografia e descriptografia de dados. Existem dados que devem ser criptografados mas quando eu precisar deles eu preciso descriptografalos. Quando eu criptografo um dado eu consigo pegar a chave usada porém, quando eu vou reutilizar a chave as vezes ele não consegue fazer a descriptografia correta.

O codigo é o seguinte:
import java.security.*;
import javax.crypto.*;

public class Class {
    
    private static SecretKey desKey = null;
    private static byte[] key = null;
    
    public static SecretKey getKeyGen(){
        
        if(desKey==null){
            KeyGenerator keygen=null;
            try {
                keygen = KeyGenerator.getInstance("DES");
                desKey = keygen.generateKey();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
           
            return desKey;
        }
        
        return desKey;
    }
    
    public static String encripta(String dado) throws GeneralSecurityException{
        
        Cipher enCipher;
        // Criando o Cipher
        enCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
        //Iniciando o cipher
        enCipher.init(Cipher.WRAP_MODE, Class.getKeyGen());
        key = enCipher.wrap(Class.getKeyGen()); //Guardando a chave
        enCipher.init(Cipher.ENCRYPT_MODE, Class.getKeyGen());
        /*Byte do dado a ser criptografado*/
        byte[] dados = dado.getBytes();
        /*O dado já criptografado*/
        byte[] dadoEncriptado = enCipher.doFinal(dados);
        
        return new String(dadoEncriptado);
    }
    
    public static String decriptaECB(String dadoEncriptado) throws GeneralSecurityException{
                
        Cipher desCipher;

        // Criando o Cipher
        desCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
                
        // Os dados criptografados para descriptografar
        byte[] dadoDescriptografado = dadoEncriptado.getBytes();

        // Inicializando o cipher e pegando a minha chave para descripografar
        desCipher.init(Cipher.UNWRAP_MODE,Class.getKeyGen());
        desCipher.init(Cipher.DECRYPT_MODE,desCipher.unwrap(key,"DES",Cipher.SECRET_KEY));
        // Descriptografando
        byte[] cleartext1 = desCipher.doFinal(dadoDescriptografado);
        
        return new String(cleartext1);
        
    }
    public static void main(String args[]){
        String dado = "Minha informação";
        String en = null;
        String des = null;
        System.out.println("String antes: "+dado);
        try {
            en =  Class.encripta(dado);
        } catch (GeneralSecurityException e) {
                  e.printStackTrace();
        }
        System.out.println("String criptografada: "+en);
              
        try {
            des = Class.decriptaECB(en);
        } catch (GeneralSecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("String Descriptografada: "+des);
      }
}

Se você rodar o codigo muitas vezes algumas vezes ele vai conseguir descriptografar corretamente.

Alguem ai da uma luz?

6 Respostas

fmeyer

eu estava com esse problema por causa de encoding da string, converta pra utf-8 antes de criptografar e depois de decriptografar que esse problema é corrigido.

tRuNkSnEt

Ahh, boa fmeyer!

Deu certinho agora ... Converti para UTF-8 e coloquei na base 64 para que a chave coubesse. Fico devendo essa.

No final ficou:

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.*;
import javax.crypto.*;
 
 public class Class {
     
     private static SecretKey desKey = null;
     private static byte[] key = null;
     
     public static SecretKey getKeyGen(){
         
         if(desKey==null){
             KeyGenerator keygen=null;
             try {
                 keygen = KeyGenerator.getInstance("DES");
                 desKey = keygen.generateKey();
             } catch (NoSuchAlgorithmException e) {
                 e.printStackTrace();
             }
            
             return desKey;
         }
         
         return desKey;
     }
     
     public static String encripta(String dado) throws GeneralSecurityException{
         
         Cipher enCipher;
         // Criando o Cipher
         enCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
         //Iniciando o cipher
         enCipher.init(Cipher.WRAP_MODE, Class.getKeyGen());
         key = enCipher.wrap(Class.getKeyGen()); //Guardando a chave
         enCipher.init(Cipher.ENCRYPT_MODE, Class.getKeyGen());
         /*Byte do dado a ser criptografado*/
         byte[] dados = null;
		try {
			dados = dado.getBytes("UTF8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
         /*O dado já criptografado*/
         byte[] dadoEncriptado = enCipher.doFinal(dados);
         
         return new sun.misc.BASE64Encoder().encode(dadoEncriptado);
     }
     
     public static String decripta(String dadoEncriptado) throws GeneralSecurityException, UnsupportedEncodingException{
                 
         Cipher desCipher;
         
         // Criando o Cipher
         desCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
                 
         // Os dados criptografados para descriptografar
         byte[] dadoDescriptografado=null;
         try {
			dadoDescriptografado = new sun.misc.BASE64Decoder().decodeBuffer(dadoEncriptado);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
 
         // Inicializando o cipher e pegando a minha chave para descripografar
         desCipher.init(Cipher.UNWRAP_MODE,Class.getKeyGen());
         desCipher.init(Cipher.DECRYPT_MODE,desCipher.unwrap(key,"DES",Cipher.SECRET_KEY));
         // Descriptografando
         byte[] texto = desCipher.doFinal(dadoDescriptografado);
         
         return new String(texto,"UTF8");
         
     }
     public static void main(String args[]){
         String dado = "Minha informação";
         String en = null;
         String des = null;
         System.out.println("String antes: "+dado);
         try {
             en =  Class.encripta(dado);
           
         } catch (GeneralSecurityException e) {
                   e.printStackTrace();
         } 
         System.out.println("String criptografada: "+en);
               
         try {
             try {
				des = Class.decripta(en);
			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
         } catch (GeneralSecurityException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
         }
         System.out.println("String Descriptografada: "+des);
         System.out.println("Key utilizada: "+new String(key));
       }
 }
S

Boa Tarde…

fmeyer esse codigo que vc postou aqui eh exatamente o que preciso :lol:, porem eu precisaria que fosse mantido a mesma key sempre.

Eh que minha aplicacao vai ler a senha de um arquivo .properties e no primeiro login do usuario criptografa - la. A partir do segundo login eu terei que descriptografar sempre para efetuar o login no BD, mas como eh usado key diferentes da pau.

Alguem sabe como posso fazer isso!??!?!

[ ]s

O

sbarbutti:
Boa Tarde…

fmeyer esse codigo que vc postou aqui eh exatamente o que preciso :lol:, porem eu precisaria que fosse mantido a mesma key sempre.

Eh que minha aplicacao vai ler a senha de um arquivo .properties e no primeiro login do usuario criptografa - la. A partir do segundo login eu terei que descriptografar sempre para efetuar o login no BD, mas como eh usado key diferentes da pau.

Alguem sabe como posso fazer isso!??!?!

[ ]s

Uma solução seria fazer um outro programa que gera a chave e salva em um arquivo, o objeto SecretKey. Dai seria modificar o programa acima para ao inves de gerar uma chave, ler o arquivo. Poderia, ao inves de gravar em um arquivo o objeto, transformá-lo em um property, mas teria que usar um Base64 para poder gravar em um arquivo de properties.

Uma outra solução mais elaborada seria ao inves de apenas salvar o objeto SecretKey em um arquivo, usar uma algoritmo de PBE (Password-Base Encryption) para proteger a chave.

T

Dê uma estudada no código abaixo.

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.spec.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.KeySpec;

public final class TestePBE {
	private static SecretKey skey;
	private static final String algorithm = "AES/CBC/PKCS5Padding";
	public static final void encrypt(char[] password, File arq)
		throws  IOException, 
			BadPaddingException,
			NoSuchPaddingException,
			IllegalBlockSizeException,
			InvalidKeyException,
			NoSuchAlgorithmException {
        	SecretKeyFactory skf = SecretKeyFactory.getInstance(algorithm);
		KeySpec ks = new PBEKeySpec (password, new byte[]{1,2,3,4,5,6,7,8,9,10}, 1000);
		SecretKey skey = skf.generateSecret (ks);
		final Cipher cipher = Cipher.getInstance(algorithm);
		cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
		return cipher.doFinal(text.getBytes());
	}
	public static final void decrypt(char[] password, File arq)
		throws  IOException,
			BadPaddingException,
			NoSuchPaddingException,
			IllegalBlockSizeException,
			InvalidKeyException,
			NoSuchAlgorithmException {
		SecretKeyFactory skf = SecretKeyFactory.getInstance(algorithm);
		KeySpec ks = new PBEKeySpec (password, new byte[]{1,2,3,4,5,6,7,8,9,10}, 1000);
		SecretKey skey = skf.generateSecret (ks);
		final Cipher cipher = Cipher.getInstance(algorithm);
		cipher.init(Cipher.DECRYPT_MODE, skeySpec);
		return cipher.doFinal(text.getBytes());
	}
	
	private static int tamArquivoTeste = 12345;
	
	private static void geraArquivoTeste(File arq) throws IOException {
	    Random r = new Random ();
	    r.setSeed (123456789);
	    byte[] bytes = new byte[tamArquivoTeste];
	    r.next (bytes);
	    OutputStream os = new FileOutputStream (arq);
	    os.write (bytes);
	    os.close();
        }
        
	private static boolean confereArquivoTeste(File arq) throws IOException {
	    boolean ret = true;
	    Random r = new Random ();
	    r.setSeed (123456789);
	    byte[] bytes = new byte[tamArquivoTeste];
	    r.next (bytes);
	    byte[] readBytes = new byte[tamArquivoTeste];
	    if (arq.length() != tamArquivoTeste) {
	        System.out.println ("Arquivo de tamanho diferente do esperado");
	        return false;
            }
	    InputStream is = new FileInputStream (arq);
	    int nBytes = is.read (readBytes);
	    is.close();
	    
	    if (nBytes != tamArquivoTeste) {
	        System.out.println ("Arquivo de tamanho diferente do esperado");
	        return false;
            }
            return Arrays.equals (readBytes, bytes);
        }
	
	public static void main(String[] args) throws Exception {
            String password = "senha altamente secreta";
            File arqEntrada = new File ("teste.bin");
            File arqCifrado = new File ("teste.bin.cifrado");
            File arqDecifrado = new File ("teste.bin.decifrado");
            geraArquivoTeste (arqTeste);		
            TestePBE.encrypt (password, arqEntrada, arqCifrado);
            //-- Checando com a senha certa
            TestePBE.decrypt (password, arqCifrado, arqDecifrado);
            if (confereArquivoTeste (arqEntrada, arqDecifrado)) {
                System.out.println ("Os arquivos bateram");
            }
            //-- Checando com a senha errada
            TestePBE.decrypt ("senhaErrada", arqTeste);
            if (confereArquivoTeste (arqEntrada, arqDecifrado)) {
                System.out.println ("Os arquivos bateram");
            }
	}
}
S

Obrigado pelas respostas…

Vou dar uma estudada nesse codigo…

[ ]s

Criado 21 de setembro de 2006
Ultima resposta 10 de out. de 2006
Respostas 6
Participantes 5