protected OutgoingMessage computeSharedSecret(final IncomingMessage in)
      throws KeyAgreementException {
    N = in.readMPI();
    g = in.readMPI();
    final BigInteger s = in.readMPI();
    final BigInteger B = in.readMPI();

    if (B.mod(N).equals(BigInteger.ZERO)) {
      throw new KeyAgreementException("illegal value for B");
    }

    // generate an ephemeral keypair
    final SRPKeyPairGenerator kpg = new SRPKeyPairGenerator();
    final Map attributes = new HashMap();
    if (rnd != null) {
      attributes.put(SRPKeyPairGenerator.SOURCE_OF_RANDOMNESS, rnd);
    }
    attributes.put(SRPKeyPairGenerator.SHARED_MODULUS, N);
    attributes.put(SRPKeyPairGenerator.GENERATOR, g);
    kpg.setup(attributes);
    userKeyPair = kpg.generate();

    final BigInteger A = ((SRPPublicKey) userKeyPair.getPublic()).getY();
    final BigInteger u = uValue(A, B); // u = H(A | B)

    if (u.mod(N).equals(BigInteger.ZERO)) {
      throw new KeyAgreementException("u is zero");
    }

    final BigInteger x;
    try {
      x = new BigInteger(1, srp.computeX(Util.trim(s), I, p));
    } catch (Exception e) {
      throw new KeyAgreementException("computeSharedSecret()", e);
    }

    // compute S = (B - 3g^x) ^ (a + ux)
    final BigInteger a = ((SRPPrivateKey) userKeyPair.getPrivate()).getX();
    final BigInteger S = B.subtract(THREE.multiply(g.modPow(x, N))).modPow(a.add(u.multiply(x)), N);

    K = S;

    final OutgoingMessage result = new OutgoingMessage();
    result.writeMPI(A);

    complete = true;
    return result;
  }
  private OutgoingMessage sendIdentity(final IncomingMessage in) throws KeyAgreementException {
    final OutgoingMessage result = new OutgoingMessage();
    result.writeString(I);

    return result;
  }