2016-07-19 2 views
5

때때로, 나는 흥미로운, 이상한 일을 충족를 사용하여 성공!이상한 DES 동작 해독은 다른 키

아무도 나에게 어떤 문제가 있음을 나타낼 수 있습니까? 고마워.

나 DES/AES 등, 난 그냥 문제가 어디 있는지 알고 싶어 3 배로 전환 할 수하려고하지 마십시오 - 자바 SDK 또는 Java SDK의 버그를 호출하는 방법은?

D:\>java -version 
java version "1.7.0_21" 
Java(TM) SE Runtime Environment (build 1.7.0_21-b11) 
Java HotSpot(TM) 64-Bit Server VM (build 23.21-b01, mixed mode) 

D:\>java DESTest -e 12345678 abcde977 

encrypted as [17fd146fa6fdbb5db667efe657dfcb60] 

D:\>java DESTest -d 17fd146fa6fdbb5db667efe657dfcb60 abcde977 

decryted as [12345678] 

D:\>java DESTest -d 17fd146fa6fdbb5db667efe657dfcb60 abcde976 

decryted as [12345678] 

D:\>java DESTest -d 17fd146fa6fdbb5db667efe657dfcb60 abcde967 

decryted as [12345678] 

D:\>java DESTest -d 17fd146fa6fdbb5db667efe657dfcb60 abcde867 

decryted as [12345678] 

D:\>java DESTest -d 17fd146fa6fdbb5db667efe657dfcb60 abcdf867 
Exception in thread "main" java.lang.RuntimeException: javax.crypto.BadPaddingEx 
ception: Given final block not properly padded 
     at DESTest.des(DESTest.java:46) 
     at DESTest.dec(DESTest.java:31) 
     at DESTest.main(DESTest.java:19) 
Caused by: javax.crypto.BadPaddingException: Given final block not properly padd 
ed 
     at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811) 
     at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676) 
     at com.sun.crypto.provider.DESCipher.engineDoFinal(DESCipher.java:314) 
     at javax.crypto.Cipher.doFinal(Cipher.java:2087) 
     at DESTest.des(DESTest.java:44) 
     ... 2 more 

D:\>java DESTest -e 12345678 abcde976 

encrypted as [17fd146fa6fdbb5db667efe657dfcb60] 

D:\>java DESTest -e 12345678 abcde967 

encrypted as [17fd146fa6fdbb5db667efe657dfcb60] 

D:\> 

는 소스 코드 :

import java.io.UnsupportedEncodingException; 
import java.security.SecureRandom; 

import javax.crypto.Cipher; 
import javax.crypto.SecretKey; 
import javax.crypto.SecretKeyFactory; 
import javax.crypto.spec.DESKeySpec; 

public class DESTest { 
    public static void main(String[] args) { 
     if (args.length < 3) { 
      System.out.println("usage: java " + DESTest.class.getCanonicalName() + " -e|-d text key"); 
      return; 
     } 
     String mode = args[0].trim(); 
     String text = args[1].trim(); 
     String key = args[2].trim(); 
     try { 
      String s = "-d".equalsIgnoreCase(mode) ? dec(text, key) : enc(text, key); 
      System.out.println("\n" + ("-d".equalsIgnoreCase(mode) ? "decryted as [" : "encrypted as [") + s + "]"); 
     } catch (UnsupportedEncodingException e) { 
      e.printStackTrace(); 
     } 
    } 

    private static String enc(String plainText, String key) throws UnsupportedEncodingException { 
     return new String(encHex(des(plainText.getBytes("UTF-8"), key, Cipher.ENCRYPT_MODE))); 
    } 

    private static String dec(String encrypted, String key) throws UnsupportedEncodingException { 
     return new String(des(decHex(encrypted), key, Cipher.DECRYPT_MODE), "UTF-8"); 
    } 

