/** * Create second message in SMP exchange. Input is Bob's secret value. Information from earlier * steps in the exchange is taken from Bob's state. Output is a serialized mpi array whose * elements correspond to the following: [0] = g2b, Bob's half of DH exchange to determine g2 [1] * = c2, [2] = d2, Bob's ZK proof of knowledge of g2b exponent [3] = g3b, Bob's half of DH * exchange to determine g3 [4] = c3, [5] = d3, Bob's ZK proof of knowledge of g3b exponent [6] = * pb, [7] = qb, Bob's halves of the (Pa/Pb) and (Qa/Qb) values [8] = cp, [9] = d5, [10] = d6, * Bob's ZK proof that pb, qb formed correctly * * @throws OTRException */ public static byte[] step2b(SMState bstate, byte[] secret, Provider prov) throws OTRException { /* Convert the given secret to the proper form and store it */ // Util.checkBytes("secret", secret); MPI secret_mpi = new MPI(secret); bstate.secret = secret_mpi; MPI[] msg2 = new MPI[11]; msg2[0] = prov.powm(bstate.g1, bstate.x2, new MPI(MODULUS_S)); MPI[] res = proofKnowLog(bstate.g1, bstate.x2, 3, prov); msg2[1] = res[0]; msg2[2] = res[1]; msg2[3] = prov.powm(bstate.g1, bstate.x3, new MPI(MODULUS_S)); res = proofKnowLog(bstate.g1, bstate.x3, 4, prov); msg2[4] = res[0]; msg2[5] = res[1]; /* Calculate P and Q values for Bob */ MPI r = randomExponent(prov); // MPI r = new MPI(SM.GENERATOR_S); bstate.p = prov.powm(bstate.g3, r, new MPI(MODULUS_S)); // Util.checkBytes("Pb", bstate.p.getValue()); msg2[6] = bstate.p; MPI qb1 = prov.powm(bstate.g1, r, new MPI(MODULUS_S)); // Util.checkBytes("Qb1", qb1.getValue()); MPI qb2 = prov.powm(bstate.g2, bstate.secret, new MPI(MODULUS_S)); // Util.checkBytes("Qb2", qb2.getValue()); // Util.checkBytes("g2", bstate.g2.getValue()); // Util.checkBytes("secret", bstate.secret.getValue()); bstate.q = prov.mulm(qb1, qb2, new MPI(MODULUS_S)); // Util.checkBytes("Qb", bstate.q.getValue()); msg2[7] = bstate.q; res = proofEqualCoords(bstate, r, 5, prov); msg2[8] = res[0]; msg2[9] = res[1]; msg2[10] = res[2]; /* Convert to serialized form */ return serializeMPIArray(msg2); }
/** * Create third message in SMP exchange. Input is a message generated by otrl_sm_step2b. Output is * a serialized mpi array whose elements correspond to the following: [0] = pa, [1] = qa, Alice's * halves of the (Pa/Pb) and (Qa/Qb) values [2] = cp, [3] = d5, [4] = d6, Alice's ZK proof that * pa, qa formed correctly [5] = ra, calculated as (Qa/Qb)^x3 where x3 is the exponent used in g3a * [6] = cr, [7] = d7, Alice's ZK proof that ra is formed correctly * * @throws OTRException */ public static byte[] step3(SMState astate, byte[] input, Provider prov) throws OTRException { /* Read from input to find the mpis */ astate.smProgState = PROG_CHEATED; MPI[] msg2 = unserializeMPIArray(input); if (checkGroupElem(msg2[0], prov) || checkGroupElem(msg2[3], prov) || checkGroupElem(msg2[6], prov) || checkGroupElem(msg2[7], prov) || checkExpon(msg2[2], prov) || checkExpon(msg2[5], prov) || checkExpon(msg2[9], prov) || checkExpon(msg2[10], prov)) { throw new OTRException("Invalid Parameter"); } MPI[] msg3 = new MPI[8]; /* Store Bob's g3a value for later in the protocol */ astate.g3o = msg2[3]; /* Verify Bob's knowledge of discreet log proofs */ if (checkKnowLog(msg2[1], msg2[2], astate.g1, msg2[0], 3, prov) != 0 || checkKnowLog(msg2[4], msg2[5], astate.g1, msg2[3], 4, prov) != 0) { throw new OTRException("Proof checking failed"); } /* Combine the two halves from Bob and Alice and determine g2 and g3 */ astate.g2 = prov.powm(msg2[0], astate.x2, new MPI(MODULUS_S)); // Util.checkBytes("g2a", astate.g2.getValue()); astate.g3 = prov.powm(msg2[3], astate.x3, new MPI(MODULUS_S)); // Util.checkBytes("g3a", astate.g3.getValue()); /* Verify Bob's coordinate equality proof */ if (checkEqualCoords(msg2[8], msg2[9], msg2[10], msg2[6], msg2[7], astate, 5, prov) != 0) throw new OTRException("Invalid Parameter"); /* Calculate P and Q values for Alice */ MPI r = randomExponent(prov); // MPI r = new MPI(SM.GENERATOR_S); astate.p = prov.powm(astate.g3, r, new MPI(MODULUS_S)); // Util.checkBytes("Pa", astate.p.getValue()); msg3[0] = astate.p; MPI qa1 = prov.powm(astate.g1, r, new MPI(MODULUS_S)); // Util.checkBytes("Qa1", qa1.getValue()); MPI qa2 = prov.powm(astate.g2, astate.secret, new MPI(MODULUS_S)); // Util.checkBytes("Qa2", qa2.getValue()); // Util.checkBytes("g2", astate.g2.getValue()); // Util.checkBytes("secret", astate.secret.getValue()); astate.q = prov.mulm(qa1, qa2, new MPI(MODULUS_S)); msg3[1] = astate.q; // Util.checkBytes("Qa", astate.q.getValue()); MPI[] res = proofEqualCoords(astate, r, 6, prov); msg3[2] = res[0]; msg3[3] = res[1]; msg3[4] = res[2]; /* Calculate Ra and proof */ MPI inv = prov.invm(msg2[6], new MPI(MODULUS_S)); astate.pab = prov.mulm(astate.p, inv, new MPI(MODULUS_S)); inv = prov.invm(msg2[7], new MPI(MODULUS_S)); astate.qab = prov.mulm(astate.q, inv, new MPI(MODULUS_S)); msg3[5] = prov.powm(astate.qab, astate.x3, new MPI(MODULUS_S)); res = proofEqualLogs(astate, 7, prov); msg3[6] = res[0]; msg3[7] = res[1]; byte[] output = serializeMPIArray(msg3); astate.smProgState = PROG_OK; return output; }