76 votes

Comment puis-je utiliser le cryptage 3des/déchiffrement en Java?

Chaque méthode j'écris pour encoder une chaîne de caractères en Java à l'aide de 3DES ne peut pas être déchiffré à l'origine de la chaîne. Quelqu'un aurait-il un simple extrait de code qui peut juste coder et décoder la chaîne de retour à la chaîne d'origine?

Je sais que je suis en train de faire un très bête erreur quelque part dans ce code. Voici ce que j'ai travaillé jusqu'à présent:

** remarque, je ne suis pas de retour de la BASE64 texte à partir du cryptage de la méthode, et je ne suis pas en base64 de l'onu-le codage dans le déchiffrer méthode parce que j'essayais de voir si je faisais une erreur dans le BASE64 partie du puzzle.

public class TripleDESTest {

public static void main(String[] args) {

    String text = "kyle boon";

    byte[] codedtext = new TripleDESTest().encrypt(text);
    String decodedtext  = new TripleDESTest().decrypt(codedtext);

    System.out.println(codedtext);
    System.out.println(decodedtext);
}

public byte[] encrypt(String message)
{
    try
	{
		final MessageDigest md = MessageDigest.getInstance("md5");
        final byte[] digestOfPassword = md.digest("HG58YZ3CR9".getBytes("utf-8"));
        final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
        for (int j = 0,  k = 16; j < 8;)
        {
            keyBytes[k++] = keyBytes[j++];
        }

        final SecretKey key = new SecretKeySpec(keyBytes, "DESede");
        final IvParameterSpec iv = new IvParameterSpec(new byte[8]);
        final Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key, iv);

        final byte[] plainTextBytes = message.getBytes("utf-8");
        final byte[] cipherText = cipher.doFinal(plainTextBytes);
        final String encodedCipherText = new sun.misc.BASE64Encoder().encode(cipherText);

        return cipherText;    
    }
    catch (java.security.InvalidAlgorithmParameterException e) { System.out.println("Invalid Algorithm"); }
    catch (javax.crypto.NoSuchPaddingException e) { System.out.println("No Such Padding"); }
    catch (java.security.NoSuchAlgorithmException e) { System.out.println("No Such Algorithm"); }
    catch (java.security.InvalidKeyException e) { System.out.println("Invalid Key"); }
    catch (BadPaddingException e) { System.out.println("Invalid Key");}
    catch (IllegalBlockSizeException e) { System.out.println("Invalid Key");}
    catch (UnsupportedEncodingException e) { System.out.println("Invalid Key");}

    return null;
}

public String decrypt(byte[] message)
{
    try
	{
		final MessageDigest md = MessageDigest.getInstance("md5");
        final byte[] digestOfPassword = md.digest("HG58YZ3CR9".getBytes("utf-8"));
        final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
        for (int j = 0,  k = 16; j < 8;)
        {
            keyBytes[k++] = keyBytes[j++];
        }

        final SecretKey key = new SecretKeySpec(keyBytes, "DESede");
        final IvParameterSpec iv = new IvParameterSpec(new byte[8]);
        final Cipher decipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        decipher.init(Cipher.DECRYPT_MODE, key, iv);

        //final byte[] encData = new sun.misc.BASE64Decoder().decodeBuffer(message);
        final byte[] plainText = decipher.doFinal(message);

        return plainText.toString();            
    }
    catch (java.security.InvalidAlgorithmParameterException e) { System.out.println("Invalid Algorithm"); }
    catch (javax.crypto.NoSuchPaddingException e) { System.out.println("No Such Padding"); }
    catch (java.security.NoSuchAlgorithmException e) { System.out.println("No Such Algorithm"); }
    catch (java.security.InvalidKeyException e) { System.out.println("Invalid Key"); }
    catch (BadPaddingException e) { System.out.println("Invalid Key");}
    catch (IllegalBlockSizeException e) { System.out.println("Invalid Key");}
    catch (UnsupportedEncodingException e) { System.out.println("Invalid Key");} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}

    return null;
}

}

68voto

Boris Terzic Points 6148

