2014-10-16 2 views
0

문자열 암호화 및 해독을 위해 SO의 예제 중 하나를 따르려고했습니다.문자열 암호화 및 암호 해독

public static String encrypt(String value) { 
     byte[] encrypted = null; 
     String encrypted_string = null; 
     try { 

      byte[] raw = new byte[]{'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y'}; 
      Key skeySpec = new SecretKeySpec(raw, "AES"); 
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
      byte[] iv = new byte[cipher.getBlockSize()]; 

      IvParameterSpec ivParams = new IvParameterSpec(iv); 
      cipher.init(Cipher.ENCRYPT_MODE, skeySpec,ivParams); 
      encrypted = cipher.doFinal(value.getBytes()); 
      System.out.println("encrypted string:" + encrypted.length); 

      //Encrypted byte array 
      System.out.println("encrypted byte array:" + encrypted); 

      //Encrypted string 
      encrypted_string = new String(encrypted); 
      System.out.println("encrypted string: " + encrypted_string); 

     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
     return encrypted_string; 
    } 

    public static String decrypt(String encrypted_string) { 
     byte[] original = null; 
     Cipher cipher = null; 
     String decrypted_string = null; 
     try { 
      byte[] raw = new byte[]{'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y'}; 
      Key key = new SecretKeySpec(raw, "AES"); 
      cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
      //the block size (in bytes), or 0 if the underlying algorithm is not a block cipher 
      byte[] ivByte = new byte[cipher.getBlockSize()]; 
      //This class specifies an initialization vector (IV). Examples which use 
      //IVs are ciphers in feedback mode, e.g., DES in CBC mode and RSA ciphers with OAEP encoding operation. 
      IvParameterSpec ivParamsSpec = new IvParameterSpec(ivByte); 
      cipher.init(Cipher.DECRYPT_MODE, key, ivParamsSpec); 
      original= cipher.doFinal(encrypted_string.getBytes()); 

      //Converts byte array to String 
      decrypted_string = new String(original); 
      System.out.println("Text Decrypted : " + decrypted_string); 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
     return decrypted_string; 
    } 

내가 문자열을 암호화하고 암호화 된 문자열을 반환 할 수 있도록하려면 :

는 여기에 지금까지 무슨이다. 그런 다음 암호화 된 문자열을 가져 와서 원래 암호 해독 된 문자열을 반환하는 내 decrypt 메서드에 전달합니다.

나는 Byte [] 배열을 사용하는 예제를 따라 갔지만 Byte 배열을 사용하고 싶지는 않습니다. 단지 문자열 만 사용하고 싶습니다. "않고 IllegalBlockSizeException 잘못된 최종 블록 길이"라고

original= cipher.doFinal(encrypted_string.getBytes()); 

을 : 위의와

문제는 내가이 줄에 오류가 있습니다. 어느 날 문자열을 바이트 배열로 변환하고 doFinal() 메서드로 전달할 수 없다고 생각합니다. 하지만 내가 원하는 형식으로이 문제를 해결하려면 어떻게해야합니까?

+3

거의 모든 암호화 알고리즘이 문자열이 아닌 바이트에서 작동합니다. 앞뒤로 변환해야한다고 받아들입니다. 즉,'string.getBytes (StandardCharsets.UTF_8)'과'new String (bytes, StandardCharsets.UTF_8)'을 사용하여 문자열과 바이트 배열 표현 사이를 효율적으로 변환 할 수 있습니다. –

+1

cipher 텍스트를 바이트가 아닌 문자열로 처리하려면 Base-64를 사용하는 것이 좋습니다. – rossum

답변

1

일반적인 서명 인 임의의 바이트 배열을 문자열로 변환하면 인쇄 할 수없는 문자가 모두 대체 문자로 바뀝니다. 대체 문자는 사용 된 인코딩에 따라 다릅니다. ASCII의 경우 이것은 무엇입니까? (3F 16 진수) 이고 UTF-8의 경우 이것은 (EFBFBD 16 진수)입니다.

public String(byte[] bytes)은 변환에 기본 인코딩을 사용하며 이는 애플리케이션에 UTF-8 일 것입니다. 그런 다음 String.getBytes()은 문자열 데이터를 기본 인코딩으로 다시 변환하므로 원래 데이터의 인쇄 할 수없는 문자 각각에 대해 EFBFBD가 많아 입니다. 차례로 AES는 블록 암호이고 16 바이트 블록에서 작동합니다. 따라서 모든 암호 텍스트의 길이는 16에 비례합니다. 따라서 잘못된 블록 크기를 얻는 이유는 으로, 손상된 데이터를 AES 암호 해독에 제공 할 때입니다.

이진 데이터를 문자열 표현으로 변환 할 수있는 가능성 중 하나는 Base64 인코딩입니다. Android에서는 Base64 클래스로 수행 할 수 있습니다.

String encryptedString = Base64.encodeToString(encrypted, Base64.DEFAULT); 
byte[] encrypted2 = Base64.decode(encryptedString, Base64.DEFAULT); 
+0

Java 8에는 Base64 인코딩 (URL 안전 인코딩 포함)이 있습니다. 또한 16 진수 인코딩을 사용하는 것이 표준입니다. –

+0

예, 그렇지만 Android에서 Java 8을 지원하게 될까요? – divanov

+0

해당 태그를 확인하지 못했습니다. 어쨌든 관심있을 수도 있습니다. –