Protocol::OTR::Channel - Off-the-Record communication Channel
version 0.05
use Protocol::OTR qw( :constants ); my $otr = Protocol::OTR->new( { privkeys_file => "otr.private_key", contacts_file => "otr.fingerprints", instance_tags_file => "otr.instance_tags", } ); # find or create account my $alice = $otr->account('alice@domain', 'prpl-jabber'); # find or create contact known by $alice my $bob = $alice->contact('bob@domain'); # create secure channel to Bob my $channel = $bob->channel( { policy => ..., max_message_size => ..., on_write => sub { ... }, on_read => sub { ... }, on_gone_secure => sub { ... }, on_gone_insecure => sub { ... }, on_still_secure => sub { ... }, on_unverified_fingerprint => sub { ... }, on_symkey => sub { ... }, on_timer => sub { ... }, on_smp => sub { ... }, on_error => sub { ... }, on_event => sub { ... }, on_smp_event => sub { ... }, on_before_encrypt => sub { ... }, on_after_decrypt => sub { ... }, on_is_contact_logged_in => sub { ... }, } );
Protocol::OTR::Channel represents the OTR communication channel.
my $account = $channel->account();
Returns channel's Protocol::OTR::Account object.
my $contact = $channel->contact();
Returns channel's Protocol::OTR::Contact object.
$channel->init();
Send OTR default query message to initialize secure session.
'<b>'. $channel->account->name .'</b> has requested an ' .'<a href="http://otr.cypherpunks.ca/">Off-the-Record ' .'private conversation</a>. However, you do not have a plugin ' .'to support that.\nSee <a href="http://otr.cypherpunks.ca/">' .'http://otr.cypherpunks.ca/</a> for more information.'
$channel->refresh();
Refreshes current authentication keys.
$channel->finish();
Finish all sessions within the channel.
print $channel->status();
Returns current status of the channel, which is one of:
Unused
Not private
Unverified
Private
Finished
my $symkey = $channel->create_symkey( $use, $use_for );
Returns symmetric key agreed with other party. $use is an integer (1 is reserved for future support of file transfers), while $use_for is a message how the symmetric key will be used.
$use
$use_for
Generate key for symmetric encryption:
# Alice my $crypt_cipher = "Blowfish"; my $crypt_key = $channel->create_symkey( 2, $crypt_cipher ); my $crypt = Crypt::CBC->new( -key => $crypt_key, -cipher => $crypt_cipher, ); # Bob on_symkey => sub { my ($c, $symkey, $use, $use_for) = @_; my $crypt_cipher = $use_for; my $crypt_key = $symkey; my $crypt = Crypt::CBC->new( -key => $crypt_key, -cipher => $crypt_cipher, ); }
$channel->ping();
Call this function every so often, either as directed by the "on_timer" callback or every minute if the callback is not implemented.
See "on_timer" for more details.
$channel->smp_verify( $answer, [ $question ]);
Verify identity of the contact using Socialist Millionaires' Protocol (SMP). Contact is required to respond with the expected $answer, optional $question may be provided.
$answer
$question
sub display_smp_popup { my ($channel, $question) = @_; my $answer = get_answer($question); $channel->smp_respond( $answer ); }
Respond to SMP identity verification question with expected secret/answer.
$channel->smp_abort();
Abort the SMP when error occured.
$channel->write( $message );
Send message over the secure channel. The encrypted message ready for sending will be passed to "on_write" callback to transport.
$channel->read( $input );
Handle a message just received from the network. It is safe to pass all received messages to this routine. Decrypted messages will be passed to "on_read" callback.
my @sessions = $channel->sessions();
Returns a list of session IDs (instags) that were used by the contact in this channel.
my $current_session_id = $channel->current_session();
Returns currently used by the contact session ID (instag) in this channel.
$channel->select_session( $id );
Selects provided session id as the current session. Returns false if session id is not known.
One of special session selectors (exported via ":instags" in Protocol::OTR) can be also used.
my $channel = $contact->channel( { policy => ..., max_message_size => ..., on_write => sub { ... }, on_read => sub { ... }, on_gone_secure => sub { ... }, on_gone_insecure => sub { ... }, on_still_secure => sub { ... }, on_unverified_fingerprint => sub { ... }, on_symkey => sub { ... }, on_timer => sub { ... }, on_smp => sub { ... }, on_error => sub { ... }, on_event => sub { ... }, on_smp_event => sub { ... }, on_before_encrypt => sub { ... }, on_after_decrypt => sub { ... }, on_is_contact_logged_in => sub { ... }, } );
my $channel = $contact->channel( { policy => POLICY_OPPORTUNISTIC, ... } );
Select the default OTR policy, see ":policies" in Protocol::OTR for details.
my $channel = $contact->channel( { max_message_size => 10 * 1024, ... } );
Define the maximum message size handled by protocol. Messages larger then this value will be split and delivered separetely.
Following defaults are used based on the protocol:
prpl-msn: 1409
prpl-icq: 2346
prpl-aim: 2343
prpl-yahoo: 799
prpl-gg: 1999
prpl-irc: 417
prpl-oscar: 2343
my $channel = $contact->channel( { on_write => sub { my ($c, $message) = @_; $transporter->deliver( $c->contact->name, $message ); }, ... } );
Receives encrypted message to be sent. This callback is required.
$c is a reference to the current channel.
$c
$message is the encrypted message to be sent.
$message
$channel->read( $raw_message ); my $channel = $contact->channel( { on_read => sub { my ($c, $message) = @_; print "From: ", $c->contact->name, "\n"; print "To: ", $c->account->name, "\n"; print "Message:\n", $message, "\n"; }, ... } );
Receives decrypted messages. This callback is required.
$message is the received message.
Note: internal protocol messages are not received by this callback.
my $channel = $contact->channel( { on_gone_secure => sub { my ($c) = @_; print "Channel between ", $c->contact->name , " and ", $c->account->name, " is now secure\n"; my $fp = $c->contact->active_fingerprint; unless ( $fp->is_verified ) { print "Fingerprint ", $fp->hash, " is not verified\n"; } }, ... } );
Called when the channel has entered secure state.
my $channel = $contact->channel( { on_gone_insecure => sub { my ($c) = @_; print "Channel between ", $c->contact->name , " and ", $c->account->name, " is not secure anymore\n"; }, ... } );
Called when the channel has left secure state.
my $channel = $contact->channel( { on_still_secure => sub { my ($c) = @_; print "Channel between ", $c->contact->name , " and ", $c->account->name, " is still secure\n"; }, ... } );
Called when the channel has entered secure state using already known D-H keys.
my $channel = $contact->channel( { on_unverified_fingerprint => sub { my ($c, $fingerprint_hash, $seen_before) = @_; print "Unverified fingerprint ", $fingerprint_hash, " from ", $c->contact->name , " to ", $c->account->name, " is ", ( $seen_before ? "unrecognised" : "not authenticated" ), "\n"; }, ... } );
Called when new fingerprint has been received.
$fingerprint_hash is the human readable hash of the fingerprint.
$fingerprint_hash
$seen_before is a boolean indicating if the fingerprint was seen before.
$seen_before
my $channel = $contact->channel( { on_symkey => sub { my ($c, $symkey, $use, $use_for) = @_; print "Received symmetric key for ", $use_for, " (", $use,") ", " from ", $c->contact->name , " to ", $c->account->name, ":\n", unpack("H*", $symkey), "\n"; encrypt_file( $symkey ); }, ... } );
Called when received symmetric key from our contact. Example use is as password to archive file.
$symkey is the symmetric key.
$symkey
$use is the numeric code of the requested use (use numbers > 1).
$use_for is the use specific data.
my $channel = $contact->channel( { on_timer => sub { my ($c, $interval) = @_; undef $ping_timer; if ( $interval > 0 ) { $ping_timer = AE::timer 0, $interval, sub { $c->ping(); }; } }, ... } );
When called, turn off any existing periodic timer.
Additionally, if interval > 0, set a new periodic timer to go off every $interval seconds. When that timer fires, you must call "ping" method.
$interval
The timing does not have to be exact; this timer is used to provide forward secrecy by cleaning up stale private state that may otherwise stick around in memory. Note that the on_timer callback may be invoked from "ping" itself, possibly to indicate that $interval == 0 (that is, that there's no more periodic work to be done at this time).
on_timer
If you set this callback is not provided, then you must ensure that your application calls "ping" every minute. The advantage of implementing the on_timer callback is that the timer can be turned on by the library only when it's needed.
It is not a problem (except for a minor performance hit) to call "ping" more often than requested, whether on_timer is implemented or not.
If you fail to implement the on_timer callback, and also fail to periodically call "ping", then you open your users to a possible forward secrecy violation: an attacker that compromises the user's computer may be able to decrypt a handful of long-past messages (the first messages of an OTR conversation).
$interval is described above.
my $channel = $contact->channel( { on_smp => sub { my ($c, $question) = @_; print "SMP verification in channel between ", $c->contact->name, " and ", $c->account->name, "\n"; display_smp_popup( $c, $question ); }, ... } );
Called when received SMP verification. Use to retrieve the answer.
$question is an optional question/hint.
my $channel = $contact->channel( { on_error => sub { my ($c, $error_code) = @_; print "Handling error in channel between ", $c->contact->name, " and ", $c->account->name, "\n"; handle_error( $c, $error_code ); }, ... } );
Called when error occured in the channel. See ":error_codes" in Protocol::OTR for possible errors.
$error_code is the numeric code of error.
$error_code
my $channel = $contact->channel( { on_event => sub { my ($c, $event_code, $message) = @_; print "Handling event in channel between ", $c->contact->name, " and ", $c->account->name, "\n"; handle_event( $c, $event_code, $message ); }, ... } );
Called when event occured in the channel. See ":event_codes" in Protocol::OTR for possible events.
$event_code is the numeric code of event.
$event_code
$message is set only for following events: MSGEVENT_SETUP_ERROR, MSGEVENT_RCVDMSG_GENERAL_ERR, MSGEVENT_RCVDMSG_UNENCRYPTED.
MSGEVENT_SETUP_ERROR
MSGEVENT_RCVDMSG_GENERAL_ERR
MSGEVENT_RCVDMSG_UNENCRYPTED
my $channel = $contact->channel( { on_smp_event => sub { my ($c, $smp_event_code, $progress) = @_; print "Handling SMP event (progress at ", $progress, "%) ", "in channel between ", $c->contact->name, " and ", $c->account->name, "\n"; handle_smp_event( $c, $smp_event_code, $progress ); }, ... } );
Called when SMP event occured in the channel. See ":smp_event_codes" in Protocol::OTR for possible events.
$smp_event_code is the numeric code of SMP event.
$smp_event_code
$progress indicates the overall progress of SMP verification process.
$progress
my $channel = $contact->channel( { on_before_encrypt => sub { my ($c, $message) = @_; return $translator->write( $message ); }, ... } );
Called immediately before a data message is encrypted.
$message is the message to be sent.
my $channel = $contact->channel( { on_after_decrypt => sub { my ($c, $message) = @_; return $translator->read( $message ); }, ... } );
Called immediately after a data message is decrypted.
my $channel = $contact->channel( { on_is_contact_logged_in => sub { my ($c) = @_; return 1; }, ... } );
Report whether you think the given user is online. Return 1 if yes, 0 if no, -1 if unkown.
If you return 1, messages such as heartbeats or other notifications may be sent to the user, which could result in "not logged in" errors if you're wrong.
Protocol::OTR
Protocol::OTR::Account
Protocol::OTR::Contact
Protocol::OTR::Fingerprint
Protocol::OTR::Channel
Alex J. G. Burzyński <ajgb@cpan.org>
This software is copyright (c) 2014 by Alex J. G. Burzyński <ajgb@cpan.org>.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
To install Protocol::OTR, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Protocol::OTR
CPAN shell
perl -MCPAN -e shell install Protocol::OTR
For more information on module installation, please visit the detailed CPAN module installation guide.