UNPKG

otr4

Version:

OTR Messaging Protocol [native libotr4.x.x]

286 lines (237 loc) 7.12 kB
var otr = require("../index.js"); var document = document || {}; var FORCE_SMP = false; var SEND_BAD_SECRET = false; var SMP_TEST_DONE = false; var SMP_TEST_IN_PROGRESS = false; var SMP_TEST_PASSED = false; var SMP_TEST_PERFORMED = false; var SYMKEY_TEST_DONE = false; var SYMKEY_TEST_IN_PROGRESS = false; var SYMKEY_TEST_PASSED = false; var SYMKEY_TEST_VALUES = {}; if (typeof process !== "undefined") { process.argv.forEach(function (arg) { if (arg == "--force-smp") FORCE_SMP = true; if (arg == "--bad-secret") SEND_BAD_SECRET = true; }); } var debug = debug || function debug() { console.log([].join.call(arguments, " ")); }; debug("== loaded libotr version:", otr.version()); var alice_settings = { accountname: "alice@telechat.org", protocol: "telechat" }; var bob_settings = { accountname: "bob@telechat.org", protocol: "telechat" }; ///setting up Alice's side of the connection var alice = new otr.User({ keys: "./alice.keys", fingerprints: "./alice.fp", instags: "./alice.instags" }); alice.name = "Alice"; var alice_account = alice.account(alice_settings.accountname, alice_settings.protocol); var BOB = alice_account.contact("BOB"); dumpFingerprints(BOB.fingerprints()); var session_a = BOB.openSession({ policy: otr.POLICY.DEFAULT, secret: 's3cr37', MTU: 3000 }); ///setting up Bob's side of the connection var bob = new otr.User({ keys: "./bob.keys", fingerprints: "./bob.fp", instags: "./bob.instags" }); bob.name = "Bob"; var bob_account = bob.account(bob_settings.accountname, bob_settings.protocol); console.log("---"); var ALICE = bob_account.contact("ALICE"); dumpFingerprints(ALICE.fingerprints()); var session_b = ALICE.openSession({ policy: otr.POLICY.DEFAULT, secret: 's3cr37', MTU: 3000 }); //simulate a network connection between two parties session_a.on("inject_message", function (msg) { debug("ALICE:", msg); session_b.recv(msg); }); session_b.on("inject_message", function (msg) { debug("BOB:", msg); session_a.recv(msg); }); session_a.on("create_privkey", function (a, p) { debug("Alice doesn't have a key.. run keygen.js to generate keys for this example."); process.exit(); }); session_b.on("create_privkey", function (a, p) { debug("Bob doesn't have a key.. run keygen.js to generate keys for this example."); process.exit(); }); session_a.on("create_instag", function (a, p) { alice_account.generateInstag(); }); session_b.on("create_instag", function (a, p) { bob_account.generateInstag(); }); session_a.on("gone_secure", function () { debug("[Alice] Encrypted Connection Established - Gone Secure."); }); session_b.on("gone_secure", function () { debug("[Bob] Encrypted Connection Established - Gone Secure."); }); //output incoming messages to console function print_message(name, msg, encrypted) { if (encrypted) { debug(name + '[ENCRYPTED]:', msg); } else { debug(name + '[PLAINTEXT]:', msg); } } session_a.on("msg_event", function (e) { debug(JSON.stringify(e)); }); session_b.on("msg_event", function (e) { debug(JSON.stringify(e)); }); //alice received message from bob session_a.on("message", function (msg, encrypted) { print_message('<<', msg, encrypted); session_b.end(); }); //bob received message from alice session_b.on("message", function (msg, encrypted) { print_message('>>', msg, encrypted); this.send("got your message '" + msg + "'"); }); session_a.on("disconnect", function () { debug("Session was closed remotely"); exit_test("", true); }); session_b.on("received_symkey", function (use, usedata, key) { SYMKEY_TEST_IN_PROGRESS = false; SYMKEY_TEST_DONE = true; debug("Received Symmetric Key"); debug(" use:", use); debug("usedata:", ab2str(usedata)); debug(" key:", ab2str(key)); SYMKEY_TEST_PASSED = ( (SYMKEY_TEST_VALUES.use === use) && (SYMKEY_TEST_VALUES.usedata === ab2str(usedata)) && (SYMKEY_TEST_VALUES.key === ab2str(key)) ); }); session_a.on("write_fingerprints", function () { alice.writeFingerprints(); dumpFingerprints(BOB.fingerprints()); }); session_b.on("write_fingerprints", function () { bob.writeFingerprints(); dumpFingerprints(ALICE.fingerprints()); }); function end_smp_test() { debug("SMP TEST DONE"); SMP_TEST_PASSED = session_a.isAuthenticated(); SMP_TEST_DONE = true; SMP_TEST_IN_PROGRESS = false; } session_b.on("smp", function (type) { if (type !== "request") return; debug("Received SMP Request."); if (!SEND_BAD_SECRET) { debug("responding with correct secret"); this.smpRespond('s3cr37'); } else { debug("responding with wrong secret"); this.smpRespond("!!wrong_secret!!"); } }); session_a.on("smp", end_smp_test); console.log("sending ?OTR?"); //start OTR session_a.send("?OTR?"); //or session_a.start(); //session_b.send("?OTR?"); //don't start OTR simultaneously on both ends! var loop = setInterval(function () { debug("_"); //wait for secure session to be established if (!session_a.isEncrypted() && !session_b.isEncrypted()) return; //dont do anything if tests are in progress if (SMP_TEST_IN_PROGRESS || SYMKEY_TEST_IN_PROGRESS) { debug("entered loop, tests in progress..."); return; } //smp test if (session_a.isEncrypted() && !SMP_TEST_DONE) { if (!session_a.isAuthenticated() || FORCE_SMP) { SMP_TEST_IN_PROGRESS = true; SMP_TEST_PERFORMED = true; debug("Starting SMP Test"); session_a.smpStart(); } else { debug("Skipping SMP Test buddies previously authenticated"); SMP_TEST_DONE = true; } return; } //start symkey test (after smp test is done) if (!SYMKEY_TEST_DONE && SMP_TEST_DONE) { SYMKEY_TEST_IN_PROGRESS = true; debug("Starting Extra Symmertic Key Test"); SYMKEY_TEST_VALUES = { 'use': 1000, 'usedata': 'ftp://website.net/files.tgz' }; session_a.extraSymKey(SYMKEY_TEST_VALUES.use, SYMKEY_TEST_VALUES.usedata, function (key) { SYMKEY_TEST_VALUES.key = ab2str(key); }); return; } //send an encrypted message if (session_a.isEncrypted() && SYMKEY_TEST_DONE && SMP_TEST_DONE) { debug("sending message"); session_a.send("test encrypted message"); session_a.recv("this is an unencrypted message, during a secure session!"); //should raise a msg_event UNENCRYPTED return; } exit_test("Tests did not complete...", false); }, 500); function exit_test(msg, TEST_PASSED) { debug(msg); if (loop) clearInterval(loop); dumpConnContext(session_a, "Alice's ConnContext:"); dumpConnContext(session_b, "Bob's ConnContext:"); if (SMP_TEST_PERFORMED) { debug("SMP TEST PERFORMED"); debug("Trusted connection after SMP? ", SMP_TEST_PASSED); } if (SYMKEY_TEST_DONE) debug("SYMKEY TEST", SYMKEY_TEST_PASSED ? "PASSED" : "FAILED"); if (TEST_PASSED) { debug("== TEST PASSED ==\n"); } else { debug("== TEST FAILED ==\n"); } process.exit(); } function dumpConnContext(session, msg) { console.log(session.context); } function dumpFingerprints(fingerprints) { console.log("dumping fingerprints..."); fingerprints.forEach(function (fp) { console.log(fp); debug(fp.fingerprint()); debug(fp.trust()); }); } function ab2str(buf) { return String.fromCharCode.apply(null, new Uint16Array(buf)); }