@Test public void testAcceptsMaxPayloadWithoutPadding() throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher, streamNumber, tag, streamHeaderNonce, streamHeaderKey, frameKey); byte[] bigPayload = new byte[MAX_PAYLOAD_LENGTH]; s.writeFrame(bigPayload, MAX_PAYLOAD_LENGTH, 0, false); assertEquals(TAG_LENGTH + STREAM_HEADER_LENGTH + MAX_FRAME_LENGTH, out.size()); }
@Override public void writeFrame(byte[] payload, int payloadLength, int paddingLength, boolean finalFrame) throws IOException { if (payloadLength < 0 || paddingLength < 0) throw new IllegalArgumentException(); if (payloadLength + paddingLength > MAX_PAYLOAD_LENGTH) throw new IllegalArgumentException(); if (frameNumber < 0) throw new IOException(); if (writeTag) writeTag(); if (writeStreamHeader) writeStreamHeader(); FrameEncoder.encodeHeader(frameHeader, finalFrame, payloadLength, paddingLength); FrameEncoder.encodeNonce(frameNonce, frameNumber, true); try { cipher.init(true, frameKey, frameNonce); int encrypted = cipher.process(frameHeader, 0, FRAME_HEADER_PLAINTEXT_LENGTH, frameCiphertext, 0); if (encrypted != FRAME_HEADER_LENGTH) throw new RuntimeException(); } catch (GeneralSecurityException badCipher) { throw new RuntimeException(badCipher); } System.arraycopy(payload, 0, framePlaintext, 0, payloadLength); for (int i = 0; i < paddingLength; i++) framePlaintext[payloadLength + i] = 0; FrameEncoder.encodeNonce(frameNonce, frameNumber, false); try { cipher.init(true, frameKey, frameNonce); int encrypted = cipher.process(framePlaintext, 0, payloadLength + paddingLength, frameCiphertext, FRAME_HEADER_LENGTH); if (encrypted != payloadLength + paddingLength + MAC_LENGTH) throw new RuntimeException(); } catch (GeneralSecurityException badCipher) { throw new RuntimeException(badCipher); } out.write(frameCiphertext, 0, FRAME_HEADER_LENGTH + payloadLength + paddingLength + MAC_LENGTH); frameNumber++; }
StreamEncrypterImpl implements StreamEncrypter { @Override public void writeFrame(byte[] payload, int payloadLength, int paddingLength, boolean finalFrame) throws IOException { if (payloadLength < 0 || paddingLength < 0) throw new IllegalArgumentException(); if (payloadLength + paddingLength > MAX_PAYLOAD_LENGTH) throw new IllegalArgumentException(); if (frameNumber < 0) throw new IOException(); if (writeTag) writeTag(); if (writeStreamHeader) writeStreamHeader(); FrameEncoder.encodeHeader(frameHeader, finalFrame, payloadLength, paddingLength); FrameEncoder.encodeNonce(frameNonce, frameNumber, true); try { cipher.init(true, frameKey, frameNonce); int encrypted = cipher.process(frameHeader, 0, FRAME_HEADER_PLAINTEXT_LENGTH, frameCiphertext, 0); if (encrypted != FRAME_HEADER_LENGTH) throw new RuntimeException(); } catch (GeneralSecurityException badCipher) { throw new RuntimeException(badCipher); } System.arraycopy(payload, 0, framePlaintext, 0, payloadLength); for (int i = 0; i < paddingLength; i++) framePlaintext[payloadLength + i] = 0; FrameEncoder.encodeNonce(frameNonce, frameNumber, false); try { cipher.init(true, frameKey, frameNonce); int encrypted = cipher.process(framePlaintext, 0, payloadLength + paddingLength, frameCiphertext, FRAME_HEADER_LENGTH); if (encrypted != payloadLength + paddingLength + MAC_LENGTH) throw new RuntimeException(); } catch (GeneralSecurityException badCipher) { throw new RuntimeException(badCipher); } out.write(frameCiphertext, 0, FRAME_HEADER_LENGTH + payloadLength + paddingLength + MAC_LENGTH); frameNumber++; } }
StreamEncrypterImpl implements StreamEncrypter { @Override public void writeFrame(byte[] payload, int payloadLength, int paddingLength, boolean finalFrame) throws IOException { if (payloadLength < 0 || paddingLength < 0) throw new IllegalArgumentException(); if (payloadLength + paddingLength > MAX_PAYLOAD_LENGTH) throw new IllegalArgumentException(); if (frameNumber < 0) throw new IOException(); if (writeTag) writeTag(); if (writeStreamHeader) writeStreamHeader(); FrameEncoder.encodeHeader(frameHeader, finalFrame, payloadLength, paddingLength); FrameEncoder.encodeNonce(frameNonce, frameNumber, true); try { cipher.init(true, frameKey, frameNonce); int encrypted = cipher.process(frameHeader, 0, FRAME_HEADER_PLAINTEXT_LENGTH, frameCiphertext, 0); if (encrypted != FRAME_HEADER_LENGTH) throw new RuntimeException(); } catch (GeneralSecurityException badCipher) { throw new RuntimeException(badCipher); } System.arraycopy(payload, 0, framePlaintext, 0, payloadLength); for (int i = 0; i < paddingLength; i++) framePlaintext[payloadLength + i] = 0; FrameEncoder.encodeNonce(frameNonce, frameNumber, false); try { cipher.init(true, frameKey, frameNonce); int encrypted = cipher.process(framePlaintext, 0, payloadLength + paddingLength, frameCiphertext, FRAME_HEADER_LENGTH); if (encrypted != payloadLength + paddingLength + MAC_LENGTH) throw new RuntimeException(); } catch (GeneralSecurityException badCipher) { throw new RuntimeException(badCipher); } out.write(frameCiphertext, 0, FRAME_HEADER_LENGTH + payloadLength + paddingLength + MAC_LENGTH); frameNumber++; } StreamEncrypterImpl(OutputStream out, AuthenticatedCipher cipher,
			long streamNumber, @Nullable byte[] tag, byte[] streamHeaderNonce,
			SecretKey streamHeaderKey, SecretKey frameKey); }
