2014-03-03 2 views
2

왜 내 암호 해독 방법이 이상한 문자를 제공하는지 이해하는 데 도움이 될지 궁금합니다. 특히,이 경우에, 나는자바의 AES 암호 해독에서 이상한 문자

여기
�����c~�+�J*zC�iV�-��&�_l��*. 

와 유사한 문자를 내 코드입니다 얻을 : 출력해야 바이트 배열

import java.io.ByteArrayOutputStream; 
import java.io.UnsupportedEncodingException; 
import java.math.BigInteger; 
import java.nio.charset.Charset; 
import javax.crypto.*; 
import java.security.*; 
import java.util.Arrays; 
import javax.crypto.spec.*; 
import org.apache.commons.codec.DecoderException; 
import org.apache.commons.codec.binary.Base64; 

import org.apache.commons.codec.binary.Hex; 

public class AESCrypto2 { 

private Cipher AEScipher; 
private KeyGenerator AESgen; 
private SecretKeySpec AESkey; 
private SecretKeySpec decodeKey; 
private String hexDecodeKey; 
private String decodeKey64; 
private byte[] cipherData; 
private String msg; 
private String encMsg; 

public static void main(String[] args) { 
    try { 
     AESCrypto2 a = new AESCrypto2(); 
     a.encrypt("Hello!"); 
     try { 
      a.decrypt(a.getEncryptedMsg(), a.getDecodeKey()); 
     } catch (DecoderException ex) { 
      ex.printStackTrace(); 
     } 
    } catch (NoSuchAlgorithmException ex) { 
     ex.printStackTrace(); 
    } catch (NoSuchPaddingException ex) { 
     ex.printStackTrace(); 
    } catch (InvalidKeyException ex) { 
     ex.printStackTrace(); 
    } catch (UnsupportedEncodingException ex) { 
     ex.printStackTrace(); 
    } catch (IllegalBlockSizeException ex) { 
     ex.printStackTrace(); 
    } catch (BadPaddingException ex) { 
     ex.printStackTrace(); 
    } 

} 

public AESCrypto2() throws NoSuchAlgorithmException, NoSuchPaddingException, 
     UnsupportedEncodingException { 
    AESgen = KeyGenerator.getInstance("AES"); 
    AESgen.init(128); 
    AESkey = (SecretKeySpec) AESgen.generateKey(); 
    decodeKey = new SecretKeySpec(AESkey.getEncoded(), "AES"); 
    hexDecodeKey = keyToString(decodeKey); 
    AEScipher = Cipher.getInstance("AES/ECB/NoPadding"); 
} 

public AESCrypto2(String msg) throws NoSuchAlgorithmException, 
     NoSuchPaddingException, InvalidKeyException, 
     UnsupportedEncodingException, IllegalBlockSizeException, 
     BadPaddingException { 
    this(); 
    encrypt(msg); 
} 

public String encrypt(String msg) throws NoSuchAlgorithmException, 
     InvalidKeyException, UnsupportedEncodingException, 
     IllegalBlockSizeException, BadPaddingException, NoSuchPaddingException { 
    AEScipher.init(Cipher.ENCRYPT_MODE, AESkey); 
    cipherData = AEScipher.doFinal(handleString(msg.getBytes("UTF-8"))); 

    this.msg = msg; 
    encMsg = stringToHex(new String(cipherData)); 
    return encMsg; 
} 

public String decrypt(String msg, String hexDecodeKey) throws 
     InvalidKeyException, IllegalBlockSizeException, 
     BadPaddingException, UnsupportedEncodingException, 
     NoSuchAlgorithmException, NoSuchPaddingException, DecoderException { 
    AEScipher.init(Cipher.DECRYPT_MODE, stringToKey(hexDecodeKey)); 
    byte[] decryptedData = AEScipher.doFinal(handleString(hexToString(msg).getBytes("UTF-8"))); 
    encMsg = msg; 
    msg = new String(decryptedData); 
    System.out.println(msg); 
    return msg; 
} 

public String getEncryptedMsg() { 
    return encMsg; 
} 

public String getDecryptedMsg() { 
    return msg; 
} 

public String getDecodeKey() { 
    return hexDecodeKey; 
} 

public SecretKeySpec getKey() { 
    return decodeKey; 
} 

//AEScipher requires that 16 divides the length of b 
public static byte[] handleString(byte[] b) throws UnsupportedEncodingException { 
    byte[] temp = b; 
    if (temp.length % 16 != 0) { 
     byte[] byteMsg = Arrays.copyOf(temp, temp.length + 16 - (temp.length % 16)); 
     return byteMsg; 
    } 
    return temp; 
} 

public static String keyToString(SecretKeySpec key) { 
    String decoded = Hex.encodeHexString(key.getEncoded()); 
    return decoded; 
} 

public static SecretKeySpec stringToKey(String key) throws DecoderException { 
    byte[] decodedKey = Hex.decodeHex(key.toCharArray()); 
    return new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES"); 
} 

public static String stringToHex(String msg) throws UnsupportedEncodingException { 
    return Hex.encodeHexString(msg.getBytes("UTF-8")); 
} 

public static String hexToString(String msg) throws DecoderException { 
    return new String(Hex.decodeHex(msg.toCharArray())); 
} 

}

