@Test(expected = IOException.class) public void testWrongStreamNumberThrowsException() throws Exception { byte[] wrongStreamNumberBytes = new byte[8]; ByteUtils.writeUint64(streamNumber + 1, wrongStreamNumberBytes, 0); byte[] frameHeader = new byte[FRAME_HEADER_LENGTH]; FrameEncoder.encodeHeader(frameHeader, false, payloadLength, paddingLength); byte[] frameHeader1 = new byte[FRAME_HEADER_LENGTH]; int payloadLength1 = 345, paddingLength1 = 456; FrameEncoder.encodeHeader(frameHeader1, true, payloadLength1, paddingLength1); byte[] payload1 = TestUtils.getRandomBytes(payloadLength1); ByteArrayOutputStream out = new ByteArrayOutputStream(); out.write(streamHeaderNonce); out.write(protocolVersionBytes); out.write(wrongStreamNumberBytes); out.write(frameKey.getBytes()); out.write(new byte[MAC_LENGTH]); out.write(frameHeader); out.write(payload); out.write(new byte[paddingLength]); out.write(new byte[MAC_LENGTH]); out.write(frameHeader1); out.write(payload1); out.write(new byte[paddingLength1]); out.write(new byte[MAC_LENGTH]); ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); StreamDecrypterImpl s = new StreamDecrypterImpl(in, cipher, streamNumber, streamHeaderKey); byte[] buffer = new byte[MAX_PAYLOAD_LENGTH]; s.readFrame(buffer); }
@Override public int readFrame(byte[] payload) throws IOException { if (payload.length < MAX_PAYLOAD_LENGTH) throw new IllegalArgumentException(); if (finalFrame) return -1; if (frameNumber < 0) throw new IOException(); if (frameKey == null) readStreamHeader(); int offset = 0; while (offset < FRAME_HEADER_LENGTH) { int read = in.read(frameCiphertext, offset, FRAME_HEADER_LENGTH - offset); if (read == -1) throw new EOFException(); offset += read; } FrameEncoder.encodeNonce(frameNonce, frameNumber, true); try { cipher.init(false, frameKey, frameNonce); int decrypted = cipher.process(frameCiphertext, 0, FRAME_HEADER_LENGTH, frameHeader, 0); if (decrypted != FRAME_HEADER_PLAINTEXT_LENGTH) throw new RuntimeException(); } catch (GeneralSecurityException e) { throw new FormatException(); } finalFrame = FrameEncoder.isFinalFrame(frameHeader); int payloadLength = FrameEncoder.getPayloadLength(frameHeader); int paddingLength = FrameEncoder.getPaddingLength(frameHeader); if (payloadLength + paddingLength > MAX_PAYLOAD_LENGTH) throw new FormatException(); int frameLength = FRAME_HEADER_LENGTH + payloadLength + paddingLength + MAC_LENGTH; while (offset < frameLength) { int read = in.read(frameCiphertext, offset, frameLength - offset); if (read == -1) throw new EOFException(); offset += read; } FrameEncoder.encodeNonce(frameNonce, frameNumber, false); try { cipher.init(false, frameKey, frameNonce); int decrypted = cipher.process(frameCiphertext, FRAME_HEADER_LENGTH, payloadLength + paddingLength + MAC_LENGTH, payload, 0); if (decrypted != payloadLength + paddingLength) throw new RuntimeException(); } catch (GeneralSecurityException e) { throw new FormatException(); } for (int i = 0; i < paddingLength; i++) if (payload[payloadLength + i] != 0) throw new FormatException(); frameNumber++; return payloadLength; }
StreamDecrypterImpl implements StreamDecrypter { @Override public int readFrame(byte[] payload) throws IOException { if (payload.length < MAX_PAYLOAD_LENGTH) throw new IllegalArgumentException(); if (finalFrame) return -1; if (frameNumber < 0) throw new IOException(); if (frameKey == null) readStreamHeader(); int offset = 0; while (offset < FRAME_HEADER_LENGTH) { int read = in.read(frameCiphertext, offset, FRAME_HEADER_LENGTH - offset); if (read == -1) throw new EOFException(); offset += read; } FrameEncoder.encodeNonce(frameNonce, frameNumber, true); try { cipher.init(false, frameKey, frameNonce); int decrypted = cipher.process(frameCiphertext, 0, FRAME_HEADER_LENGTH, frameHeader, 0); if (decrypted != FRAME_HEADER_PLAINTEXT_LENGTH) throw new RuntimeException(); } catch (GeneralSecurityException e) { throw new FormatException(); } finalFrame = FrameEncoder.isFinalFrame(frameHeader); int payloadLength = FrameEncoder.getPayloadLength(frameHeader); int paddingLength = FrameEncoder.getPaddingLength(frameHeader); if (payloadLength + paddingLength > MAX_PAYLOAD_LENGTH) throw new FormatException(); int frameLength = FRAME_HEADER_LENGTH + payloadLength + paddingLength + MAC_LENGTH; while (offset < frameLength) { int read = in.read(frameCiphertext, offset, frameLength - offset); if (read == -1) throw new EOFException(); offset += read; } FrameEncoder.encodeNonce(frameNonce, frameNumber, false); try { cipher.init(false, frameKey, frameNonce); int decrypted = cipher.process(frameCiphertext, FRAME_HEADER_LENGTH, payloadLength + paddingLength + MAC_LENGTH, payload, 0); if (decrypted != payloadLength + paddingLength) throw new RuntimeException(); } catch (GeneralSecurityException e) { throw new FormatException(); } for (int i = 0; i < paddingLength; i++) if (payload[payloadLength + i] != 0) throw new FormatException(); frameNumber++; return payloadLength; } }
StreamDecrypterImpl implements StreamDecrypter { @Override public int readFrame(byte[] payload) throws IOException { if (payload.length < MAX_PAYLOAD_LENGTH) throw new IllegalArgumentException(); if (finalFrame) return -1; if (frameNumber < 0) throw new IOException(); if (frameKey == null) readStreamHeader(); int offset = 0; while (offset < FRAME_HEADER_LENGTH) { int read = in.read(frameCiphertext, offset, FRAME_HEADER_LENGTH - offset); if (read == -1) throw new EOFException(); offset += read; } FrameEncoder.encodeNonce(frameNonce, frameNumber, true); try { cipher.init(false, frameKey, frameNonce); int decrypted = cipher.process(frameCiphertext, 0, FRAME_HEADER_LENGTH, frameHeader, 0); if (decrypted != FRAME_HEADER_PLAINTEXT_LENGTH) throw new RuntimeException(); } catch (GeneralSecurityException e) { throw new FormatException(); } finalFrame = FrameEncoder.isFinalFrame(frameHeader); int payloadLength = FrameEncoder.getPayloadLength(frameHeader); int paddingLength = FrameEncoder.getPaddingLength(frameHeader); if (payloadLength + paddingLength > MAX_PAYLOAD_LENGTH) throw new FormatException(); int frameLength = FRAME_HEADER_LENGTH + payloadLength + paddingLength + MAC_LENGTH; while (offset < frameLength) { int read = in.read(frameCiphertext, offset, frameLength - offset); if (read == -1) throw new EOFException(); offset += read; } FrameEncoder.encodeNonce(frameNonce, frameNumber, false); try { cipher.init(false, frameKey, frameNonce); int decrypted = cipher.process(frameCiphertext, FRAME_HEADER_LENGTH, payloadLength + paddingLength + MAC_LENGTH, payload, 0); if (decrypted != payloadLength + paddingLength) throw new RuntimeException(); } catch (GeneralSecurityException e) { throw new FormatException(); } for (int i = 0; i < paddingLength; i++) if (payload[payloadLength + i] != 0) throw new FormatException(); frameNumber++; return payloadLength; } StreamDecrypterImpl(InputStream in, AuthenticatedCipher cipher,
			long streamNumber, SecretKey streamHeaderKey); }
