2016-06-14 2 views
0

두 개의 Socket이 루프백을 통해 서로 연결되어 있으며 JUnit 테스트 목적으로 서버 클라이언트 설정을 시뮬레이션하기 위해 별도의 스레드에서 실행되는 두 개의 동기식 메소드로 제어됩니다. 서버 측 소켓은 BufferedWriter이고 클라이언트 측 소켓은 BufferedReader입니다.보낸 암호문과 수신 한 암호문이 일치하지 않습니다.

의도을 통해 RSA를 사용하여 일반 텍스트 문자열을 암호화하는 자바에 내장 된 Cipher 클래스, 다음 BufferedReader에서를 읽고 다시 일반 텍스트로 암호를 해독의 BufferedWriter을 통해 결과 암호문 바이트 배열을 보낼 수 있습니다.

BufferedWriter bw; 
BufferedReader br; 
public void send(String plaintext){ 
    byte[] ciphertext = ... //encrypt plaintext here using Java's Cipher class 
    bw.write(new String(ciphertext).toCharArray()); 
    bw.newLine(); 
    bw.flush(); 
} 

public void receive(){ 
    byte[] ciphertext = br.readLine().getBytes(); 
} 

문제는 BufferedWriter 전송 바이트 배열과 일치하지 않는 BufferedReader로부터 판독 된 바이트의 어레이이다. 둘 다 콘솔에 인쇄 한 다음 비교를 위해 메모장에 복사하여 붙여 넣습니다. 일치하지 않습니다. 어쨌든 수신 된 암호문을 해독하려는 시도는 자연히 IllegalBlockSizeException을 던졌습니다.

이제 실제로는 BufferedReader.readLine()이 실제 줄 바꿈이나 수신 된 데이터의 존재 여부에 관계없이 ASCII 줄 바꿈 및 캐리지 리턴 문자 (0A 및 0D)에 대한 바이트 값을 만나는 순간을 즉시 중단하겠다고 약속했습니다. 암호화되어 있기 때문에 이러한 바이트가 포함됩니다. 단순히 readLine()을 반복하고 결과를 연결하는 것이 도움이되지 않습니다. 두 가지 중 어느 것이 멈추게되었는지 알 수 없기 때문에 암호문에 어느 것을 다시 삽입할지 알 수 없습니다. 암호문의 길이를 어지럽히는 이러한 누락 된 문자 이외에는 문제가 없습니다.

내가 실제, 고의적 인 선 종료 될 때까지 되풀이 read()readLine()를 교체 한 시도 다음 일은 :

ciphertext = new byte[0];  //to avoid a NullPointerException down the line 
byte[] stream = new byte[0]; 
while(br.ready()){ 
    stream = Arrays.copyOf(stream, stream.length + 1); 
    stream[stream.length-1] = (byte)(char)br.read(); 
} 
ciphertext = Arrays.copyOf(stream, stream.length - 5); 

는 암호문에 대한 올바른 길이를 얻었다. 이제 문제는 전체 암호문이 수신되는 동안 비트 오류로 가득 차 있다는 것입니다. 예를 들어, 패딩이 사용되지 않은 RSA-1024가 있습니다 (패딩을 던지기 전에 먼저이 작업을 수행하고 싶습니다. 이렇게하면 왼쪽과 같이 예외가 발생합니다). BufferedWriter를 통해 전송 무엇

는 : 415EFB8FBBF54FB9BFC31C45E9BEA46035D744D0015E8C7A6B17D967FFCE5F18F5A4311BAC5BB572DA3488EE1DEC8018D611A9197C52B768896EF2FE9CFA0B057D5FE478BD85F13274FF3A59B6821F64A7089B7F470B83C010F263B5753202A7EC443E17617CA1D9516F3C57788A43F14A6FB3202317E9E11F35FF2696CE19EC

BufferedReader 나온 것 : 415E7179BB514F057C021C45E93EA46035D74410015E5A7A6B176E67D9CE5F1851A4311BAC5BB572DA343FEE1D1BAC18D611A9197C52B768306E48635BFA0B057D5FE478DD26443274D93A59B61A1F64A7083A7F470B3F54104863B5753202A71B443E17617CC76E516F3C57786043444A6F42202317E9E11F35D92613CE191B

당신이 볼 수 있듯이,이 비슷하지만 사방에 차이가 있습니다. 나는 입니다.입니다. 이중 유형 캐스팅 (read()은 을 반환하기 때문에 암시 적으로 byte으로 변환되지 않습니다.)하지만 두 번째 의견을 확인하고 가능한 해결책을 지적하겠습니다. 인코딩 문제 일지 모르지만 나는 암호문의 bytechar으로 바뀌고 int으로 읽은 후 char으로 다시 캐스팅 한 다음 byte으로 다시 캐스팅했습니다. UTF-16 문자가 버퍼에 쓰여진다면 처음 환경에서 버퍼에 쓴 동일한 환경에 따라 int으로 다시 읽혀집니다. int은 원래 문자의 UTF-16 코드를 포함하지 않습니다. ? 아니면 typecasting ASCII로 해석 할 것이라고?

답변

0

현대 암호 체계의 암호문은 이진 암호입니다.바이너리 데이터가 일종의 문자 인코딩 (ASCII, UTF-8 등)이있는 문자로 해석 될 수 있다고 가정하면 실망하게됩니다. 모든 바이트가 유효한 인쇄 가능한 문자를 구성하는 것은 아닙니다. 일부 제어 문자는 암호문을 깨는 특별한 방법으로 해석됩니다.

그래서 String 기반 "스트림"(Java에서는 ...Reader...Writer)을 사용하지 않고 실제 스트림 (...InputStream...OutputStream)을 대신 사용합니다.

Writer 및 Reader를 실제로 사용해야하는 경우 byte[]을 인쇄 가능한 양식으로 인코딩해야합니다 (예 : 16 진수 또는 Base64.

+0

음 ... byte []를 16 진수 문자열로 변환 하시겠습니까? 간단하고 효과적입니다. 나는 솔직히 왜 그것이 저에게 이전에 일어나지 않았는지 당혹 스럽습니다. 나는 전환을 되돌리기위한 7 년 된 솔루션을 발견했다. 바로이 바로 사이트에서. 제안 해 주셔서 감사합니다. – amitakartok