+1

복사하여 붙여 넣으셨습니까? 너무 많은 수준에서 잘못되었습니다 ... – ntoskrnl

+0

나는 모든 것을 복사했지만 일부는 복사하지 않았습니다. – Kortlek

+1

-1은 보안 관련 작업을 수행하려고 시도하는 라이브러리의 기본 사용법을 적절하게 조사하지 않기 때문에 -1입니다. 이것은 Q & A 포럼이며 귀하의 질문은 유효하지만 질문을하기 전에 어느 수준의 연구 및 문제 해결이 예상됩니다. 질문이 적절하게 조사되지 않았고 간단한 오류가 있었기 때문에 검색 쿼리에 응답하여 질문을 찾은 사람들에게이 솔루션이 유용 할 것 같지 않습니다. 이 질문은 제 의견으로는 "간단한 타이포그래피 오류"기준에 거의 위배됩니다. –

답변

4

:

msg = new String(decryptedData, "UTF-8"); 

A는 정리하고 코드를 수정하려고 :

msg = new String(decryptedData); 

당신은 암호화와 같은 인코딩을 줄 필요가 : 암호 해독에 또한

암호문의 UTF8 변환을 제거하면 해독 문제가 제거되고 순수 바이트 배열 만 사용됩니다. UTF-8 인 코드 + 디코드는 바이너리 문자열에 사용될 때 동일한 결과를 얻는다는 것을 보장하지 않습니다. 사실 동일하게 돌아 오지 않을 가능성이 더 높습니다. 그리고 해독은 비트 오류에서 싫은 경향이 있습니다.

public static String byteArrayToHex(byte[] bytes) throws UnsupportedEncodingException { 
    return Hex.encodeHexString(bytes); 
} 

public static byte[] hexToByteArray(String hex) throws DecoderException { 
    return Hex.decodeHex(hex.toCharArray()); 
} 

public String encrypt(String msg) throws NoSuchAlgorithmException, 
     InvalidKeyException, UnsupportedEncodingException, 
     IllegalBlockSizeException, BadPaddingException, NoSuchPaddingException { 
    AEScipher.init(Cipher.ENCRYPT_MODE, AESkey); 
    cipherData = AEScipher.doFinal(handleString(msg.getBytes("UTF-8"))); 

    this.msg = msg; 
    encMsg = byteArrayToHex(cipherData); 
    return encMsg; 
} 

public String decrypt(String msg, String hexDecodeKey) throws 
     InvalidKeyException, IllegalBlockSizeException, 
     BadPaddingException, UnsupportedEncodingException, 
     NoSuchAlgorithmException, NoSuchPaddingException, DecoderException { 
    SecretKeySpec key = stringToKey(hexDecodeKey); 
    AEScipher.init(Cipher.DECRYPT_MODE, key); 
    byte[] decryptedData = AEScipher.doFinal(handleString(hexToByteArray(msg))); 
    encMsg = msg; 
    msg = new String(decryptedData); 
    System.out.println(msg); 
    return msg; 
} 

는 또한 AES/ECB/PKCS5Padding과 같은 몇 가지 표준 패딩을 사용하는 것이 좋습니다 수 있습니다.

+0

+1 표준 패딩을 사용해야 함을 언급합니다.그러나 PKCS # 7 패딩은 요즘에는 어떤 암호로든 사용해야한다고 생각합니다. 주로 큰 블록 크기를 가질 수있는 임의의 암호를 사용할 때 오류가 발생하기 쉽기 때문입니다. –

+0

@ MichaelJ.Gray : Java 알고리즘 사양에서 PKCS5Padding과 PKCS7Padding은 동일합니다. 즉, 둘 다 PKCS7 패딩을 수행합니다. –

+0

@GregS SunJCE 프로 바이더는 「PKCS7Padding」를 서포트하지 않기 때문에, 어떠한 경우에서도 「PKCS5Padding」를 사용할 필요가 있습니다. :) – ntoskrnl

2

음 ... 어떻게 든 암호화 ...