    private static byte[] des(byte[] bytes, String key, int cipherMode) { 
     final String encoding = "UTF-8"; 
     try { 
      DESKeySpec desKey = new DESKeySpec(key.getBytes(encoding)); 
      SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); 
      SecretKey securekey = keyFactory.generateSecret(desKey); 
      // SecretKey securekey = new SecretKeySpec(key.getBytes(encoding), "DES");//same result as the 3 lines above 
      Cipher cipher = Cipher.getInstance("DES"); 
      SecureRandom random = new SecureRandom(); 
      cipher.init(cipherMode, securekey, random); 
      return cipher.doFinal(bytes); 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 

    private static final char[] HEX_CHARS = "abcdef".toCharArray(); 

    private static String encHex(byte[] bytes) { 
     final char[] chars = new char[bytes.length * 2]; 
     for (int i = 0, j = 0; i < bytes.length; i++) { 
      chars[j++] = HEX_CHARS[(0xF0 & bytes[i]) >>> 4]; 
      chars[j++] = HEX_CHARS[0x0F & bytes[i]]; 
     } 
     return new String(chars); 
    } 

    private static byte[] decHex(String hex) { 
     final int len = hex.length(); 
     final byte[] bytes = new byte[len/2]; 
     for (int i = 0, j = 0; j < len; i++) { 
      int f = Character.digit(hex.charAt(j), 16) << 4; 
      j++; 
      f = f | Character.digit(hex.charAt(j), 16); 
      j++; 
      bytes[i] = (byte) (f & 0xFF); 
     } 
     return bytes; 
    } 
} 
+0

는 다른 키 문자열 [97, 98, 98, 100, 100, 56, 55, 55], 동일한 secureKey 복호의 성공 여부를 일으킬 즉 동일한 secureKey (라인 39)을 생성 할 것으로 . 하지만 다른 키가 동일한 secureKey를 생성하는 이유와 그것을 피하는 방법을 알 수 없습니까? – reqresp

답변

4

데스 작업 (암호화 및 암호 해독)은 각 바이트의 lsbit을 무시 아래

윈도우 7 리눅스 상자에 같은 결과에 출력 키의. 즉, 키 내의 lsbits를 뒤집 으면 조작은 동일하게 유지됩니다. 그것은 당신이 시도한 키에서 일어나는 일입니다 : ASCII 코드는 0x20이고, 스페이스는 ASCII 코드입니다! 0x21입니다. 그들은 lsbit에서만 다릅니다. 따라서 키에 공백을 나타내는 ASCII 코드가있는 바이트가 있으면!로 대체 할 수 있으며 해독 할 수 있습니다. 마찬가지로 *의 ASCII 코드는 0x2a이고 +의 ASCII 코드는 0x2b입니다. 또한 lsbit에서만 다릅니다. 원래 표준에서 DES

는 lsbit은 (각 바이트는 항상 홀수 패리티를 갖는) 패리티 체크 비트로서 사용되어 있었다. 그것은 수동으로 입력 된 키에 대한 약한 오류 검사로되어있었습니다. 요즘에는 아무도이 패리티 체크를하지 않으므로 lsbit는 무시됩니다.

Poncho's 통찰력이있는 Answer에서 Cryptography Stackexchange으로 추출됩니다.

+0

알 것. 설명 주셔서 감사합니다! – reqresp

1

DES 이제 무시할 각 키의 바이트가 lsbit initiallly 패리티를 사용하고, 56 비트 키를 갖는다.

답변 : DES를 사용하지 마십시오! DES는 안전하지 못하고 AES (Advanced Encryption Standard)에 의해 능가되었습니다. AES는 DES를 대체하기 위해 특별히 설계되었습니다.

또한 하나의 키로 문자열을 사용하지 않아야합니다, 가장 좋은 방법은 PBKDF2 (암호 기반 키 유도 기능)와 같은 기능을 가진 문자열에서 암호화 키를 유도하는 것입니다. I 코드를 디버깅

+0

알았는데. 설명 주셔서 감사합니다! – reqresp

관련 문제