2010-03-24 6 views
7

자바에서 AES 인코딩 데이터를 네트워크를 통해 보내고 루비에서 디코딩하려고합니다.AES 자바 인코딩, 루비 디코딩

기본 문자열로 잘 작동하지만 일단 문자열의 길이가 16 바이트 이상이면 디코딩 된 루비 문자열의 인코딩에 쓰레기가 생깁니다. 나는 패딩과 관련이 있다고 생각한다. (정확한 크기가 16 인 문자열에도 영향을 미치기 때문에 확실하지 않다.)

PKCS를 사용하거나 정확한 길이와 일치하도록 문자열의 끝에 공백을 추가하려고 시도했다. 행운

또한 왜 내가 "aes-256-cbc"루비 내 Java 코드를 사용하여 알면서 128 할 설명 할 수 있습니까? 시도 AES를-128-CBC 루비는 여기 내 기본 코드

자바

byte[] raw = key.getBytes(); 
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 
Cipher cipher = Cipher.getInstance("AES"); 
cipher.init(Cipher.ENCRYPT_MODE, skeySpec); 
byte[] encrypted = cipher.doFinal(str.getBytes()); 
return new BASE64Encoder().encode(encrypted); 

루비

def aes_decrypt(key, encrypted) 
decipher =OpenSSL::Cipher::Cipher.new("aes-256-cbc") 
decipher.decrypt 
decipher.padding = 0 
decipher.key = key 
d = decipher.update(encrypted) 
d << decipher.final 
logger.debug "email #{d.to_s}" 
return d.to_s 
end 

답변

11

패딩이 있고 연쇄이 있습니다. 먼저 체인 연결 권한을 얻어야합니다.

AES는 더 이상없고 더 적은 16 바이트 블록을 암호화합니다. 잠재적으로 16 바이트보다 긴 메시지를 암호화하려면 데이터를 블록으로 분할하고 나중에 다시 어셈블하는 방법을 결정해야합니다. 기본 분할 알고리즘은 ECB입니다.이 블록은 개별적으로 암호화 된 블록으로 "단지 분할"됩니다. ECB는 어떤 평문 블록이 같은지 (동일한 암호로 암호화 될 것임) 정보를 누설하고 "중복"이 종종 "정상"데이터에서 발생하기 때문에 실제 데이터에 약한 것으로 알려져 있습니다.

따라서 데이터 중복을 숨기기 위해 데이터 블록을 어떤 방식으로 "임의 화"해야합니다.CBC 모드는 "연결"을 통해이를 수행합니다. 블록의 처리는 이전 블록의 암호화 결과에 따라 다릅니다. 즉, to-encrypt 평문 블록은 이전 블록 암호화의 출력과 결합됩니다 (비트 XOR 사용).

여기서 중요한 점은 암호화 할 첫 번째 블록 (데이터의 처음 16 바이트)에는 "이전 블록"이 없으므로 XOR에 아무 것도 없다는 것입니다. 이는 "임의의 IV", 즉 XORing 단계에서 "블록 -1"로 사용될 16 개의 임의 바이트 시퀀스를 선택하여 해결됩니다. IV는 해독 당사자에게 알려 져야합니다 (그렇지 않으면 해독 된 블록을 XOR 할 대상을 알 수 없으며 데이터의 처음 16 바이트는 알 수 없습니다). 밝은면은 IV가 비밀 일 필요가 없다는 것입니다. (각 메시지에 대해 증가 된 카운터 일 수는 없지만) 일률적으로 선택되어야하지만, 보통 암호화 된 메시지 자체를 따라 "투명하게"전송 될 수 있습니다.

그래서 IV에 대해 조금 걱정할 필요가 있습니다. Java 또는 Ruby 코드에서 이에 대해 전혀 알지 못합니다. 일반적으로 Java는 ECB로 기본 설정됩니다 (따라서 IV가 전혀 없습니다). 루비가 CBC에서 "모두 제로 IV"(기본적으로 안전하지 않음)를 기본으로 설정하면 첫 번째 블록을 해독 할 수있는 것이 정상입니다 (적어두면 "그냥 작동합니다"). 그러나 정상적으로 동일합니다 후속 블록에서는 작동하지 않습니다.