StreamDecrypterImpl implements StreamDecrypter { @Override public int readFrame(byte[] payload) throws IOException { if (payload.length < MAX_PAYLOAD_LENGTH) throw new IllegalArgumentException(); if (finalFrame) return -1; if (frameNumber < 0) throw new IOException(); if (frameKey == null) readStreamHeader(); int offset = 0; while (offset < FRAME_HEADER_LENGTH) { int read = in.read(frameCiphertext, offset, FRAME_HEADER_LENGTH - offset); if (read == -1) throw new EOFException(); offset += read; } FrameEncoder.encodeNonce(frameNonce, frameNumber, true); try { cipher.init(false, frameKey, frameNonce); int decrypted = cipher.process(frameCiphertext, 0, FRAME_HEADER_LENGTH, frameHeader, 0); if (decrypted != FRAME_HEADER_PLAINTEXT_LENGTH) throw new RuntimeException(); } catch (GeneralSecurityException e) { throw new FormatException(); } finalFrame = FrameEncoder.isFinalFrame(frameHeader); int payloadLength = FrameEncoder.getPayloadLength(frameHeader); int paddingLength = FrameEncoder.getPaddingLength(frameHeader); if (payloadLength + paddingLength > MAX_PAYLOAD_LENGTH) throw new FormatException(); int frameLength = FRAME_HEADER_LENGTH + payloadLength + paddingLength + MAC_LENGTH; while (offset < frameLength) { int read = in.read(frameCiphertext, offset, frameLength - offset); if (read == -1) throw new EOFException(); offset += read; } FrameEncoder.encodeNonce(frameNonce, frameNumber, false); try { cipher.init(false, frameKey, frameNonce); int decrypted = cipher.process(frameCiphertext, FRAME_HEADER_LENGTH, payloadLength + paddingLength + MAC_LENGTH, payload, 0); if (decrypted != payloadLength + paddingLength) throw new RuntimeException(); } catch (GeneralSecurityException e) { throw new FormatException(); } for (int i = 0; i < paddingLength; i++) if (payload[payloadLength + i] != 0) throw new FormatException(); frameNumber++; return payloadLength; } StreamDecrypterImpl(InputStream in, AuthenticatedCipher cipher,
			long streamNumber, SecretKey streamHeaderKey); @Override int readFrame(byte[] payload); }
