Criptografia DES

Olá pessoal,

preciso urgente realizar uma criptografia DES em java…achei o seguinte exemplo:

import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;

public class MainClass {
  public static void main(String args[]) throws Exception {
    Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    SecretKey key = KeyGenerator.getInstance("DES").generateKey();

    // for CBC; must be 8 bytes
    byte[] initVector = new byte[] { 0x10, 0x10, 0x01, 0x04, 0x01, 0x01, 0x01, 0x02 };

    AlgorithmParameterSpec algParamSpec = new IvParameterSpec(initVector);
    Cipher m_encrypter = Cipher.getInstance("DES/CBC/PKCS5Padding");
    Cipher m_decrypter = Cipher.getInstance("DES/CBC/PKCS5Padding");

    m_encrypter.init(Cipher.ENCRYPT_MODE, key, algParamSpec);
    m_decrypter.init(Cipher.DECRYPT_MODE, key, algParamSpec);

    byte[] clearText = "www.java2s.com".getBytes();

    byte[] encryptedText = m_encrypter.doFinal(clearText);

    byte[] decryptedText = m_decrypter.doFinal(encryptedText);

    System.out.println(new String(clearText));
    System.out.println(new String(encryptedText));
    System.out.println(new String(decryptedText));

  }

}

mas o problema é q eu preciso passar uma chave privada, em hexa e aqui eu nao tenho esta opcao, e eu nao achei como passar uma chave criada por mim no lugar de KeyGenerator.getInstance(“DES”).generateKey();

vlew…abraços.

Opa, tente isto para criar sua chave:

SecretKey key2 = new SecretKeySpec(arrayByte, “DES”);

Até mais

ok, ele aceitou, mas aceita somente uma cheve de 8 digitos…achei estranho, ou devo estar informando de uma maneira errada…pq preciso informar uma chave hexa…por exemplo : 5446615264454F49.

Posta como você está fazendo agora.

new SecretKeySpec(key.getBytes(), “DES”);

Já tentou ?

Lá vai…se a chave for de 8 digitos funciona, mas com essa nao funciona


package testedes;


import java.io.UnsupportedEncodingException;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;


public class CryptoEx1 {
  Cipher ecipher;
  Cipher dcipher;
  CryptoEx1(SecretKey key) {
    try {
      ecipher = Cipher.getInstance("DES");
      dcipher = Cipher.getInstance("DES");
      ecipher.init(Cipher.ENCRYPT_MODE, key);
      dcipher.init(Cipher.DECRYPT_MODE, key);
 
    } catch (javax.crypto.NoSuchPaddingException e) {
    } catch (java.security.NoSuchAlgorithmException e) {
    } catch (java.security.InvalidKeyException e) {
    }
  }
 
  public String encrypt(String str) {
    try {
      
      byte[] iso = str.getBytes("ISO-8859-1");
 
      // criptografa
      byte[] enc = ecipher.doFinal(iso);
 
      // Retorna um string com o encode base64
      return new sun.misc.BASE64Encoder().encode(enc);
    } catch (javax.crypto.BadPaddingException e) {
    } catch (IllegalBlockSizeException e) {
    } catch (UnsupportedEncodingException e) {
    } catch (java.io.IOException e) {
    }
    return null;
  }
 
  public String decrypt(String str) {
    try {
      // Decodifica o string em bytes
      byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str);
 
      // descriptografa
      byte[] iso = dcipher.doFinal(dec);
 
      // Retorna o string em utf8
      return new String(iso, "ISO-8859-1");
    } catch (javax.crypto.BadPaddingException e) {
    } catch (IllegalBlockSizeException e) {
    } catch (UnsupportedEncodingException e) {
    } catch (java.io.IOException e) {
    }
    return null;
  }
 
  public static void main(String[] args) {
   
       try {
      // Gera uma chave que será utilizada para criptografar e
      // descriptografar
      String chave = "5446615264454F49";
       byte[] rawkey = chave.getBytes("ISO-8859-1");
      
      SecretKey key = new SecretKeySpec(chave.getBytes(),"DES");
      
      
 
      // Cria a classe que criptografa
      CryptoEx1 encrypter = new CryptoEx1(key);
 
      // Criptografa
      String encrypted = encrypter.encrypt("Isso é um segredo.");
      System.out.println(encrypted);
      // Descriptografa
      String decrypted = encrypter.decrypt(encrypted);
      System.out.println(decrypted);
    } catch (Exception e) {
    }
 
  }
 
}

obrigado.

Você precisa pegar sua chave, que está em uma string hexadecimal de 16 caracteres, e transformá-la em um array de bytes de 8 bytes.

Isso é só uma coisa braçal e acho que é fácil você fazer isso com substring e Integer.parseInt.

