https://github.com/arlolra/otr
Off-the-Record Messaging Protocol implemented in JavaScript
https://github.com/arlolra/otr
Last synced: about 2 months ago
JSON representation
Off-the-Record Messaging Protocol implemented in JavaScript
- Host: GitHub
- URL: https://github.com/arlolra/otr
- Owner: arlolra
- License: mpl-2.0
- Created: 2012-07-08T22:59:50.000Z (almost 13 years ago)
- Default Branch: master
- Last Pushed: 2020-12-01T12:28:33.000Z (over 4 years ago)
- Last Synced: 2024-10-29T19:41:46.393Z (7 months ago)
- Language: JavaScript
- Homepage: https://arlolra.github.io/otr/
- Size: 1.06 MB
- Stars: 457
- Watchers: 25
- Forks: 61
- Open Issues: 10
-
Metadata Files:
- Readme: readme.md
- Changelog: changelog.md
- Contributing: contributing.md
- License: license
Awesome Lists containing this project
- awesome-github-repos - arlolra/otr - Off-the-Record Messaging Protocol implemented in JavaScript (JavaScript)
README
[](https://travis-ci.org/arlolra/otr)
[Off-the Record Messaging Protocol](http://www.cypherpunks.ca/otr/) in JavaScript
==================================================### Warning
This library hasn't been properly vetted by security researchers. Do not use
in life and death situations!### Install
Include the build files on the page,
Here's an [example](https://github.com/arlolra/otr/blob/master/test/browser.html) use in the browser.
Although this is a client library, it can be used [on the server](https://github.com/arlolra/otr/blob/master/test/xmpp.js).
npm install otr
And then,
var DSA = require('otr').DSA
var OTR = require('otr').OTR### Build
The contents of `build/` are the result of calling `make build` and are only
updated with releases. Please submit patches against `lib/` and `vendor/`.### Release
The normal flow for making a release is as follows,
make test
// bump the version numbers in package.json / bower.json
make build
git changelog // cleanup the changelog
git commit -m "bump version"
git tag -a vX.X.X -m "version X.X.X"
git push origin master
git push --tags
npm publish
// update github releases and pages### Usage
**Initial setup**: Compute your long-lived key beforehand. Currently this is
expensive and can take several seconds.// precompute your DSA key
var myKey = new DSA()For each user you're communicating with, instantiate an OTR object.
// provide options
var options = {
fragment_size: 140
, send_interval: 200
, priv: myKey
}var buddy = new OTR(options)
buddy.on('ui', function (msg, encrypted, meta) {
console.log("message to display to the user: " + msg)
// encrypted === true, if the received msg was encrypted
console.log("(optional) with receiveMsg attached meta data: " + meta)
})buddy.on('io', function (msg, meta) {
console.log("message to send to buddy: " + msg)
console.log("(optional) with sendMsg attached meta data: " + meta)
})buddy.on('error', function (err, severity) {
if (severity === 'error') // either 'error' or 'warn'
console.error("error occurred: " + err)
})**New message from buddy received**: Pass the received message to the `receiveMsg`
method.var rcvmsg = "Message from buddy."
var meta = "optional some meta data, like delay"
buddy.receiveMsg(rcvmsg, meta)**Send a message to buddy**: Pass the message to the `sendMsg` method.
var newmsg = "Message to userA."
var meta = "optional some meta data, like message id"
buddy.sendMsg(newmsg, meta)**Going encrypted**: Initially, messages are sent in plaintext. To manually
initiate the authenticated key exchange.buddy.sendQueryMsg()
Alternatively, one can set the policy `REQUIRE_ENCRYPTION` and send a plaintext
message. This will store the message, initiate the authentication and then,
upon success, send it out.buddy.REQUIRE_ENCRYPTION = true
buddy.sendMsg('My plaintext message to be encrypted.')Another policy, `SEND_WHITESPACE_TAG`, will append tags to plaintext messages,
indicating a willingness to speak OTR. If the recipient in turn has set the
policy `WHITESPACE_START_AKE`, the AKE will be initiated.**Close private connection**: To end an encrypted communication session,
buddy.endOtr(function() {
// calls back when the 'disconnect' message has been sent
})will return the message state to plaintext and notify the correspondent.
**Options**: A dictionary of the current options accepted by the OTR constructor.
var options = {
// long-lived private key
priv: new DSA(),// turn on some debuggin logs
debug: false,// fragment the message in case of char limits
fragment_size: 140,// ms delay between sending fragmented msgs, avoid rate limits
send_interval: 200}
### Status
A listener can be attached for status changes. These are non-standard codes,
specific to this OTR library, indicating various things like the AKE success.buddy.on('status', function (state) {
switch (state) {
case OTR.CONST.STATUS_AKE_SUCCESS:
// sucessfully ake'd with buddy
// check if buddy.msgstate === OTR.CONST.MSGSTATE_ENCRYPTED
break
case OTR.CONST.STATUS_END_OTR:
// if buddy.msgstate === OTR.CONST.MSGSTATE_FINISHED
// inform the user that his correspondent has closed his end
// of the private connection and the user should do the same
break
}
})### Policies
To be set on a per-correspondent basis. The defaults are as follows:
// Allow version 2 or 3 of the OTR protocol to be used.
ALLOW_V2 = true
ALLOW_V3 = true// Refuse to send unencrypted messages.
REQUIRE_ENCRYPTION = false// Advertise your support of OTR using the whitespace tag.
SEND_WHITESPACE_TAG = false// Start the OTR AKE when you receive a whitespace tag.
WHITESPACE_START_AKE = false// Start the OTR AKE when you receive an OTR Error Message.
ERROR_START_AKE = false### Instance Tags
These are intended to be persistent and can be precomputed.
var myTag = OTR.makeInstanceTag()
var options = { instance_tag: myTag }var buddy = new OTR(options)
### Fingerprints
OTR public key fingerprints can be obtained as follows:
// assume you've gone through the ake with buddy
var buddy = new OTR({ priv: myKey })
// buddy.msgstate === OTR.CONST.MSGSTATE_ENCRYPTED// for my key, either one of the following
myKey.fingerprint()
// or,
buddy.priv.fingerprint()// for their key
buddy.their_priv_pk.fingerprint()### Socialist Millionaire Protocol
At any time after establishing encryption, either party can initiate SMP to
detect impersonation or man-in-the-middle attacks. A shared secret,
exchanged through an out-of-band channel prior to starting the conversation,
is required.var secret = "ghostbusters"
buddy.smpSecret(secret)A question can be supplied, as a reminder of the shared secret.
var question = "who are you going to call?"
buddy.smpSecret(secret, question)If you plan on using SMP, as opposed to just allowing fingerprints for
verification, provide on optional callback when initiating OTR,
otherwise a no-opt is fired.var buddy = new OTR()
buddy.on('smp', function (type, data, act) {
switch (type) {
case 'question':
// call(data) some function with question?
// return the user supplied data to
// userA.smpSecret(secret)
break
case 'trust':
// smp completed
// check data (true|false) and update ui accordingly
// act ("asked"|"answered") provides info one who initiated the smp
break
case 'abort':
// smp was aborted. notify the user or update ui
default:
throw new Error('Unknown type.')
}
})Both users should run the SMP to establish trust. Further, it should be run each time a partner presents a fresh long-lived key.
### Private Keys
To export a private, long-lived key:
var myKey = new DSA()
var string = myKey.packPrivate() // returns a Base64 encoded stringIt can then be imported as follows,
string = "AAAAAACA4COdKHpU/np9F8EDdnGiJJmc89p ... I9BzTkQduFA7ovXAMY="
myKey = DSA.parsePrivate(string)Importing the (somewhat) standard libotr s-expression format works as well,
// in node.js
var fs = require('fs')
string = fs.readFileSync("~/.purple/otr.private_key", 'utf8')// leaving out the terminal backslashes needed for multiline strings in js
string = "(privkeys
(account
(name "[email protected]")
(protocol prpl-jabber)
(private-key
(dsa
(p #00FC07 ... 2AEFD07A2081#)
(q #ASD5FF ... LKJDF898DK12#)
(g #535E3E ... 1E3BC1FC6F26#)
(y #0AC867 ... 8969009B6ECF#)
(x #14D034 ... F72D79043216#)
)
)
)
)"myKey = DSA.parsePrivate(string, true)
### Extra Symmetric Key
In version 3 of the protocol, an extra symmetric key is derived during the AKE. This may be used for secure communication over a different channel (e.g., file transfer, voice chat).
var filename = "test.zip"
var buddy = new OTR()
buddy.sendFile(filename)
buddy.on('file', function (type, key, filename) {
// type === 'send'
// key should be used to encrypt filename
// and sent through a different channel
})On the other end,
var friend = new OTR()
friend.on('file', function (type, key, filename) {
// type === 'receive'
// decrypt filename with key, once received
})### WebWorkers
Some support exists for calling computationally expensive work off the main
thread. However, some feedback on these APIs would be appreciated.// generate a DSA key in a web worker
DSA.createInWebWorker(null, function (key) {
var buddy = new OTR({
priv: key,
// setting `smw` to a truthy value will perform the socialist
// millionaire protocol in a webworker.
smw: {}
})
})WebWorkers don't have access to `window.crypto.getRandomValues()`, so they will
need to include Salsa20.
### Links
Spec:
- http://www.cypherpunks.ca/otr/Protocol-v3-4.0.0.html
- http://www.cypherpunks.ca/otr/Protocol-v2-3.1.0.html
- See: `specs/`Using:
- [crypto-js](http://code.google.com/p/crypto-js/)
- [bigint.js](http://leemon.com/crypto/BigInt.html)
- [salsa20.js](https://gist.github.com/dchest/4582374)
- [eventemitter.js](https://github.com/Wolfy87/EventEmitter)### In The Wild
A sampling of projects that use this library:
- [Cryptocat](https://github.com/cryptocat/cryptocat)
- [Yabasta](https://github.com/jonkri/yabasta)
- [Diaspora](https://github.com/sualko/diaspora)
- [Converse.js](https://github.com/jcbrand/converse.js)
- [WebRTCCopy](https://github.com/erbbysam/webRTCCopy)
- [OTRon](https://github.com/osnr/otron)
- [ojsxc (owncloud)](https://github.com/sualko/ojsxc)
- [sjsxc (SOGo)](https://github.com/sualko/sjsxc)
- [LoquiIM](https://loqui.im/)
- [Salut à Toi](http://salut-a-toi.org/) ([Python wrapper][0] for Pyjamas)
- [HackTunnel](https://github.com/devhq-io/hacktunnel)[0]: http://repos.goffi.org/libervia/file/tip/src/browser/sat_browser/otrjs_wrapper.py
### Donate
Bitcoins: 1BWLnnig89fpn8hCcASd2B1YbfK6j1vtX3
### License
MPL v2.0