int JPAKE_STEP1_generate(JPAKE_STEP1 *send, JPAKE_CTX *ctx)
    {
    genrand(ctx);
    generate_step_part(&send->p1, ctx->xa, ctx->p.g, ctx);
    generate_step_part(&send->p2, ctx->xb, ctx->p.g, ctx);

    return 1;
    }
int YAK_STEP1_generate(YAK_STEP1 *send, YAK_CTX *ctx)
    {
    genrand(ctx);
    generate_step_part(&send->p1, ctx->xa, ctx->p.g, ctx);
    generate_step_part(&send->p2, ctx->xb, ctx->p.g, ctx);

    return 1;
    }
int JPAKE_STEP2_generate(JPAKE_STEP2 *send, JPAKE_CTX *ctx)
    {
    BIGNUM *t1 = BN_new();
    BIGNUM *t2 = BN_new();

   /*
    * X = g^{(xa + xc + xd) * xb * s}
    * t1 = g^xa
    */
    BN_mod_exp(t1, ctx->p.g, ctx->xa, ctx->p.p, ctx->ctx);
   /* t2 = t1 * g^{xc} = g^{xa} * g^{xc} = g^{xa + xc} */
    BN_mod_mul(t2, t1, ctx->p.gxc, ctx->p.p, ctx->ctx);
   /* t1 = t2 * g^{xd} = g^{xa + xc + xd} */
    BN_mod_mul(t1, t2, ctx->p.gxd, ctx->p.p, ctx->ctx);
   /* t2 = xb * s */
    BN_mod_mul(t2, ctx->xb, ctx->secret, ctx->p.q, ctx->ctx);

   /*
    * ZKP(xb * s)
    * XXX: this is kinda funky, because we're using
    *
    * g' = g^{xa + xc + xd}
    *
    * as the generator, which means X is g'^{xb * s}
    * X = t1^{t2} = t1^{xb * s} = g^{(xa + xc + xd) * xb * s}
    */
    generate_step_part(send, t2, t1, ctx);

   /* cleanup */
    BN_free(t1);
    BN_free(t2);

    return 1;
    }