/**
   * Verify: Alice's IP + Alice's port + Bob's IP + Bob's port + Alice's new relay tag + Bob's
   * signed on time Caller must synch on this.
   */
  private boolean verifySessionCreated() {
    byte signed[] =
        new byte
            [256
                + 256 // X + Y
                + _aliceIP.length
                + 2
                + _bobIP.length
                + 2
                + 4 // sent relay tag
                + 4 // signed on time
            ];

    int off = 0;
    System.arraycopy(_sentX, 0, signed, off, _sentX.length);
    off += _sentX.length;
    System.arraycopy(_receivedY, 0, signed, off, _receivedY.length);
    off += _receivedY.length;
    System.arraycopy(_aliceIP, 0, signed, off, _aliceIP.length);
    off += _aliceIP.length;
    DataHelper.toLong(signed, off, 2, _alicePort);
    off += 2;
    System.arraycopy(_bobIP, 0, signed, off, _bobIP.length);
    off += _bobIP.length;
    DataHelper.toLong(signed, off, 2, _bobPort);
    off += 2;
    DataHelper.toLong(signed, off, 4, _receivedRelayTag);
    off += 4;
    DataHelper.toLong(signed, off, 4, _receivedSignedOnTime);
    boolean valid =
        _context
            .dsa()
            .verifySignature(_receivedSignature, signed, _remotePeer.getSigningPublicKey());
    if (_log.shouldLog(Log.DEBUG) || (_log.shouldLog(Log.WARN) && !valid)) {
      StringBuilder buf = new StringBuilder(128);
      buf.append("Signed sessionCreated:");
      buf.append(" Alice: ").append(Addresses.toString(_aliceIP, _alicePort));
      buf.append(" Bob: ").append(Addresses.toString(_bobIP, _bobPort));
      buf.append(" RelayTag: ").append(_receivedRelayTag);
      buf.append(" SignedOn: ").append(_receivedSignedOnTime);
      buf.append(" signature: ").append(Base64.encode(_receivedSignature.getData()));
      if (valid) _log.debug(buf.toString());
      else if (_log.shouldLog(Log.WARN)) _log.warn("INVALID: " + buf.toString());
    }
    return valid;
  }
  /**
   * Let's sign everything so we can fragment properly.
   *
   * <p>Note that while a SessionConfirmed could in theory be fragmented, in practice a
   * RouterIdentity is 387 bytes and a single fragment is 512 bytes max, so it will never be
   * fragmented.
   */
  public synchronized void prepareSessionConfirmed() {
    if (_sentSignedOnTime > 0) return;
    byte signed[] =
        new byte
            [256
                + 256 // X + Y
                + _aliceIP.length
                + 2
                + _bobIP.length
                + 2
                + 4 // Alice's relay key
                + 4 // signed on time
            ];

    _sentSignedOnTime = _context.clock().now() / 1000;

    int off = 0;
    System.arraycopy(_sentX, 0, signed, off, _sentX.length);
    off += _sentX.length;
    System.arraycopy(_receivedY, 0, signed, off, _receivedY.length);
    off += _receivedY.length;
    System.arraycopy(_aliceIP, 0, signed, off, _aliceIP.length);
    off += _aliceIP.length;
    DataHelper.toLong(signed, off, 2, _alicePort);
    off += 2;
    System.arraycopy(_bobIP, 0, signed, off, _bobIP.length);
    off += _bobIP.length;
    DataHelper.toLong(signed, off, 2, _bobPort);
    off += 2;
    DataHelper.toLong(signed, off, 4, _receivedRelayTag);
    off += 4;
    DataHelper.toLong(signed, off, 4, _sentSignedOnTime);
    // BUG - if SigningPrivateKey is null, _sentSignature will be null, leading to NPE later
    // should we throw something from here?
    _sentSignature = _context.dsa().sign(signed, _context.keyManager().getSigningPrivateKey());
  }