StreamDecrypterImpl implements StreamDecrypter { @Override public int readFrame(byte[] payload) throws IOException { if (payload.length < MAX_PAYLOAD_LENGTH) throw new IllegalArgumentException(); if (finalFrame) return -1; if (frameNumber < 0) throw new IOException(); if (frameKey == null) readStreamHeader(); int offset = 0; while (offset < FRAME_HEADER_LENGTH) { int read = in.read(frameCiphertext, offset, FRAME_HEADER_LENGTH - offset); if (read == -1) throw new EOFException(); offset += read; } FrameEncoder.encodeNonce(frameNonce, frameNumber, true); try { cipher.init(false, frameKey, frameNonce); int decrypted = cipher.process(frameCiphertext, 0, FRAME_HEADER_LENGTH, frameHeader, 0); if (decrypted != FRAME_HEADER_PLAINTEXT_LENGTH) throw new RuntimeException(); } catch (GeneralSecurityException e) { throw new FormatException(); } finalFrame = FrameEncoder.isFinalFrame(frameHeader); int payloadLength = FrameEncoder.getPayloadLength(frameHeader); int paddingLength = FrameEncoder.getPaddingLength(frameHeader); if (payloadLength + paddingLength > MAX_PAYLOAD_LENGTH) throw new FormatException(); int frameLength = FRAME_HEADER_LENGTH + payloadLength + paddingLength + MAC_LENGTH; while (offset < frameLength) { int read = in.read(frameCiphertext, offset, frameLength - offset); if (read == -1) throw new EOFException(); offset += read; } FrameEncoder.encodeNonce(frameNonce, frameNumber, false); try { cipher.init(false, frameKey, frameNonce); int decrypted = cipher.process(frameCiphertext, FRAME_HEADER_LENGTH, payloadLength + paddingLength + MAC_LENGTH, payload, 0); if (decrypted != payloadLength + paddingLength) throw new RuntimeException(); } catch (GeneralSecurityException e) { throw new FormatException(); } for (int i = 0; i < paddingLength; i++) if (payload[payloadLength + i] != 0) throw new FormatException(); frameNumber++; return payloadLength; } StreamDecrypterImpl(InputStream in, AuthenticatedCipher cipher,
			long streamNumber, SecretKey streamHeaderKey); @Override int readFrame(byte[] payload);  }