그래서 명시 적으로 CBC (자바에서는 "AES"이 아니라)를 사용하고 IV를 관리하는 것이 좋습니다 (전송해야 함). 암호화 된 메시지 앞에 IV를 연결하는 규칙을 사용할 수 있습니다).

다른 몇 가지주의 사항 : 당신이 적절한 입력 길이를 가질 수 있도록 일반 텍스트로 일부 데이터를 추가하는 방법에 대한 것입니다

  • 패딩. CBC는 입력 길이가 블록 크기의 배수 (16 바이트)를 요구합니다. PKCS # 5 패딩은 널리 사용되는 방법으로 적어도 1 바이트 (최대 16 바이트)를 추가하여 모두 값이 n 인 경우 n이 추가 된 바이트 수입니다. 그러면 수신자는 얼마나 많은 바이트가 추가되었는지 (모호하지 않게) 알고 제거 할 수 있습니다. 자바가 당신을 위해 패딩을 추가 할 수 있으며, 멋지게 질문하는 경우 루비가 자동으로 패딩을 처리 할 수 ​​있다고 가정합니다.

  • Java 코드에서 key.getBytes()을 사용합니다. keyString입니다. getBytes()은 플랫폼 기본 문자 집합에 따라 문자열을 인코딩한다는 것을 알고 있습니다. 이는 항상 전 세계적으로 동일하지는 않습니다. 명시 적 charset을 지정하여 걱정을 덜어줍니다. 또한 128 비트 키를 사용하려고하지만 "AES-256"이있는 루비 쪽에서 뭔가를 얻으 려한다면 실제로 자바 측에서 256 비트 키를 사용한다고 가정합니다. 내 생각 엔 key 문자열은 16 진수 32 문자로 표시됩니다. key.getBytes()은 16 진수를 해석하지 않습니다. 문자 자체를 인코딩하여 32 바이트 배열을 만듭니다. 32 바이트는 128가 아니라 256 비트입니다.

+0

위대한 설명! –

1
이야 어떤 도움을 크게

을 감사

문자열이 작동하지 않습니다

나는 패딩에 대한 귀하의 의혹에 동의합니다. PKCS # 5 패딩은 평문을 다음 전체 블록 경계로 "반올림"합니다. 블록의 전체 개수를 지정하면 전체 패딩 블록 하나가 추가됩니다.

만약 내가 당신이라면 JCE에게 AES를 요청했을 때 정확히 무엇을 얻고 있는지 알고 싶을 것입니다. AES/CBC/PKCS5Padding을 받고 있다고 생각되지만, 네가 원해. 비슷하게 Ruby에서 끝내고있는 것을 정확하게 찾아야합니다. 해독 끝에있는 "쓰레기"가 패딩 바이트일까요? PKCS # 5 사양을 읽고 현재 사용중인 것과 비교하십시오.

자바 측에서 AES-128을 사용하고 있지만 Ruby/OpenSSL 측에서는 (분명히) AES-256을 사용한다고해서 약간 걱정됩니다. 그런 종류의 불일치는 거의 작동하지 않을 것이라고 확신합니다. 그러나 적어도 짧은 메시지는 암호화가 작동한다고 말합니다. 실제로 자바에서 AES-256을 얻는 것이 가능할 수도 있습니다 (다시 말하면, "AES"에 대해 묻는다면 은 실제로이됩니까?) 또는 뭔가 이상한 점이 있습니다. 128 비트 키를 사용하여 올바른 것으로 간주하는 것을 수행하십시오.

다음 : 암호문에 무결성 보호가 필요한지 여부를 고려 했습니까? 기밀성은 모두 매우 좋지만 성공적인 암호 해독은 암호문이 전송 중에 변조되지 않았 음을 보장하지 않습니다.

관련 문제