Come utilizzo la crittografia / decrittografia 3DES in Java?

Ogni metodo che scrivo per codificare una stringa in Java usando 3DES non può essere decrittografato alla stringa originale. Qualcuno ha uno snippet di codice semplice che può solo codificare e quindi decodificare la stringa fino alla stringa originale?

So che sto facendo un errore molto stupido da qualche parte in questo codice. Ecco cosa ho lavorato finora:

** nota, non sto restituendo il testo BASE64 dal metodo di crittografia, e non sono codifica di base64 nel decrypt perché stavo cercando di vedere se stavo facendo un errore nella parte BASE64 del 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; } } 

Il tuo codice andava bene tranne che per il bit di codifica Base 64 (che hai menzionato come test), il motivo per cui l’output non avrebbe avuto senso è che stavi visualizzando un array di byte non elaborato (facendo aString () su un array di byte restituisce il suo interno Riferimento Java, non la rappresentazione String dei contenuti ). Ecco una versione che è appena un po ‘pulita e che stampa “kyle boon” come stringa decodificata:

 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"); } } 

Ecco una soluzione che utilizza la libreria javax.crypto e la libreria di codec di apache commons per la codifica e la decodifica in 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); } } 

Eseguendo i risultati del programma di cui sopra con il seguente risultato:

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

Ho avuto dei momentjs difficili a pensarci e questo post mi ha aiutato a trovare la risposta giusta per il mio caso. Quando si lavora con la messaggistica finanziaria come ISO-8583 i requisiti di 3DES sono piuttosto specifici, quindi per il mio caso particolare le combinazioni “DESede / CBC / PKCS5Padding” non risolvevano il problema. Dopo alcuni test comparativi dei miei risultati con alcuni calcolatori 3DES progettati per il mondo finanziario, ho trovato che il valore “DESede / ECB / Nopadding” è più adatto per l’attività specifica.

Ecco una implementazione demo della mia class TripleDes (utilizzando il provider di Bouncy Castle)

 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); } } 

Ecco una semplice statica encrypt / decrypt class biased sul Bouncy Castle senza esempio di riempimento di Jose Luis Montes de Oca. Questo sta usando “DESede / ECB / PKCS7Padding” quindi non devo preoccuparmi di riempire manualmente.

 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); } }
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); } } 
 import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.Key; import javax.crypto.Cipher; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESedeKeySpec; import javax.crypto.spec.IvParameterSpec; import java.util.Base64; import java.util.Base64.Encoder; /** * * @author shivshankar pal * * this code is working properly. doing proper encription and decription note:- it will work only with jdk8 * * */ public class TDes { private static byte[] key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 }; private static byte[] keyiv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; public static String encode(String args) { System.out.println("plain data==> " + args); byte[] encoding; try { encoding = Base64.getEncoder().encode(args.getBytes("UTF-8")); System.out.println("Base64.encodeBase64==>" + new String(encoding)); byte[] str5 = des3EncodeCBC(key, keyiv, encoding); System.out.println("des3EncodeCBC==> " + new String(str5)); byte[] encoding1 = Base64.getEncoder().encode(str5); System.out.println("Base64.encodeBase64==> " + new String(encoding1)); return new String(encoding1); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } public static String decode(String args) { try { System.out.println("encrypted data==>" + new String(args.getBytes("UTF-8"))); byte[] decode = Base64.getDecoder().decode(args.getBytes("UTF-8")); System.out.println("Base64.decodeBase64(main encription)==>" + new String(decode)); byte[] str6 = des3DecodeCBC(key, keyiv, decode); System.out.println("des3DecodeCBC==>" + new String(str6)); String data=new String(str6); byte[] decode1 = Base64.getDecoder().decode(data.trim().getBytes("UTF-8")); System.out.println("plaintext==> " + new String(decode1)); return new String(decode1); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return "u mistaken in try block"; } private static byte[] des3EncodeCBC(byte[] key, byte[] keyiv, byte[] data) { try { Key deskey = null; DESedeKeySpec spec = new DESedeKeySpec(key); SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede"); deskey = keyfactory.generateSecret(spec); Cipher cipher = Cipher.getInstance("desede/ CBC/PKCS5Padding"); IvParameterSpec ips = new IvParameterSpec(keyiv); cipher.init(Cipher.ENCRYPT_MODE, deskey, ips); byte[] bout = cipher.doFinal(data); return bout; } catch (Exception e) { System.out.println("methods qualified name" + e); } return null; } private static byte[] des3DecodeCBC(byte[] key, byte[] keyiv, byte[] data) { try { Key deskey = null; DESedeKeySpec spec = new DESedeKeySpec(key); SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede"); deskey = keyfactory.generateSecret(spec); Cipher cipher = Cipher.getInstance("desede/ CBC/NoPadding");//PKCS5Padding NoPadding IvParameterSpec ips = new IvParameterSpec(keyiv); cipher.init(Cipher.DECRYPT_MODE, deskey, ips); byte[] bout = cipher.doFinal(data); return bout; } catch (Exception e) { System.out.println("methods qualified name" + e); } return null; } }