문제

3DES를 사용하여 Java에서 문자열을 인코딩하기 위해 작성한 모든 메서드는 원래 문자열로 다시 해독될 수 없습니다.문자열을 인코딩한 다음 다시 원래 문자열로 디코딩할 수 있는 간단한 코드 조각을 가진 사람이 있습니까?

나는 이 코드 어딘가에서 매우 어리석은 실수를 하고 있다는 것을 알고 있습니다.지금까지 제가 작업한 내용은 다음과 같습니다.

** 참고로 저는 암호화 방법에서 BASE64 텍스트를 반환하지 않으며 퍼즐의 BASE64 부분에서 실수를 했는지 확인하려고 했기 때문에 해독 방법에서 base64 인코딩을 해제하지 않습니다.

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;
    }
}
도움이 되었습니까?

해결책

귀하의 코드는 Base 64 인코딩 비트(테스트라고 언급한)를 제외하고는 괜찮았습니다. 출력이 의미가 없는 이유는 원시 바이트 배열을 표시했기 때문입니다(바이트 배열에서 toString()을 수행하면 내부 비트가 반환됨). 문자열 표현이 아닌 Java 참조 내용물).다음은 약간의 정리 작업을 수행하고 "kyle boon"을 디코딩된 문자열로 인쇄하는 버전입니다.

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

다른 팁

다음은 javax.crypto Base64에서 인코딩 및 디코딩을 위한 라이브러리 및 Apache Commons 코덱 라이브러리:

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

    }

}

위 프로그램을 실행하면 다음과 같은 결과가 출력됩니다.

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

나는 그것을 스스로 알아내는 데 어려움을 겪었고 이 게시물은 내 사건에 대한 올바른 답을 찾는 데 도움이 되었습니다.ISO-8583과 같은 금융 메시징 작업을 할 때 3DES 요구 사항은 매우 구체적이므로 "DESede/CBC/PKCS5Padding" 조합으로는 문제가 해결되지 않았습니다.금융계를 위해 설계된 일부 3DES 계산기와 내 결과를 비교 테스트한 후 "DESede/ECB/Nopadding" 값이 특정 작업에 더 적합하다는 것을 알았습니다.

다음은 내 TripleDes 클래스의 데모 구현입니다(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);
       }
    }

다음은 Jose Luis Montes de Oca의 패딩 없는 Bouncy Castle 예제에 편향된 매우 간단한 정적 암호화/해독 클래스입니다.이것은 "DESede/ECB/PKCS7Padding"을 사용하므로 수동으로 패딩할 필요가 없습니다.


    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;

    }

}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top