StreamEncrypterImpl implements StreamEncrypter { @Override public void writeFrame(byte[] payload, int payloadLength, int paddingLength, boolean finalFrame) throws IOException { if (payloadLength < 0 || paddingLength < 0) throw new IllegalArgumentException(); if (payloadLength + paddingLength > MAX_PAYLOAD_LENGTH) throw new IllegalArgumentException(); if (frameNumber < 0) throw new IOException(); if (writeTag) writeTag(); if (writeStreamHeader) writeStreamHeader(); FrameEncoder.encodeHeader(frameHeader, finalFrame, payloadLength, paddingLength); FrameEncoder.encodeNonce(frameNonce, frameNumber, true); try { cipher.init(true, frameKey, frameNonce); int encrypted = cipher.process(frameHeader, 0, FRAME_HEADER_PLAINTEXT_LENGTH, frameCiphertext, 0); if (encrypted != FRAME_HEADER_LENGTH) throw new RuntimeException(); } catch (GeneralSecurityException badCipher) { throw new RuntimeException(badCipher); } System.arraycopy(payload, 0, framePlaintext, 0, payloadLength); for (int i = 0; i < paddingLength; i++) framePlaintext[payloadLength + i] = 0; FrameEncoder.encodeNonce(frameNonce, frameNumber, false); try { cipher.init(true, frameKey, frameNonce); int encrypted = cipher.process(framePlaintext, 0, payloadLength + paddingLength, frameCiphertext, FRAME_HEADER_LENGTH); if (encrypted != payloadLength + paddingLength + MAC_LENGTH) throw new RuntimeException(); } catch (GeneralSecurityException badCipher) { throw new RuntimeException(badCipher); } out.write(frameCiphertext, 0, FRAME_HEADER_LENGTH + payloadLength + paddingLength + MAC_LENGTH); frameNumber++; } StreamEncrypterImpl(OutputStream out, AuthenticatedCipher cipher,
			long streamNumber, @Nullable byte[] tag, byte[] streamHeaderNonce,
			SecretKey streamHeaderKey, SecretKey frameKey); @Override void writeFrame(byte[] payload, int payloadLength,
			int paddingLength, boolean finalFrame); @Override void flush(); }
StreamEncrypterImpl implements StreamEncrypter { @Override public void writeFrame(byte[] payload, int payloadLength, int paddingLength, boolean finalFrame) throws IOException { if (payloadLength < 0 || paddingLength < 0) throw new IllegalArgumentException(); if (payloadLength + paddingLength > MAX_PAYLOAD_LENGTH) throw new IllegalArgumentException(); if (frameNumber < 0) throw new IOException(); if (writeTag) writeTag(); if (writeStreamHeader) writeStreamHeader(); FrameEncoder.encodeHeader(frameHeader, finalFrame, payloadLength, paddingLength); FrameEncoder.encodeNonce(frameNonce, frameNumber, true); try { cipher.init(true, frameKey, frameNonce); int encrypted = cipher.process(frameHeader, 0, FRAME_HEADER_PLAINTEXT_LENGTH, frameCiphertext, 0); if (encrypted != FRAME_HEADER_LENGTH) throw new RuntimeException(); } catch (GeneralSecurityException badCipher) { throw new RuntimeException(badCipher); } System.arraycopy(payload, 0, framePlaintext, 0, payloadLength); for (int i = 0; i < paddingLength; i++) framePlaintext[payloadLength + i] = 0; FrameEncoder.encodeNonce(frameNonce, frameNumber, false); try { cipher.init(true, frameKey, frameNonce); int encrypted = cipher.process(framePlaintext, 0, payloadLength + paddingLength, frameCiphertext, FRAME_HEADER_LENGTH); if (encrypted != payloadLength + paddingLength + MAC_LENGTH) throw new RuntimeException(); } catch (GeneralSecurityException badCipher) { throw new RuntimeException(badCipher); } out.write(frameCiphertext, 0, FRAME_HEADER_LENGTH + payloadLength + paddingLength + MAC_LENGTH); frameNumber++; } StreamEncrypterImpl(OutputStream out, AuthenticatedCipher cipher,
			long streamNumber, @Nullable byte[] tag, byte[] streamHeaderNonce,
			SecretKey streamHeaderKey, SecretKey frameKey); @Override void writeFrame(byte[] payload, int payloadLength,
			int paddingLength, boolean finalFrame); @Override void flush();  }