Por exemplo, você pode usar ((byte) Integer.parseInt (“4F”, 16)) para obter o byte 0x4F.

thingol,

tem algo errado…veja se estou correto, eu teria q converter o seu exemplo assim :

byte[] teste = (byte) Integer.parseInt (“4F”, 16);

?

Em vez de try catch, joga a excessao pra cima, com throws, para pelo menos você ver o que está acontecendo no seu código. A Excessao do seu código é esta:

Exception in thread “main” java.security.InvalidKeyException: Invalid key length: 16 bytes
at com.sun.crypto.provider.DESCipher.engineGetKeySize(DashoA6275)
at javax.crypto.Cipher.b(DashoA12275)
at javax.crypto.Cipher.a(DashoA12275)
at javax.crypto.Cipher.a(DashoA12275)
at javax.crypto.Cipher.a(DashoA12275)
at javax.crypto.Cipher.init(DashoA12275)
at javax.crypto.Cipher.init(DashoA12275)
at pacote1.CryptoEx1.(CryptoEx1.java:22)
at pacote1.CryptoEx1.main(CryptoEx1.java:71)

Ele não está aceitando uma chave privada de 16 bytes.

[quote=tap_pedroso]thingol,

tem algo errado…veja se estou correto, eu teria q converter o seu exemplo assim :

byte[] teste = (byte) Integer.parseInt (“4F”, 16);

?[/quote]

Não é bem isso, a dica que lhe dei é para converter apenas um dos bytes; não todos, que acho que você consegue codificar um loop. É por isso que eu falei em “substring” e disse quantos bytes tem de ter o array de bytes.

sim, eu entendi o que vc quis dizer, mas antes eu tentei converter somente 1 valor hexa desta maneira que escrevi para ver o retorno e se nao acontecia nenhum erro.

thingol, veja se vc consegue me dar um ultimo help…tentei colocar os valores da chave hexa dentro do array de bytes, mas ele entra no array como decimal, nao estou conseguindo chegar ao valor correto…eu tenho feito em delphi uma aplicação que faz o DES e funciona legal…o valor em texto claro é 9626000715612011, a chave é 5446615264454F49, e o valor cifrado com DES é 0146423EE2145003…em java o retorno nao bate nunca…vou posta o codigo que estou passando para o array de bytes e o codigo completo…muito obrigado pela força.

Tentando passar a chave hexa para um array de byte

  public static byte[] hexBytes(String hexText){
            
            String decodedText=null;
            String chunk=null;
            
            int numBytes = hexText.length()/2;

            byte[] rawToByte = new byte[numBytes];
            int offset=0;
            int bCounter=0;
            for(int i =0; i <numBytes; i++) {
                chunk = hexText.substring(offset,offset+2);
                offset+=2;                
                rawToByte[i] = (byte) (Integer.parseInt(chunk,16));
            }
      return rawToByte;
  }

codigo completo

import java.io.UnsupportedEncodingException;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;


public class CryptoEx1 {
  Cipher ecipher;
  Cipher dcipher;
  CryptoEx1(SecretKey key) {
    try {
      ecipher = Cipher.getInstance("DES");
      dcipher = Cipher.getInstance("DES");
      ecipher.init(Cipher.ENCRYPT_MODE, key);
      dcipher.init(Cipher.DECRYPT_MODE, key);
 
    } catch (javax.crypto.NoSuchPaddingException e) {
    } catch (java.security.NoSuchAlgorithmException e) {
    } catch (java.security.InvalidKeyException e) {
    }
  }
 
  public String encrypt(String str) {
    try {
      
      byte[] iso = str.getBytes("ISO-8859-1");
 
      // criptografa
      byte[] enc = ecipher.doFinal(iso);
 
      // Retorna um string com o encode base64
      return new sun.misc.BASE64Encoder().encode(enc);
    } catch (javax.crypto.BadPaddingException e) {
    } catch (IllegalBlockSizeException e) {
    } catch (UnsupportedEncodingException e) {
    } catch (java.io.IOException e) {
    }
    return null;
  }
 
  public String decrypt(String str) {
    try {
      // Decodifica o string em bytes
      byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str);
 
      // descriptografa
      byte[] iso = dcipher.doFinal(dec);
 
      // Retorna o string em utf8
      return new String(iso, "ISO-8859-1");
    } catch (javax.crypto.BadPaddingException e) {
    } catch (IllegalBlockSizeException e) {
    } catch (UnsupportedEncodingException e) {
    } catch (java.io.IOException e) {
    }
    return null;
  }
 
