2017-04-20 2 views
1

this answer에 샘플 코드를 사용하여 Java로 암호화/암호 해독 프로토 타입을 작성했습니다. 그러나 AES의 카운터 모드 (CTR)로 재생하려고하는데 암호화 된 값은 암호화하려는 정수 시퀀스만큼 증가하는 것처럼 보입니다. enc 값은 보통 한 자릿수로 dec 값과 어떻게 다른지Java AES 카운터 모드 증분

i = 0: enc='5941F8', dec='000', length=6 
i = 1: enc='5941F9', dec='001', length=6 
i = 2: enc='5941FA', dec='002', length=6 
i = 3: enc='5941FB', dec='003', length=6 
i = 4: enc='5941FC', dec='004', length=6 
i = 5: enc='5941FD', dec='005', length=6 
i = 6: enc='5941FE', dec='006', length=6 
i = 7: enc='5941FF', dec='007', length=6 
i = 8: enc='5941F0', dec='008', length=6 
i = 9: enc='5941F1', dec='009', length=6 
i = 10: enc='5940F8', dec='010', length=6 
i = 11: enc='5940F9', dec='011', length=6 
i = 12: enc='5940FA', dec='012', length=6 

주의 사항 :

내 프로토 타입의 다음과 같은 출력을 고려하십시오. AES의 카운터 모드에서 생성 된 암호화 된 값은 일반적으로이 반복 가능/서로 비슷하거나 잘못된 것입니까?

지금까지 다른 암호화 키, 초기화 벡터, 패딩 스키마, 다른 값에서 시작하는 더 길거나/더 짧은 정수 시퀀스 등을 사용해 보았습니다.하지만 지금까지는 아무 것도 작동하지 않는 것 같습니다. 또한 카운터 모드의 Java AES 암호에 대한 Google 및 기타 문의 사항은 지금까지 거의 사용되지 않았습니다. 내가 암호 초보자라는 것을 명심하십시오. 다음과 같이 내 프로토 타입

코드는 다음과 같습니다

public class Encryptor { 
    public static String encrypt(String key, String initVector, String value) { 
    try { 
     IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8")); 
     SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES"); 

     Cipher cipher = Cipher.getInstance("AES/CTR/PKCS5PADDING"); 
     cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); 

     byte[] encrypted = cipher.doFinal(value.getBytes()); 
     return DatatypeConverter.printHexBinary(encrypted); 
    } 
    catch (Exception ex) { 
     throw new RuntimeException(ex); 
    } 
    } 

    public static String decrypt(String key, String initVector, String encrypted) { 
    try { 
     IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8")); 
     SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES"); 

     Cipher cipher = Cipher.getInstance("AES/CTR/PKCS5PADDING"); 
     cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); 

     byte[] decrypted = cipher.doFinal(DatatypeConverter.parseHexBinary(encrypted)); 
     return new String(decrypted); 
    } 
    catch (Exception ex) { 
     ex.printStackTrace(); 
    } 

    return null; 
    } 

    public static void main(String[] args) { 
    String key = "Bar12345Bar12345"; // 128 bit key 
    String initVector = "RandomInitVector"; // 16 bytes IV 

    System.out.println(decrypt(key, initVector, 
     encrypt(key, initVector, "Hello World"))); 
    for (int i = 0; i < 1000; ++i) { 
     String encrypted = encrypt(key, initVector, StringUtils.leftPad("" + i, 3, '0')); 
     String decrypted = decrypt(key, initVector, encrypted); 
     int encLen = encrypted.length(); 
     System.out.println("i = " + i + ": enc='" + encrypted + "', dec='" + decrypted + "', length=" + encLen); 
    } 
    } 
} 
+2

흥미롭게도, 나는 당신이 연결하고있는 대답을 downvoted. 너도 그래야 해. CBC 모드에서 동일한 IV를 사용하는 것은 문제이지만 CTR 모드에서는 더 큰 문제이므로 질문하십시오. –

+0

당신이이 질문을하지 못하도록 막아야하는 링크 된 대답 아래에 내 의견을 기록하십시오. 나는해야 할 일을 충분히 분명히하지 않았는가? –

+0

아니, 대답은 괜찮 았어. 당신의 충고를 받았을 때 나는 더 나은 데이터를 얻었습니다. 그러나 당신의 대답은 흥미로운 결과 문제를 야기합니다. 답에 대한 아래의 주석을보십시오. – entpnerd

답변

4

CTR mode is a streaming mode of operation. 이는 nonce와 키 쌍이 고유 키 스트림을 생성 한 다음 평문과 XOR 처리된다는 것을 의미합니다. XOR은 대칭이므로, 암호문을 해독하는 데 정확히 동일한 연산이 적용됩니다.

이제 XOR은 비트 방식으로 작동합니다. 과 동일한 키와 nonce 쌍을 여러 암호화에 사용하면 매번 똑같은 키 스트림으로 평문을 암호화합니다. 이것은 두 개의 일반 텍스트 사이에 다른 비트 위치가 두 개의 결과 암호 텍스트를 비교할 때 서로 다를 것임을 의미합니다. 이를 2 회 패드 또는 여러 번 패드라고합니다.

예를 들어 각 반복마다 XOR encdec이있는 경우 항상 0x6971C8이됩니다. 이것들은 키 스트림의 처음 3 바이트입니다. ASCII 문자 0은 0x30이고 0x59으로 XOR 할 때 0x69 등입니다.

동일한 키를 사용하여 암호화 할 때마다 다른 논스 (한 번 사용 된 번호)를 사용하는 것이 해결책입니다. nonce (IV라고도 함)는 기본 블록 암호의 블록 크기보다 작습니다. AES의 블록 크기는 16 바이트입니다. 일반적으로 카운터 충돌없이 암호화 할 데이터의 양에 따라 길이가 8 바이트 또는 12 바이트 인 랜덤 nonce를 선택합니다. 충돌 가능성이 거의없는 많은 임의의 논스를 생성 할 수 있고 카운터 충돌 가능성없이 키 + 넌스 쌍으로 최대 68GB를 암호화 할 수 있기 때문에 12 바이트 논스는 최상의 절충안처럼 보입니다.

+0

당신의 해결책은 작동합니다. 매우 감사합니다. 기본적으로 초기화 벡터와 같은 버전의 변수 'i'를 사용했습니다. 그러나 이것은 해결할 수있는 것보다 더 큰 이슈를 제기합니다. 어떤 순서로 정수가되어야하는 값을 해독 할 실용적인 방법이 실제로 없다고 추측하는 것이 맞습니까? 해독이 작동하려면 초기화 벡터를 알아야합니다. 다시 한 번 감사드립니다! – entpnerd

+2

예, 아니요, 임의로 선택하지 않아도되지만 다른 값이어야합니다. 예를 들어, 암호화하려는 정수와 연관된 고유 ID가있는 경우 해당 ID를 간단히 nonce로 사용할 수 있습니다. 당신이 그것을 원하지 않는다면, 항상 포맷 - 보존 암호화를 사용할 가능성이 있습니다. FPE 구현은 많지 않습니다. –

+2

경고 : IV는 논스가 아니며 CTR 모드의 초기 카운터 값입니다. nonce는 예 : IV의 첫 번째 (가장 왼쪽) 8 바이트. 고유 한 IV를 사용하는 경우에도 카운터 값이 겹치지 않도록 나머지는 비워 둡니다. 이것은 답변에서 충분히 명확하지 않습니다. –