private OutgoingMessage sendParameters(final IncomingMessage in) throws KeyAgreementException {
    final String I = in.readString();

    // get s and v for user identified by I
    // ----------------------------------------------------------------------
    final Map credentials;
    try {
      final Map userID = new HashMap();
      userID.put(Registry.SASL_USERNAME, I);
      userID.put(SRPRegistry.MD_NAME_FIELD, srp.getAlgorithm());
      credentials = passwordDB.lookup(userID);
    } catch (IOException x) {
      throw new KeyAgreementException("computeSharedSecret()", x);
    }

    final BigInteger s =
        new BigInteger(1, Util.fromBase64((String) credentials.get(SRPRegistry.SALT_FIELD)));
    final BigInteger v =
        new BigInteger(
            1, Util.fromBase64((String) credentials.get(SRPRegistry.USER_VERIFIER_FIELD)));

    final Map configuration;
    try {
      final String mode = (String) credentials.get(SRPRegistry.CONFIG_NDX_FIELD);
      configuration = passwordDB.getConfiguration(mode);
    } catch (IOException x) {
      throw new KeyAgreementException("computeSharedSecret()", x);
    }

    N = new BigInteger(1, Util.fromBase64((String) configuration.get(SRPRegistry.SHARED_MODULUS)));
    g = new BigInteger(1, Util.fromBase64((String) configuration.get(SRPRegistry.FIELD_GENERATOR)));
    // ----------------------------------------------------------------------

    // 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);
    attributes.put(SRPKeyPairGenerator.USER_VERIFIER, v);
    kpg.setup(attributes);
    hostKeyPair = kpg.generate();

    final BigInteger B = ((SRPPublicKey) hostKeyPair.getPublic()).getY();

    final OutgoingMessage result = new OutgoingMessage();
    result.writeMPI(N);
    result.writeMPI(g);
    result.writeMPI(s);
    result.writeMPI(B);

    return result;
  }
  protected OutgoingMessage computeSharedSecret(final IncomingMessage in)
      throws KeyAgreementException {
    final BigInteger A = in.readMPI();

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

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

    // compute S = (Av^u) ^ b
    final BigInteger b = ((SRPPrivateKey) hostKeyPair.getPrivate()).getX();
    final BigInteger v = ((SRPPrivateKey) hostKeyPair.getPrivate()).getV();
    final BigInteger S = A.multiply(v.modPow(u, N)).modPow(b, N);

    K = S;

    complete = true;
    return null;
  }