383 строки
16 KiB
Plaintext
383 строки
16 KiB
Plaintext
Off-the-Record Messaging Library and Toolkit
|
|
v4.1.1, 9 Mar 2016
|
|
|
|
This is a library and toolkit which implements Off-the-Record (OTR) Messaging.
|
|
|
|
OTR allows you to have private conversations over IM by providing:
|
|
- Encryption
|
|
- No one else can read your instant messages.
|
|
- Authentication
|
|
- You are assured the correspondent is who you think it is.
|
|
- Deniability
|
|
- The messages you send do _not_ have digital signatures that are
|
|
checkable by a third party. Anyone can forge messages after a
|
|
conversation to make them look like they came from you. However,
|
|
_during_ a conversation, your correspondent is assured the messages
|
|
he sees are authentic and unmodified.
|
|
- Perfect forward secrecy
|
|
- If you lose control of your private keys, no previous conversation
|
|
is compromised.
|
|
|
|
For more information on Off-the-Record Messaging, see
|
|
https://otr.cypherpunks.ca/
|
|
|
|
LIBRARY USAGE
|
|
|
|
1. Initialization
|
|
|
|
Before you call any other libotr routine, you need to initialize the
|
|
library. The easiest way to do that is to include proto.h, and use the
|
|
macro:
|
|
|
|
OTRL_INIT;
|
|
|
|
somewhere early in your program. This should be called only once.
|
|
|
|
You will also need an OtrlUserState. An OtrlUserState encapsulates the
|
|
list of known fingerprints and the list of private keys, so it should be
|
|
"one per user". Many OTR-enabled programs (such as IM clients) only have a
|
|
single user, so for them, you can just create a single one, and use it
|
|
throughout. Create an OtrlUserState as follows:
|
|
|
|
userstate = otrl_userstate_create();
|
|
|
|
If you need to free an OtrlUserState:
|
|
|
|
otrl_userstate_free(userstate);
|
|
|
|
To read stored private keys:
|
|
|
|
otrl_privkey_read(userstate, privkeyfilename);
|
|
|
|
To read stored instance tags:
|
|
|
|
otrl_instag_read(userstate, instagfilename);
|
|
|
|
To read stored fingerprints:
|
|
|
|
otrl_privkey_read_fingerprints(userstate, fingerprintfilename,
|
|
add_app_info, add_app_info_data);
|
|
|
|
add_app_info is a function that will be called in the event that a new
|
|
ConnContext is created. It will be passed the add_app_info_data that
|
|
you supplied, as well as a pointer to the new ConnContext. You can use
|
|
this to add application-specific information to the ConnContext using
|
|
the "context->app" field, for example. If you don't need to do this,
|
|
you can pass NULL for the last two arguments of
|
|
otrl_privkey_read_fingerprints.
|
|
|
|
2. Setting up the UI functions
|
|
|
|
You need to let the library know how to do any UI it might require
|
|
(error messages, confirming new fingerprints, etc.). To this end, you
|
|
need to define a number of UI functions, and collect them in a
|
|
OtrlMessageAppOps struct.
|
|
|
|
The first parameter of every UI function is "void *opdata". This is a
|
|
pointer you pass to the library, and it will pass back (opaquely) to the
|
|
UI functions when it calls them. You can use this to keep track of
|
|
state or any other information.
|
|
|
|
You will need to include proto.h and message.h, and you can find a list
|
|
of the UI functions in message.h.
|
|
|
|
3. Sending messages
|
|
|
|
When you have a message you're about to send, you'll need to know four
|
|
things: you account name, the protocol id, the name of the recipient,
|
|
their instance tag, and the message.
|
|
|
|
OTR protocol version 3 introduces the notion of "instance tags." A
|
|
client may be logged into the same account multiple times from different
|
|
locations. An instance tag is intended to differentiate these clients.
|
|
When sending a message, you may also specify a particular instance tag,
|
|
or use meta instance tags like OTRL_INSTAG_MOST_SECURE.
|
|
|
|
The protocol id is just a unique string that is used to distinguish
|
|
the user foo on AIM from the user foo on MSN, etc. It can be anything
|
|
you like, so long as you're consistent, but if you've got nothing better
|
|
to use, you may as well use the ids from gaim. (Programs that use the
|
|
same protocol ids can share fingerprint and private key files.) The
|
|
gaim protocol id for AIM/ICQ is "prpl-oscar".
|
|
|
|
Note that a name does not uniquely identify a user (as shown by the
|
|
"foo" example above). Even if you know both the name and the protocol,
|
|
it may not identify the user, since there may be multiple "foo" users on
|
|
IRC, on different servers. But the *three* items (your account name,
|
|
protocol id, their name) _must_ uniquely identify a user, so your
|
|
account name needs to include any network identifier, such as a server
|
|
name. Examples would be "foo@irc.freenode.net" or "foo@jabber.org".
|
|
Protocols such as AIM that do not have separate networks can just use
|
|
"foo", of course.
|
|
|
|
To encrypt the message (if necessary; the library keeps track of which
|
|
users you have secure connections to, so you should *always* call this
|
|
next function), simply do this:
|
|
|
|
gcry_error_t err;
|
|
char *newmessage = NULL;
|
|
|
|
err = otrl_message_sending(userstate, &ui_ops, opdata, accountname,
|
|
protocolid, recipient_name, instag, message, tlvs,
|
|
&newmessage, fragPolicy, contextp, add_app_info,
|
|
add_app_info_data);
|
|
|
|
add_app_info and add_app_info_data are as above, and may be NULL.
|
|
|
|
tlvs should usually be NULL. If it's not, then it points to a chain of
|
|
OtrlTLVs which represent machine-readable data to send along with this
|
|
message.
|
|
|
|
If contextp is not NULL, it will be set to the context that was used
|
|
for sending the message.
|
|
|
|
If err is non-zero, then the library tried to encrypt the message,
|
|
but for some reason failed. DO NOT send the message in the clear in
|
|
that case.
|
|
|
|
If newmessage gets set by the call to something non-NULL, then you
|
|
should replace your message with the contents of newmessage, and
|
|
send that instead.
|
|
|
|
Once the message is encrypted, it may still be too large to send over
|
|
the network in a single piece. To check the maximum message size and
|
|
break your message into fragments if necessary, do this:
|
|
|
|
gcry_error_t err;
|
|
char *extrafragment = NULL;
|
|
|
|
err = otrl_message_fragment_and_send(&ui_ops, opdata, context,
|
|
message, fragmentPolicy, extrafragment);
|
|
|
|
fragmentPolicy determines which, if any, fragments to return instead
|
|
of sending them immediately. For example, you may wish to send all
|
|
fragments except the last one, which is handled differently. Valid
|
|
policies may be found in proto.h.
|
|
|
|
If err returns a nonzero value from fragment_and_send, the application
|
|
tried to break your message into fragments but failed for some reason.
|
|
You may still attempt to send the original message, but it might be
|
|
rejected if it too large.
|
|
|
|
When you're done with newmessage, you must call
|
|
|
|
otrl_message_free(newmessage)
|
|
|
|
4. Receiving messages
|
|
|
|
Receiving messages is similarly straightforward. Again, you need to
|
|
know four things: your account name, the protocol id, the sender's name,
|
|
and the message.
|
|
|
|
int ignore_message;
|
|
char *newmessage = NULL;
|
|
|
|
ignore_message = otrl_message_receiving(userstate, &ui_ops, opdata,
|
|
accountname, protocolid, sender_name, message, &newmessage,
|
|
&tlvs, contextp, add_app_info, add_app_info_data);
|
|
|
|
add_app_info and add_app_info_data are as above, and may be NULL.
|
|
|
|
If contextp is not NULL, it will be set to the context that was used
|
|
for receiving the message.
|
|
|
|
If otrl_message_receiving returns 1, then the message you received was
|
|
an internal protocol message, and no message should be delivered to the
|
|
user.
|
|
|
|
If it returns 0, then check if newmessage was set to non-NULL. If so,
|
|
replace the received message with the contents of newmessage, and
|
|
deliver that to the user instead. You must call
|
|
otrl_message_free(newmessage) when you're done with it.
|
|
|
|
If otrl_message_receiving returns 0 and newmessage is NULL, then this
|
|
was an ordinary, non-OTR message, which should just be delivered to the
|
|
user without modification.
|
|
|
|
If tlvs is set to non-NULL, then there is machine-readable data that was
|
|
sent along with this message. Call otrl_tlv_free(tlvs) when you're done
|
|
dealing with it (or ignoring it).
|
|
|
|
5. Socialist Millionaires' Protocol
|
|
|
|
The Socialist Millionaires' Protocol (SMP) is a way to detect
|
|
eavesdropping and man-in-the-middle attacks without requiring users to
|
|
work with fingerprints. This feature was added to OTR starting in
|
|
version 3.1.0. To learn how to modify your application to use SMP, read
|
|
the UPGRADING file.
|
|
|
|
TOOLKIT
|
|
|
|
Along with the library, this package comes with the OTR Messaging
|
|
Toolkit. This toolkit is useful for analyzing and/or forging OTR
|
|
messages. Why do we offer this? Primarily, to make absolutely sure
|
|
that transcripts of OTR conversations are really easy to forge after the
|
|
fact. [Note that *during* an OTR conversation, messages can't be forged
|
|
without real-time access to the secret keys on the participants'
|
|
computers, and in that case, all security has already been lost.]
|
|
Easily forgeable transcripts help us provide the "Deniability" property:
|
|
if someone claims you said something over OTR, they'll have no proof, as
|
|
anyone at all can modify a transcript to make it say whatever they like,
|
|
and still have all the verification come out correctly.
|
|
|
|
Here are the six programs in the toolkit:
|
|
|
|
- otr_parse
|
|
- Parse OTR messages given on stdin, showing the values of all the
|
|
fields in OTR protocol messages.
|
|
|
|
- otr_sesskeys our_privkey their_pubkey
|
|
- Shows our public key, the session id, two AES and two MAC keys
|
|
derived from the given Diffie-Hellman keys (one private, one public).
|
|
|
|
- otr_mackey aes_enc_key
|
|
- Shows the MAC key derived from the given AES key.
|
|
|
|
- otr_readforge aes_enc_key [newmsg]
|
|
- Decrypts an OTR Data message using the given AES key, and displays
|
|
the message, if the key was correct.
|
|
- If newmsg is given, replace the message with that one, encrypt
|
|
and MAC it properly, and output the resulting OTR Data Message.
|
|
This works even if the given key was not correct for the original
|
|
message, so as to enable complete forgeries.
|
|
|
|
- otr_modify mackey old_text new_text offset
|
|
- Even if you can't read the data because you don't know either
|
|
the AES key or the Diffie-Hellman private key, but you can make a
|
|
good guess that the substring "old_text" appears at the given
|
|
offset in the message, replace the old_text with the new_text
|
|
(which must be of the same length), recalculate the MAC with the
|
|
given mackey, and output the resulting Data message.
|
|
- Note that, even if you don't know any text in an existing message,
|
|
you can still forge messages of your choice using the otr_readforge
|
|
command, above.
|
|
|
|
- otr_remac mackey sender_instance receiver_instance flags keyid keyid
|
|
pubkey counter encdata revealed_mackeys
|
|
- Make a new OTR Data Message, with the given pieces (note that the
|
|
data part is already encrypted). MAC it with the given mackey.
|
|
|
|
NOTES
|
|
|
|
Please send your bug reports, comments, suggestions, patches, etc. to us
|
|
at the contact address below.
|
|
|
|
In otrl_message_sending, specifying an instance tag allows you to send a
|
|
message to a particular session of a buddy who is logged in multiple times
|
|
with an otr-enabled client. The OTRL_INSTAG_RECENT_RECEIVED meta-instance
|
|
relies on the time that libotr processed the most recent message. Meta-
|
|
instance tags resolve to actual instance tags before a message is sent. An
|
|
instant messaging network may not agree on which session of the remote party is
|
|
the most recent, e.g., due to underlying network race conditions. If the
|
|
behaviour of an instant messaging network is to only deliver to the most recent,
|
|
and libotr and the network disagree on which session is the most recent, the
|
|
other party will not process the given message. That is, the instant messaging
|
|
network will deliver the message to the session whose actual instance tag does
|
|
not match the addressed instance tag. Also note that OTRL_INSTAG_BEST also
|
|
prefers more recent instance tags in the case of multiple instances with the
|
|
same "best" status (most secure). In this case, the most recent has a
|
|
resolution of one second.
|
|
|
|
If otrl_message_sending is called with an original_msg that contains the text
|
|
"?OTR?", this is a signal to initiate or refresh an OTR session. There is
|
|
currently no way to indicate if this text was actually typed in by a user and
|
|
part of a conversation (e.g., someone communicating instructions on how to
|
|
refresh OTR). In the future, we may allow a policy to specify whether "?OTR?"
|
|
is a signal to start OTR, or just an ordinary message for encrypted and
|
|
unencrypted conversations.
|
|
|
|
MAILING LISTS
|
|
|
|
There are three mailing lists pertaining to Off-the-Record Messaging:
|
|
|
|
otr-announce:
|
|
https://lists.cypherpunks.ca/mailman/listinfo/otr-announce/
|
|
*** All users of OTR software should join this. *** It is used to
|
|
announce new versions of OTR software, and other important information.
|
|
|
|
otr-users:
|
|
https://lists.cypherpunks.ca/mailman/listinfo/otr-users/
|
|
Discussion of usage issues related to OTR Messaging software.
|
|
|
|
otr-dev:
|
|
https://lists.cypherpunks.ca/mailman/listinfo/otr-dev/
|
|
Discussion of OTR Messaging software development.
|
|
|
|
LICENSE
|
|
|
|
The Off-the-Record Messaging library (in the src directory) is
|
|
covered by the following (LGPL) license:
|
|
|
|
Off-the-Record Messaging library
|
|
Copyright (C) 2004-2016 Ian Goldberg, David Goulet, Rob Smits,
|
|
Chris Alexander, Willy Lew, Lisa Du,
|
|
Nikita Borisov
|
|
<otr@cypherpunks.ca>
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of version 2.1 of the GNU Lesser General
|
|
Public License as published by the Free Software Foundation.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
There is a copy of the GNU Lesser General Public License in the
|
|
COPYING.LIB file packaged with this library; if you cannot find it,
|
|
write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
Floor, Boston, MA 02110-1301 USA
|
|
|
|
The library comes with a test suite (in the tests directory), which is
|
|
covered by the following (GPL) license:
|
|
|
|
Copyright (C) 2014 Julien Voisin <julien.voisin@dustri.org>,
|
|
David Goulet <dgoulet@ev0ke.net>
|
|
|
|
This program is free software; you can redistribute it and/or modify it
|
|
under the terms of the GNU General Public License, version 2 only, as
|
|
published by the Free Software Foundation.
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
more details.
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
this program; if not, write to the Free Software Foundation, Inc., 51
|
|
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
The Off-the-Record Messaging Toolkit (in the toolkit directory) is covered
|
|
by the following (GPL) license:
|
|
|
|
Off-the-Record Messaging Toolkit
|
|
Copyright (C) 2004-2014 Ian Goldberg, David Goulet, Rob Smits,
|
|
Chris Alexander, Nikita Borisov
|
|
<otr@cypherpunks.ca>
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of version 2 of the GNU General Public License as
|
|
published by the Free Software Foundation.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
There is a copy of the GNU General Public License in the COPYING file
|
|
packaged with this toolkit; if you cannot find it, write to the Free
|
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
02110-1301 USA
|
|
|
|
CONTACT
|
|
|
|
To report problems, comments, suggestions, patches, etc., you can email
|
|
the authors:
|
|
|
|
Ian Goldberg, David Goulet, Rob Smits, Chris Alexander, Lisa Du,
|
|
Nikita Borisov
|
|
<otr@cypherpunks.ca>
|
|
|
|
For more information on Off-the-Record Messaging, visit
|
|
https://otr.cypherpunks.ca/
|