암호 해독은 UTF-8로 해석되어야하는 바이트 배열로 다시 변환해야합니다 - Snew 문자열을 사용하여 문자열을 인코딩합니다 (UTF_encoded 문자열

).

는 당신은 여기에 몇 가지 문자열 마법을 수행

encMsg = stringToHex(new String(cipherData)); 

왜 ??? 너 그거 필요 없어!

import java.io.UnsupportedEncodingException; 
import javax.crypto.*; 
import java.security.*; 
import java.util.Arrays; 
import javax.crypto.spec.*; 

public class AESCrypto2 { 

    private Cipher AEScipher; 
    private KeyGenerator AESgen; 
    private SecretKeySpec AESkey; 
    private SecretKeySpec decodeKey; 
    private byte[] cipherData; 
    private String msg; 

    public static void main(String[] args) { 
     try { 
      AESCrypto2 a = new AESCrypto2(); 
      a.encrypt("Hello!"); 
      a.decrypt(a.getCipherData(), a.getKey()); 
     } catch (NoSuchAlgorithmException ex) { 
      ex.printStackTrace(); 
     } catch (NoSuchPaddingException ex) { 
      ex.printStackTrace(); 
     } catch (InvalidKeyException ex) { 
      ex.printStackTrace(); 
     } catch (UnsupportedEncodingException ex) { 
      ex.printStackTrace(); 
     } catch (IllegalBlockSizeException ex) { 
      ex.printStackTrace(); 
     } catch (BadPaddingException ex) { 
      ex.printStackTrace(); 
     } 

    } 

    public AESCrypto2() throws NoSuchAlgorithmException, 
      NoSuchPaddingException, UnsupportedEncodingException { 
     AESgen = KeyGenerator.getInstance("AES"); 
     AESgen.init(128); 
     AESkey = (SecretKeySpec) AESgen.generateKey(); 
     decodeKey = new SecretKeySpec(AESkey.getEncoded(), "AES"); 
     AEScipher = Cipher.getInstance("AES/ECB/NoPadding"); 
    } 

    public AESCrypto2(String msg) throws NoSuchAlgorithmException, 
      NoSuchPaddingException, InvalidKeyException, 
      UnsupportedEncodingException, IllegalBlockSizeException, 
      BadPaddingException { 
     this(); 
     encrypt(msg); 
    } 

    public byte[] encrypt(String msg) throws NoSuchAlgorithmException, 
      InvalidKeyException, UnsupportedEncodingException, 
      IllegalBlockSizeException, BadPaddingException, 
      NoSuchPaddingException { 
     AEScipher.init(Cipher.ENCRYPT_MODE, AESkey); 
     cipherData = AEScipher.doFinal(handleString(msg.getBytes("UTF-8"))); 

     this.msg = msg; 
     return cipherData; 
    } 

    public String decrypt(byte[] enocdedData, SecretKeySpec decodeKey) 
      throws InvalidKeyException, IllegalBlockSizeException, 
      BadPaddingException, UnsupportedEncodingException, 
      NoSuchAlgorithmException, NoSuchPaddingException { 
     AEScipher.init(Cipher.DECRYPT_MODE, decodeKey); 
     byte[] decryptedData = AEScipher.doFinal(enocdedData); 
     String result = new String(decryptedData, "UTF-8"); 
     System.out.println(result); 
     return result; 
    } 

    public byte[] getCipherData() { 
     return cipherData; 
    } 

    public String getDecryptedMsg() { 
     return msg; 
    } 


    public SecretKeySpec getKey() { 
     return decodeKey; 
    } 

    // AEScipher requires that 16 divides the length of b 
    public static byte[] handleString(byte[] b) 
      throws UnsupportedEncodingException { 
     byte[] temp = b; 
     if (temp.length % 16 != 0) { 
      byte[] byteMsg = Arrays.copyOf(temp, temp.length + 16 
        - (temp.length % 16)); 
      return byteMsg; 
     } 
     return temp; 
    } 

    public static String byteToHex(byte[] msg) throws UnsupportedEncodingException { 
     return Hex.encodeHexString(msg); 
    } 

    public static byte[] hexToByte(String msg) throws DecoderException { 
     return Hex.decodeHex(msg); 
    } 

} 
+0

모든 암호화가 16 진수가되도록하십시오. 나는 당신의 다른 제안을 시도했고, 같은 결과를 얻었다. – Kortlek

+0

ciphertext와 같은 2 진 데이터를 UTF-8로 처리 할 수 ​​없습니다. – ntoskrnl

+0

중간에 주된 문제는 byte []를 16 진수 문자열로 변환하는 것입니다. – RobbySherwood