Commit 9add3e3d authored by JC Brand's avatar JC Brand

Add support for Socialist's Millionaire Protocol authentication

parent 6d237d3f
...@@ -281,17 +281,16 @@ ...@@ -281,17 +281,16 @@
this.ChatBox = Backbone.Model.extend({ this.ChatBox = Backbone.Model.extend({
initialize: function () { initialize: function () {
if (this.get('box_id') !== 'controlbox') { if (this.get('box_id') !== 'controlbox') {
if (_.contains([UNVERIFIED, VERIFIED], this.get('otr_status'))) {
this.initiateOTR();
}
this.messages = new converse.Messages(); this.messages = new converse.Messages();
this.messages.localStorage = new Backbone.LocalStorage( this.messages.localStorage = new Backbone.LocalStorage(
hex_sha1('converse.messages'+this.get('jid'))); hex_sha1('converse.messages'+this.get('jid')));
this.set({ this.set({
'user_id' : Strophe.getNodeFromJid(this.get('jid')), 'user_id' : Strophe.getNodeFromJid(this.get('jid')),
'box_id' : hex_sha1(this.get('jid')), 'box_id' : hex_sha1(this.get('jid')),
'fullname' : this.get('fullname'), 'otr_status': this.get('otr_status') || UNENCRYPTED
'url': this.get('url'),
'image_type': this.get('image_type'),
'image': this.get('image'),
'otr_status': UNENCRYPTED
}); });
} }
}, },
...@@ -305,7 +304,7 @@ ...@@ -305,7 +304,7 @@
if (savedKey) { if (savedKey) {
decrypted = cipher.decrypt(crypto.algo.AES, savedKey, pass); decrypted = cipher.decrypt(crypto.algo.AES, savedKey, pass);
myKey = otr.DSA.parsePrivate(decrypted.toString(crypto.enc.Latin1)); myKey = otr.DSA.parsePrivate(decrypted.toString(crypto.enc.Latin1));
if (cipher.decrypt(crypto.algo.AES, passCheck, 'pass').toString(crypto.enc.Latin1) === 'match') { if (cipher.decrypt(crypto.algo.AES, passCheck, pass).toString(crypto.enc.Latin1) === 'match') {
// Verified that the user's password is still the same // Verified that the user's password is still the same
return myKey; return myKey;
} }
...@@ -319,29 +318,51 @@ ...@@ -319,29 +318,51 @@
return myKey; return myKey;
}, },
initiateOTR: function () { updateOTRStatus: function (state) {
this.otr = new otr.OTR({
fragment_size: 140,
send_interval: 200,
priv: this.getPrivateKey(),
debug: this.debug
});
this.otr.on('status', $.proxy(function (state) {
switch (state) { switch (state) {
case otr.OTR.CONST.STATUS_AKE_SUCCESS: case otr.OTR.CONST.STATUS_AKE_SUCCESS:
if (this.otr.msgstate === otr.OTR.CONST.MSGSTATE_ENCRYPTED) { if (this.otr.msgstate === otr.OTR.CONST.MSGSTATE_ENCRYPTED) {
this.set('otr_status', UNVERIFIED); this.save({'otr_status': UNVERIFIED});
} }
break; break;
case otr.OTR.CONST.STATUS_END_OTR: case otr.OTR.CONST.STATUS_END_OTR:
if (this.otr.msgstate === otr.OTR.CONST.MSGSTATE_FINISHED) { if (this.otr.msgstate === otr.OTR.CONST.MSGSTATE_FINISHED) {
this.set('otr_status', FINISHED); this.save({'otr_status': FINISHED});
} else if (this.otr.msgstate === otr.OTR.CONST.MSGSTATE_PLAINTEXT) { } else if (this.otr.msgstate === otr.OTR.CONST.MSGSTATE_PLAINTEXT) {
this.set('otr_status', UNENCRYPTED); this.save({'otr_status': UNENCRYPTED});
} }
break; break;
} }
}, this)); },
onSMP: function (type, data) {
// Event handler for SMP (Socialist's Millionaire Protocol)
// used by OTR (off-the-record).
switch (type) {
case 'question':
this.otr.smpSecret(prompt(data));
break;
case 'trust':
if (this.otr.trust === true) {
this.save({'otr_status': VERIFIED});
} else {
this.save({'otr_status': UNVERIFIED});
}
break;
default:
throw new Error('Unknown type.');
}
},
initiateOTR: function () {
this.otr = new otr.OTR({
fragment_size: 140,
send_interval: 200,
priv: this.getPrivateKey(),
debug: this.debug
});
this.otr.on('status', $.proxy(this.updateOTRStatus, this));
this.otr.on('smp', $.proxy(this.onSMP, this));
this.otr.on('ui', $.proxy(function (msg) { this.otr.on('ui', $.proxy(function (msg) {
this.trigger('showReceivedOTRMessage', msg); this.trigger('showReceivedOTRMessage', msg);
...@@ -409,10 +430,16 @@ ...@@ -409,10 +430,16 @@
this.trigger('buddyStartsOTR'); this.trigger('buddyStartsOTR');
} }
} else if (text.match(/^\?OTR\:/)) { } else if (text.match(/^\?OTR\:/)) {
if (this.otr) {
// This is an encrypted message, but we don't // This is an encrypted message, but we don't
// appear to have an encrypted session. Send to OTR // appear to have an encrypted session. Send to OTR
// anyway, they'll complain. // anyway, they'll complain.
this.otr.receiveMsg(text); this.otr.receiveMsg(text);
} else {
this.showHelpMessages(
[__('We received an encrypted message, but you are not set up for encryption yet.')],
'error');
}
} else { } else {
// Normal unencrypted message. // Normal unencrypted message.
this.createMessage(message); this.createMessage(message);
...@@ -480,7 +507,8 @@ ...@@ -480,7 +507,8 @@
'<li><a class="end-otr" href="#">'+__('End encrypted conversation')+'</a></li>'+ '<li><a class="end-otr" href="#">'+__('End encrypted conversation')+'</a></li>'+
'{[ } ]}' + '{[ } ]}' +
'{[ if (otr_status === "'+UNVERIFIED+'") { ]}' + '{[ if (otr_status === "'+UNVERIFIED+'") { ]}' +
'<li><a class="auth-otr" href="#">'+__('Authenticate buddy')+'</a></li>'+ '<li><a class="auth-otr" data-scheme="fingerprint" href="#">'+__('Verify with fingerprints')+'</a></li>'+
'<li><a class="auth-otr" data-scheme="smp" href="#">'+__('Verify with SMP')+'</a></li>'+
'{[ } ]}' + '{[ } ]}' +
'<li><a href="http://www.cypherpunks.ca/otr/help/3.2.0/levels.php" target="_blank">'+__("What\'s this?")+'</a></li>'+ '<li><a href="http://www.cypherpunks.ca/otr/help/3.2.0/levels.php" target="_blank">'+__("What\'s this?")+'</a></li>'+
'</ul>'+ '</ul>'+
...@@ -788,7 +816,10 @@ ...@@ -788,7 +816,10 @@
}, },
authOTR: function (ev) { authOTR: function (ev) {
var result = confirm(__( var scheme = $(ev.target).data().scheme;
var result, question, answer;
if (scheme === 'fingerprint') {
result = confirm(__(
'Here are the fingerprints, please confirm them with %1$s, outside of this chat.\n\n'+ 'Here are the fingerprints, please confirm them with %1$s, outside of this chat.\n\n'+
'Fingerprint for you, %2$s: %3$s\n\n'+ 'Fingerprint for you, %2$s: %3$s\n\n'+
'Fingerprint for %1$s: %4$s\n\n'+ 'Fingerprint for %1$s: %4$s\n\n'+
...@@ -800,9 +831,16 @@ ...@@ -800,9 +831,16 @@
] ]
)); ));
if (result === true) { if (result === true) {
this.model.set('otr_status', VERIFIED); this.model.save({'otr_status': VERIFIED});
} else {
this.model.save({'otr_status': UNVERIFIED});
}
} else if (scheme === 'smp') {
question = prompt(__('What is your security question?'));
answer = prompt(__('What is the answer to the security question?'));
this.model.otr.smpSecret(answer, question);
} else { } else {
this.model.set('otr_status', UNVERIFIED); this.showHelpMessages([__('Invalid authentication scheme provided')], 'error');
} }
}, },
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment