public byte[] decryptBytes(byte[] combined) throws IOException, InvalidMessageException {
    try {
      byte[][] parts =
          Util.split(combined, PublicKey.KEY_SIZE, combined.length - PublicKey.KEY_SIZE);
      PublicKey theirPublicKey = new PublicKey(parts[0], 0);

      ECPrivateKey ourPrivateKey = asymmetricMasterSecret.getPrivateKey();
      byte[] secret = Curve.calculateAgreement(theirPublicKey.getKey(), ourPrivateKey);
      MasterCipher masterCipher = getMasterCipherForSecret(secret);

      return masterCipher.decryptBytes(parts[1]);
    } catch (InvalidKeyException e) {
      throw new InvalidMessageException(e);
    }
  }
  public byte[] encryptBytes(byte[] body) {
    try {
      ECPublicKey theirPublic = asymmetricMasterSecret.getDjbPublicKey();
      ECKeyPair ourKeyPair = Curve.generateKeyPair();
      byte[] secret = Curve.calculateAgreement(theirPublic, ourKeyPair.getPrivateKey());
      MasterCipher masterCipher = getMasterCipherForSecret(secret);
      byte[] encryptedBodyBytes = masterCipher.encryptBytes(body);

      PublicKey ourPublicKey = new PublicKey(31337, ourKeyPair.getPublicKey());
      byte[] publicKeyBytes = ourPublicKey.serialize();

      return Util.combine(publicKeyBytes, encryptedBodyBytes);
    } catch (InvalidKeyException e) {
      throw new AssertionError(e);
    }
  }