/*      public static byte[] hexToBytes(char[] hex) {
        int length = hex.length / 2;
        byte[] raw = new byte[length];
        for (int i = 0; i < length; i++) {
          int high = Character.digit(hex[i * 2], 16);
          int low = Character.digit(hex[i * 2 + 1], 16);
          int value = (high << 4) | low;
          if (value > 127)
            value -= 256;
            
          raw[i] = (byte) value;
        }
        return raw;
    }
    
  public static byte[] hexToBytes(String hex) {
        return hexToBytes(hex.toCharArray());
    }    
  */
  
  
  public static byte[] hexBytes(String hexText){
            
            String decodedText=null;
            String chunk=null;
            
            int numBytes = hexText.length()/2;

            byte[] rawToByte = new byte[numBytes];
            int offset=0;
            int bCounter=0;
            for(int i =0; i <numBytes; i++) {
                chunk = hexText.substring(offset,offset+2);
                offset+=2;                
                rawToByte[i] = (byte) (Integer.parseInt(chunk,16));
            }
      return rawToByte;
  }


  public static void main(String[] args) {
   
       try {
      // Gera uma chave que será utilizada para criptografar e
      // descriptografar
      String chave = "5446615264454F49";
      
      byte[] rawkey = hexBytes(chave);     
      SecretKey key = new SecretKeySpec(rawkey,"DES");
      
      
 
      // Cria a classe que criptografa
      CryptoEx1 encrypter = new CryptoEx1(key);
 
      // Criptografa
      String encrypted = encrypter.encrypt("9626000715612011");
      System.out.println(encrypted);
      // Descriptografa
      String decrypted = encrypter.decrypt(encrypted);
      System.out.println(decrypted);
    } catch (Exception e) {
    }
 
  }
 
}

Você sabe qual é o “modo” usado no Delphi? Provavelmente é ECB, e não CBC como você está usando por default.

Você teria de especificar, em vez de simplesmente DES, “DES/ECB/NoPadding”.

http://java.sun.com/javase/6/docs/api/javax/crypto/Cipher.html

ok, vou dar uma olhada aqui…mas o codigo para montar o array de bytes era isso mesmo?

Acho que sim.

Aos colegas q necessitam trabalhar com Criptografia DES…segue um exemplo funcional 100% DES com chave hexadecimal:

package testedesjce;


import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class Main {

   
public static byte[] hexToBytes(String str) {
      if (str==null) {
         return null;
      } else if (str.length() < 2) {
         return null;
      } else {
         int len = str.length() / 2;
         byte[] buffer = new byte[len];
         for (int i=0; i<len; i++) {
             buffer[i] = (byte) Integer.parseInt(
                str.substring(i*2,i*2+2),16);
         }
         return buffer;
      }

 }
   
 public static String bytesToHex(byte[] data) {
      if (data==null) {
         return null;
      } else {
         int len = data.length;
         String str = "";
         for (int i=0; i<len; i++) {
            if ((data[i]&0xFF)<16) str = str + "0" 
               + java.lang.Integer.toHexString(data[i]&0xFF);
            else str = str
               + java.lang.Integer.toHexString(data[i]&0xFF);
         }
         return str.toUpperCase();
      }
   }         
    
  public static void main(String[] a) {
      
      if (a.length<1) {
         System.out.println("Usage:");
         System.out.println("java JceSunDesTest 1/2");
         return;
      }
      String test = a[0];
      try {
         byte[] theKey = null;
         byte[] theMsg = null; 
         byte[] theExp = null; 
         if (test.equals("1")) { 
            theKey = hexToBytes("5446615264454F49");
            theMsg = hexToBytes("9626000715612011");
            theExp = hexToBytes("85E813540F0AB405");
         } else if (test.equals("2")) { 
            theKey = hexToBytes("5446615264454F49"); // "8bytekey"
            theMsg = hexToBytes("9626000715582011"); // "message."
            theExp = hexToBytes("7CF45E129445D451");
         } else {
            System.out.println("Usage:");
            System.out.println("java JceSunDesTest 1/2");
            return;
         }	
         KeySpec ks = new DESKeySpec(theKey);
         SecretKeyFactory kf 
            = SecretKeyFactory.getInstance("DES");
         SecretKey ky = kf.generateSecret(ks);
         Cipher cf = Cipher.getInstance("DES/ECB/NoPadding");
         cf.init(Cipher.ENCRYPT_MODE,ky);
         byte[] theCph = cf.doFinal(theMsg);
         System.out.println("Key     : "+bytesToHex(theKey));
         System.out.println("Message : "+bytesToHex(theMsg));
         System.out.println("Cipher  : "+bytesToHex(theCph));
         System.out.println("Expected: "+bytesToHex(theExp));
      } catch (Exception e) {
         e.printStackTrace();
         return;
      }

    }
  
}

Na minha classe o problema é essa linha:

sun.misc.BASE64Encoder

ta dando erro, não sei o que fazer, já atualizei o Java-JRE