Votre code a bien sauf pour le codage en Base 64 bits (qui, vous l'avez mentionné, était un test), la raison pour laquelle la sortie peut ne pas avoir de sens, c'est que vous étiez afficher les raw d'un tableau d'octets (toString() sur un tableau d'octets retourne sa Java interne de référence, et non pas la représentation de Chaîne des contenus). Voici une version juste un peu nettoyé et qui imprime "kyle boon" comme au décodage de la chaîne:

import java.security.MessageDigest;
import java.util.Arrays;

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

public class TripleDESTest {

    public static void main(String[] args) throws Exception {

    	String text = "kyle boon";

    	byte[] codedtext = new TripleDESTest().encrypt(text);
    	String decodedtext = new TripleDESTest().decrypt(codedtext);

    	System.out.println(codedtext); // this is a byte array, you'll just see a reference to an array
    	System.out.println(decodedtext); // This correctly shows "kyle boon"
    }

    public byte[] encrypt(String message) throws Exception {
    	final MessageDigest md = MessageDigest.getInstance("md5");
    	final byte[] digestOfPassword = md.digest("HG58YZ3CR9"
    			.getBytes("utf-8"));
    	final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
    	for (int j = 0, k = 16; j < 8;) {
    		keyBytes[k++] = keyBytes[j++];
    	}

    	final SecretKey key = new SecretKeySpec(keyBytes, "DESede");
    	final IvParameterSpec iv = new IvParameterSpec(new byte[8]);
    	final Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
    	cipher.init(Cipher.ENCRYPT_MODE, key, iv);

    	final byte[] plainTextBytes = message.getBytes("utf-8");
    	final byte[] cipherText = cipher.doFinal(plainTextBytes);
    	// final String encodedCipherText = new sun.misc.BASE64Encoder()
    	// .encode(cipherText);

    	return cipherText;
    }

    public String decrypt(byte[] message) throws Exception {
    	final MessageDigest md = MessageDigest.getInstance("md5");
    	final byte[] digestOfPassword = md.digest("HG58YZ3CR9"
    			.getBytes("utf-8"));
    	final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
    	for (int j = 0, k = 16; j < 8;) {
    		keyBytes[k++] = keyBytes[j++];
    	}

    	final SecretKey key = new SecretKeySpec(keyBytes, "DESede");
    	final IvParameterSpec iv = new IvParameterSpec(new byte[8]);
    	final Cipher decipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
    	decipher.init(Cipher.DECRYPT_MODE, key, iv);

    	// final byte[] encData = new
    	// sun.misc.BASE64Decoder().decodeBuffer(message);
    	final byte[] plainText = decipher.doFinal(message);

    	return new String(plainText, "UTF-8");
    }
}

17voto

oneiros Points 948

Voici une solution à l'aide de la javax.crypto , la bibliothèque et l'apache commons bibliothèque de codecs pour l'encodage et le décodage en Base64:

import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import org.apache.commons.codec.binary.Base64;

public class TrippleDes {

    private static final String UNICODE_FORMAT = "UTF8";
    public static final String DESEDE_ENCRYPTION_SCHEME = "DESede";
    private KeySpec ks;
    private SecretKeyFactory skf;
    private Cipher cipher;
    byte[] arrayBytes;
    private String myEncryptionKey;
    private String myEncryptionScheme;
    SecretKey key;

    public TrippleDes() throws Exception {
        myEncryptionKey = "ThisIsSpartaThisIsSparta";
        myEncryptionScheme = DESEDE_ENCRYPTION_SCHEME;
        arrayBytes = myEncryptionKey.getBytes(UNICODE_FORMAT);
        ks = new DESedeKeySpec(arrayBytes);
        skf = SecretKeyFactory.getInstance(myEncryptionScheme);
        cipher = Cipher.getInstance(myEncryptionScheme);
        key = skf.generateSecret(ks);
    }


    public String encrypt(String unencryptedString) {
        String encryptedString = null;
        try {
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] plainText = unencryptedString.getBytes(UNICODE_FORMAT);
            byte[] encryptedText = cipher.doFinal(plainText);
            encryptedString = new String(Base64.encodeBase64(encryptedText));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return encryptedString;
    }


    public String decrypt(String encryptedString) {
        String decryptedText=null;
        try {
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] encryptedText = Base64.decodeBase64(encryptedString);
            byte[] plainText = cipher.doFinal(encryptedText);
            decryptedText= new String(plainText);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return decryptedText;
    }


    public static void main(String args []) throws Exception
    {
        TrippleDes td= new TrippleDes();

        String target="imparator";
        String encrypted=td.encrypt(target);
        String decrypted=td.decrypt(encrypted);

        System.out.println("String To Encrypt: "+ target);
        System.out.println("Encrypted String:" + encrypted);
        System.out.println("Decrypted String:" + decrypted);

    }

}

L'exécution du programme ci-dessus les résultats avec la sortie suivante:

String To Encrypt: imparator
Encrypted String:FdBNaYWfjpWN9eYghMpbRA==
Decrypted String:imparator

12voto

jlmontesdeoca Points 59

J'ai eu de durs moments à essayer de le comprendre moi-même et ce post m'a aidé à trouver la bonne réponse pour mon cas. Lorsque vous travaillez avec messagerie financière comme ISO 8583 le 3DES exigences sont tout à fait spécifiques, donc pour mon cas particulier de la "DESede/SRC/PKCS5Padding" combinaisons n'était pas de résoudre le problème. Après quelques tests comparatifs de mes résultats à l'encontre de certains 3DES calculatrices conçu pour le monde de la finance, j'ai trouvé que la valeur "DESede/BCE/Nopadding" est plus adapté pour la tâche spécifique.

Voici une démo de la mise en œuvre de mon TripleDes classe (en utilisant le Château Gonflable fournisseur)



    import java.security.InvalidKeyException;
    import java.security.NoSuchAlgorithmException;
    import java.security.NoSuchProviderException;
    import java.security.Security;
    import javax.crypto.BadPaddingException;
    import javax.crypto.Cipher;
    import javax.crypto.IllegalBlockSizeException;
    import javax.crypto.NoSuchPaddingException;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;


    /**
     *
     * @author Jose Luis Montes de Oca
     */
    public class TripleDesCipher {
       private static String TRIPLE_DES_TRANSFORMATION = "DESede/ECB/Nopadding";
       private static String ALGORITHM = "DESede";
       private static String BOUNCY_CASTLE_PROVIDER = "BC";
       private Cipher encrypter;
       private Cipher decrypter;

       public TripleDesCipher(byte[] key) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,
             InvalidKeyException {
          Security.addProvider(new BouncyCastleProvider());
          SecretKey keySpec = new SecretKeySpec(key, ALGORITHM);
          encrypter = Cipher.getInstance(TRIPLE_DES_TRANSFORMATION, BOUNCY_CASTLE_PROVIDER);
          encrypter.init(Cipher.ENCRYPT_MODE, keySpec);
          decrypter = Cipher.getInstance(TRIPLE_DES_TRANSFORMATION, BOUNCY_CASTLE_PROVIDER);
          decrypter.init(Cipher.DECRYPT_MODE, keySpec);
       }

       public byte[] encode(byte[] input) throws IllegalBlockSizeException, BadPaddingException {
          return encrypter.doFinal(input);
       }

       public byte[] decode(byte[] input) throws IllegalBlockSizeException, BadPaddingException {
          return decrypter.doFinal(input);
       }
    }

2voto

siliconsmiley Points 29

Voici une manière très simple statique crypter/décrypter classe biaisée sur le Château Gonflable sans rembourrage exemple par Jose Luis Montes de Oca. Celui-ci est à l'aide de "DESede/BCE/PKCS7Padding" donc je n'est pas la peine manuellement rembourrage.


    package com.zenimax.encryption;

    import java.security.InvalidKeyException;
    import java.security.NoSuchAlgorithmException;
    import java.security.NoSuchProviderException;
    import java.security.Security;
    import javax.crypto.BadPaddingException;
    import javax.crypto.Cipher;
    import javax.crypto.IllegalBlockSizeException;
    import javax.crypto.NoSuchPaddingException;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;

    /**
     * 
     * @author Matthew H. Wagner
     */
    public class TripleDesBouncyCastle {
        private static String TRIPLE_DES_TRANSFORMATION = "DESede/ECB/PKCS7Padding";
        private static String ALGORITHM = "DESede";
        private static String BOUNCY_CASTLE_PROVIDER = "BC";

        private static void init()
        {
            Security.addProvider(new BouncyCastleProvider());
        }

        public static byte[] encode(byte[] input, byte[] key)
                throws IllegalBlockSizeException, BadPaddingException,
                NoSuchAlgorithmException, NoSuchProviderException,
                NoSuchPaddingException, InvalidKeyException {
            init();
            SecretKey keySpec = new SecretKeySpec(key, ALGORITHM);
            Cipher encrypter = Cipher.getInstance(TRIPLE_DES_TRANSFORMATION,
                    BOUNCY_CASTLE_PROVIDER);
            encrypter.init(Cipher.ENCRYPT_MODE, keySpec);
            return encrypter.doFinal(input);
        }

        public static byte[] decode(byte[] input, byte[] key)
                throws IllegalBlockSizeException, BadPaddingException,
                NoSuchAlgorithmException, NoSuchProviderException,
                NoSuchPaddingException, InvalidKeyException {
            init();
            SecretKey keySpec = new SecretKeySpec(key, ALGORITHM);
            Cipher decrypter = Cipher.getInstance(TRIPLE_DES_TRANSFORMATION,
                    BOUNCY_CASTLE_PROVIDER);
            decrypter.init(Cipher.DECRYPT_MODE, keySpec);
            return decrypter.doFinal(input);
        }
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X