changeset 522:0de69fec24e9

browser and server sides: OTR plugin, first draft
author souliane <souliane@mailoo.org>
date Tue, 02 Sep 2014 21:28:42 +0200
parents 69bffcf37ce3
children 5add182e7dd5
files src/browser/otr.min.js src/browser/otr.min.js_README src/browser/sat_browser/otrjs_wrapper.py src/browser/sat_browser/plugin_sec_otr.py src/server/server.py
diffstat 5 files changed, 690 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/browser/otr.min.js	Tue Sep 02 21:28:42 2014 +0200
@@ -0,0 +1,19 @@
+(function(a,b){if(typeof define==="function"&&define.amd){define(b.bind(a,a.crypto||a.msCrypto))}else{if(typeof module!=="undefined"&&module.exports){module.exports=b(require("crypto"))}else{a.BigInt=b(a.crypto||a.msCrypto)}}}(this,function(v){var x=26;var E=1<<x;var aw=E-1;var bd="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_=!@#$%^&*()[]{}|;:,.<>/?`~ \\'\"+-";var o=a0(1,1,1);var W=new Array(0);var aT=W;var n=W;var k=W;var j=W;var i=W;var h=W,g=W;var f=W;var e=W;var ar=W;var a2=W;var aR=W,F=W,R=W;var S=W,V=W,aG=W,aE=W,aC=W,aA=W;var ah=W,ag=W,af=W,aL=W,P=W,O=W,aH=W;var N=W,al=W,aa=W,aQ=W,ao=W,bf=W,U=W,a8=W;var ae=W,H=W,X=W,ad=W,ab=W,M=W,L=W,aW=W;var a7=W;function ba(bl){var T,bj,bk,t;bj=new Array(bl);for(T=0;T<bl;T++){bj[T]=0}bj[0]=2;bk=0;for(;bj[bk]<bl;){for(T=bj[bk]*bj[bk];T<bl;T+=bj[bk]){bj[T]=1}bk++;bj[bk]=bj[bk-1]+1;for(;bj[bk]<bl&&bj[bj[bk]];bj[bk]++){}}t=new Array(bk);for(T=0;T<bk;T++){t[T]=bj[T]}return t}function l(T,t){if(aR.length!=T.length){aR=K(T);F=K(T);R=K(T)}y(R,t);return aN(T,R)}function aN(T,t){var bl,bk,bj,bm;if(aR.length!=T.length){aR=K(T);F=K(T);R=K(T)}ax(R,t);ax(F,T);ax(aR,T);at(F,-1);at(aR,-1);if(aZ(F)){return 0}for(bj=0;F[bj]==0;bj++){}for(bl=1,bk=2;F[bj]%bk==0;bk*=2,bl++){}bm=bj*x+bl-1;if(bm){G(F,bm)}aS(R,F,T);if(!z(R,1)&&!Q(R,aR)){bk=1;while(bk<=bm-1&&!Q(R,aR)){aJ(R,T);if(z(R,1)){return 0}bk++}if(!Q(R,aR)){return 0}}return 1}function ay(t){var bj,bk,T;for(bj=t.length-1;(t[bj]==0)&&(bj>0);bj--){}for(bk=0,T=t[bj];T;(T>>=1),bk++){}bk+=x*bj;return bk}function aD(t,bj){var T=a0(0,(t.length>bj?t.length:bj)*x,0);ax(T,t);return T}function ak(T){var t=a0(0,T,0);aq(t,T);return a4(t,1)}function D(t){if(t>=600){return q(t,2)}if(t>=550){return q(t,4)}if(t>=500){return q(t,5)}if(t>=400){return q(t,6)}if(t>=350){return q(t,7)}if(t>=300){return q(t,9)}if(t>=250){return q(t,12)}if(t>=200){return q(t,15)}if(t>=150){return q(t,18)}if(t>=100){return q(t,27)}return q(t,40)}function q(bj,bm){var T,bk,t,bl;bl=30000;T=a0(0,bj,0);if(N.length==0){N=ba(30000)}if(a7.length!=T.length){a7=K(T)}for(;;){a1(T,bj,0);T[0]|=1;t=0;for(bk=0;(bk<N.length)&&(N[bk]<=bl);bk++){if(be(T,N[bk])==0&&!z(T,N[bk])){t=1;break}}for(bk=0;bk<bm&&!t;bk++){a1(a7,bj,0);while(!B(T,a7)){a1(a7,bj,0)}if(!aN(T,a7)){t=1}}if(!t){return T}}}function b(t,bj){var T=K(t);aB(T,bj);return a4(T,1)}function p(t,bj){var T=aD(t,t.length+1);at(T,bj);return a4(T,1)}function d(t,bj){var T=aD(t,t.length+bj.length);aY(T,bj);return a4(T,1)}function aP(t,bk,bj){var T=aD(t,bj.length);aS(T,a4(bk,2),a4(bj,2),0);return a4(T,1)}function a5(t,bj){var T=aD(t,(t.length>bj.length?t.length+1:bj.length+1));bc(T,bj);return a4(T,1)}function w(t,bj){var T=aD(t,(t.length>bj.length?t.length+1:bj.length+1));aI(T,bj);return a4(T,1)}function bg(t,bk){var T=aD(t,bk.length);var bj;bj=Z(T,bk);return bj?a4(T,1):null}function an(t,bk,bj){var T=aD(t,bj.length);aU(T,bk,bj);return a4(T,1)}function aq(bt,bm){var br,bu,bk,bl,bv,bn,t,T,bp,bq,bj,bo,bs;if(N.length==0){N=ba(30000)}if(al.length==0){al=new Array(512);for(bn=0;bn<512;bn++){al[bn]=Math.pow(2,bn/511-1)}}br=0.1;bk=20;bs=20;if(aQ.length!=bt.length){aQ=K(bt);ao=K(bt);a8=K(bt);H=K(bt);ab=K(bt);M=K(bt);L=K(bt);ad=K(bt);X=K(bt);aa=K(bt);bf=K(bt);U=K(bt);ae=K(bt);aW=K(bt)}if(bm<=bs){bl=(1<<((bm+2)>>1))-1;y(bt,0);for(bv=1;bv;){bv=0;bt[0]=1|(1<<(bm-1))|aV(bm);for(bn=1;(bn<N.length)&&((N[bn]&bl)==N[bn]);bn++){if(0==(bt[0]%N[bn])){bv=1;break}}}Y(bt);return}T=br*bm*bm;if(bm>2*bk){for(t=1;bm-bm*t<=bk;){t=al[aV(9)]}}else{t=0.5}bo=Math.floor(t*bm)+1;aq(U,bo);y(aQ,0);aQ[Math.floor((bm-2)/x)]|=(1<<((bm-2)%x));c(aQ,U,aa,bf);bq=ay(aa);for(;;){for(;;){a1(ao,bq,0);if(B(aa,ao)){break}}at(ao,1);aI(ao,aa);ax(X,U);aY(X,ao);m(X,2);at(X,1);ax(H,ao);m(H,2);for(bp=0,bn=0;(bn<N.length)&&(N[bn]<T);bn++){if(be(X,N[bn])==0&&!z(X,N[bn])){bp=1;break}}if(!bp){if(!l(X,2)){bp=1}}if(!bp){at(X,-3);for(bn=X.length-1;(X[bn]==0)&&(bn>0);bn--){}for(bj=0,bu=X[bn];bu;(bu>>=1),bj++){}bj+=x*bn;for(;;){a1(ae,bj,0);if(B(X,ae)){break}}at(X,3);at(ae,2);ax(ad,ae);ax(a8,X);at(a8,-1);aS(ad,a8,X);at(ad,-1);if(aZ(ad)){ax(ad,ae);aS(ad,H,X);at(ad,-1);ax(aW,X);ax(ab,ad);A(ab,X);if(z(ab,1)){ax(bt,aW);return}}}}}function aO(bk,bj){var T,t;T=Math.floor((bk-1)/x)+2;t=a0(0,0,T);a1(t,bk,bj);return t}function a1(t,bl,bk){var bj,T;for(bj=0;bj<t.length;bj++){t[bj]=0}T=Math.floor((bl-1)/x)+1;for(bj=0;bj<T;bj++){t[bj]=aV(x)}t[T-1]&=(2<<((bl-1)%x))-1;if(bk==1){t[T-1]|=(1<<((bl-1)%x))}}function ap(t,bk){var T,bj;T=K(t);bj=K(bk);A(T,bj);return T}function A(br,bq){var bp,bo,T,bn,bm,bl,t,bk,bj,bs;if(ar.length!=br.length){ar=K(br)}bj=1;while(bj){bj=0;for(bp=1;bp<bq.length;bp++){if(bq[bp]){bj=1;break}}if(!bj){break}for(bp=br.length;!br[bp]&&bp>=0;bp--){}bo=br[bp];T=bq[bp];bn=1;bm=0;bl=0;t=1;while((T+bl)&&(T+t)){bk=Math.floor((bo+bn)/(T+bl));bs=Math.floor((bo+bm)/(T+t));if(bk!=bs){break}W=bn-bk*bl;bn=bl;bl=W;W=bm-bk*t;bm=t;t=W;W=bo-bk*T;bo=T;T=W}if(bm){ax(ar,br);J(br,bq,bn,bm);J(bq,ar,t,bl)}else{aB(br,bq);ax(ar,br);ax(br,bq);ax(bq,ar)}}if(bq[0]==0){return}W=be(br,bq[0]);y(br,bq[0]);bq[0]=W;while(bq[0]){br[0]%=bq[0];W=br[0];br[0]=bq[0];bq[0]=W}}function Z(t,bj){var T=1+2*Math.max(t.length,bj.length);if(!(t[0]&1)&&!(bj[0]&1)){y(t,0);return 0}if(V.length!=T){V=new Array(T);S=new Array(T);aG=new Array(T);aE=new Array(T);aC=new Array(T);aA=new Array(T)}ax(V,t);ax(S,bj);y(aG,1);y(aE,0);y(aC,0);y(aA,1);for(;;){while(!(V[0]&1)){s(V);if(!(aG[0]&1)&&!(aE[0]&1)){s(aG);s(aE)}else{aI(aG,bj);s(aG);bc(aE,t);s(aE)}}while(!(S[0]&1)){s(S);if(!(aC[0]&1)&&!(aA[0]&1)){s(aC);s(aA)}else{aI(aC,bj);s(aC);bc(aA,t);s(aA)}}if(!B(S,V)){bc(V,S);bc(aG,aC);bc(aE,aA)}else{bc(S,V);bc(aC,aG);bc(aA,aE)}if(z(V,0)){while(r(aC)){aI(aC,bj)}ax(t,aC);if(!z(S,1)){y(t,0);return 0}return 1}}}function aX(bj,bm){var bk=1,T=0,bl;for(;;){if(bj==1){return bk}if(bj==0){return 0}T-=bk*Math.floor(bm/bj);bm%=bj;if(bm==1){return T}if(bm==0){return 0}bk-=T*Math.floor(bj/bm);bj%=bm}}function C(t,T){return aX(t,T)}function u(T,bn,bl,bj,t){var bm=0;var bk=Math.max(T.length,bn.length);if(V.length!=bk){V=new Array(bk);aG=new Array(bk);aE=new Array(bk);aC=new Array(bk);aA=new Array(bk)}while(!(T[0]&1)&&!(bn[0]&1)){s(T);s(bn);bm++}ax(V,T);ax(bl,bn);y(aG,1);y(aE,0);y(aC,0);y(aA,1);for(;;){while(!(V[0]&1)){s(V);if(!(aG[0]&1)&&!(aE[0]&1)){s(aG);s(aE)}else{aI(aG,bn);s(aG);bc(aE,T);s(aE)}}while(!(bl[0]&1)){s(bl);if(!(aC[0]&1)&&!(aA[0]&1)){s(aC);s(aA)}else{aI(aC,bn);s(aC);bc(aA,T);s(aA)}}if(!B(bl,V)){bc(V,bl);bc(aG,aC);bc(aE,aA)}else{bc(bl,V);bc(aC,aG);bc(aA,aE)}if(z(V,0)){while(r(aC)){aI(aC,bn);bc(aA,T)}m(aA,-1);ax(bj,aC);ax(t,aA);bi(bl,bm);return}}}function r(t){return((t[t.length-1]>>(x-1))&1)}function a(t,bn,T){var bl,bm=t.length,bk=bn.length;var bj=((bm+T)<bk)?(bm+T):bk;for(bl=bk-1-T;bl<bm&&bl>=0;bl++){if(t[bl]>0){return 1}}for(bl=bm-1+T;bl<bk;bl++){if(bn[bl]>0){return 0}}for(bl=bj-1;bl>=T;bl--){if(t[bl-T]>bn[bl]){return 1}else{if(t[bl-T]<bn[bl]){return 0}}}return 0}function B(t,bk){var bj;var T=(t.length<bk.length)?t.length:bk.length;for(bj=t.length;bj<bk.length;bj++){if(bk[bj]){return 0}}for(bj=bk.length;bj<t.length;bj++){if(t[bj]){return 1}}for(bj=T-1;bj>=0;bj--){if(t[bj]>bk[bj]){return 1}else{if(t[bj]<bk[bj]){return 0}}}return 0}function c(bt,bq,T,t){var bm,bl;var bk,bj,bs,bp,bn,br,bo;ax(t,bt);for(bl=bq.length;bq[bl-1]==0;bl--){}bo=bq[bl-1];for(br=0;bo;br++){bo>>=1}br=x-br;bi(bq,br);bi(t,br);for(bm=t.length;t[bm-1]==0&&bm>bl;bm--){}y(T,0);while(!a(bq,t,bm-bl)){az(t,bq,bm-bl);T[bm-bl]++}for(bk=bm-1;bk>=bl;bk--){if(t[bk]==bq[bl-1]){T[bk-bl]=aw}else{T[bk-bl]=Math.floor((t[bk]*E+t[bk-1])/bq[bl-1])}for(;;){bp=(bl>1?bq[bl-2]:0)*T[bk-bl];bn=bp;bp=bp&aw;bn=(bn-bp)/E;bs=bn+T[bk-bl]*bq[bl-1];bn=bs;bs=bs&aw;bn=(bn-bs)/E;if(bn==t[bk]?bs==t[bk-1]?bp>(bk>1?t[bk-2]:0):bs>t[bk-1]:bn>t[bk]){T[bk-bl]--}else{break}}av(t,bq,-T[bk-bl],bk-bl);if(r(t)){a9(t,bq,bk-bl);T[bk-bl]--}}G(bq,br);G(t,br)}function Y(T){var bk,bj,bl,t;bj=T.length;bl=0;for(bk=0;bk<bj;bk++){bl+=T[bk];t=0;if(bl<0){t=bl&aw;t=-((bl-t)/E);bl+=t*E}T[bk]=bl&aw;bl=((bl-T[bk])/E)-t}}function be(t,bk){var T,bj=0;for(T=t.length-1;T>=0;T--){bj=(bj*E+t[T])%bk}return bj}function a0(bk,bl,bm){var bj,T,bn;T=Math.ceil(bl/x)+1;T=bm>T?bm:T;bn=new Array(T);y(bn,bk);return bn}function a6(bt,bk,bj){var bp,bn,bm,bs,br,T;var bl=bt.length;if(bk==-1){bs=new Array(0);for(;;){br=new Array(bs.length+1);for(bn=0;bn<bs.length;bn++){br[bn+1]=bs[bn]}br[0]=parseInt(bt,10);bs=br;bp=bt.indexOf(",",0);if(bp<1){break}bt=bt.substring(bp+1);if(bt.length==0){break}}if(bs.length<bj){br=new Array(bj);ax(br,bs);return br}return bs}var bo=bk,t=0;var bq=bk==1?bl:0;while(bo>1){if(bo&1){t=1}bq+=bl;bo>>=1}bq+=t*bl;bs=a0(0,bq,0);for(bn=0;bn<bl;bn++){bp=bd.indexOf(bt.substring(bn,bn+1),0);if(bk<=36&&bp>=36){bp-=26}if(bp>=bk||bp<0){break}m(bs,bk);at(bs,bp)}for(bl=bs.length;bl>0&&!bs[bl-1];bl--){}bl=bj>bl+1?bj:bl+1;br=new Array(bl);T=bl<bs.length?bl:bs.length;for(bn=0;bn<T;bn++){br[bn]=bs[bn]}for(;bn<bl;bn++){br[bn]=0}return br}function z(t,bj){var T;if(t[0]!=bj){return 0}for(T=1;T<t.length;T++){if(t[T]){return 0}}return 1}function Q(t,bk){var bj;var T=t.length<bk.length?t.length:bk.length;for(bj=0;bj<T;bj++){if(t[bj]!=bk[bj]){return 0}}if(t.length>bk.length){for(;bj<t.length;bj++){if(t[bj]){return 0}}}else{for(;bj<bk.length;bj++){if(bk[bj]){return 0}}}return 1}function aZ(t){var T;for(T=0;T<t.length;T++){if(t[T]){return 0}}return 1}function aM(T,bm){var bk,bj,bl="";if(f.length!=T.length){f=K(T)}else{ax(f,T)}if(bm==-1){for(bk=T.length-1;bk>0;bk--){bl+=T[bk]+","}bl+=T[0]}else{while(!aZ(f)){bj=ac(f,bm);bl=bd.substring(bj,bj+1)+bl}}if(bl.length==0){bl="0"}return bl}function K(t){var T,bj;bj=new Array(t.length);ax(bj,t);return bj}function ax(t,bk){var bj;var T=t.length<bk.length?t.length:bk.length;for(bj=0;bj<T;bj++){t[bj]=bk[bj]}for(bj=T;bj<t.length;bj++){t[bj]=0}}function y(t,bk){var T,bj;for(bj=bk,T=0;T<t.length;T++){t[T]=bj&aw;bj>>=x}}function at(T,bm){var bk,bj,bl,t;T[0]+=bm;bj=T.length;bl=0;for(bk=0;bk<bj;bk++){bl+=T[bk];t=0;if(bl<0){t=bl&aw;t=-((bl-t)/E);bl+=t*E}T[bk]=bl&aw;bl=((bl-T[bk])/E)-t;if(!bl){return}}}function G(t,bk){var bj;var T=Math.floor(bk/x);if(T){for(bj=0;bj<t.length-T;bj++){t[bj]=t[bj+T]}for(;bj<t.length;bj++){t[bj]=0}bk%=x}for(bj=0;bj<t.length-1;bj++){t[bj]=aw&((t[bj+1]<<(x-bk))|(t[bj]>>bk))}t[bj]>>=bk}function s(t){var T;for(T=0;T<t.length-1;T++){t[T]=aw&((t[T+1]<<(x-1))|(t[T]>>1))}t[T]=(t[T]>>1)|(t[T]&(E>>1))}function bi(t,bk){var bj;var T=Math.floor(bk/x);if(T){for(bj=t.length;bj>=T;bj--){t[bj]=t[bj-T]}for(;bj>=0;bj--){t[bj]=0}bk%=x}if(!bk){return}for(bj=t.length-1;bj>0;bj--){t[bj]=aw&((t[bj]<<bk)|(t[bj-1]>>(x-bk)))}t[bj]=aw&(t[bj]<<bk)}function m(T,bm){var bk,bj,bl,t;if(!bm){return}bj=T.length;bl=0;for(bk=0;bk<bj;bk++){bl+=T[bk]*bm;t=0;if(bl<0){t=bl&aw;t=-((bl-t)/E);bl+=t*E}T[bk]=bl&aw;bl=((bl-T[bk])/E)-t}}function ac(t,bl){var T,bk=0,bj;for(T=t.length-1;T>=0;T--){bj=bk*E+t[T];t[T]=Math.floor(bj/bl);bk=bj%bl}return bk}function J(T,bo,bj,t){var bl,bn,bk,bm;bk=T.length<bo.length?T.length:bo.length;bm=T.length;for(bn=0,bl=0;bl<bk;bl++){bn+=bj*T[bl]+t*bo[bl];T[bl]=bn&aw;bn=(bn-T[bl])/E}for(bl=bk;bl<bm;bl++){bn+=bj*T[bl];T[bl]=bn&aw;bn=(bn-T[bl])/E}}function av(T,bo,t,bl){var bk,bn,bj,bm;bj=T.length<bl+bo.length?T.length:bl+bo.length;bm=T.length;for(bn=0,bk=bl;bk<bj;bk++){bn+=T[bk]+t*bo[bk-bl];T[bk]=bn&aw;bn=(bn-T[bk])/E}for(bk=bj;bn&&bk<bm;bk++){bn+=T[bk];T[bk]=bn&aw;bn=(bn-T[bk])/E}}function a9(t,bn,bk){var bj,bm,T,bl;T=t.length<bk+bn.length?t.length:bk+bn.length;bl=t.length;for(bm=0,bj=bk;bj<T;bj++){bm+=t[bj]+bn[bj-bk];t[bj]=bm&aw;bm=(bm-t[bj])/E}for(bj=T;bm&&bj<bl;bj++){bm+=t[bj];t[bj]=bm&aw;bm=(bm-t[bj])/E}}function az(t,bn,bk){var bj,bm,T,bl;T=t.length<bk+bn.length?t.length:bk+bn.length;bl=t.length;for(bm=0,bj=bk;bj<T;bj++){bm+=t[bj]-bn[bj-bk];t[bj]=bm&aw;bm=(bm-t[bj])/E}for(bj=T;bm&&bj<bl;bj++){bm+=t[bj];t[bj]=bm&aw;bm=(bm-t[bj])/E}}function bc(t,bm){var bj,bl,T,bk;T=t.length<bm.length?t.length:bm.length;for(bl=0,bj=0;bj<T;bj++){bl+=t[bj]-bm[bj];t[bj]=bl&aw;bl=(bl-t[bj])/E}for(bj=T;bl&&bj<t.length;bj++){bl+=t[bj];t[bj]=bl&aw;bl=(bl-t[bj])/E}}function aI(t,bm){var bj,bl,T,bk;T=t.length<bm.length?t.length:bm.length;for(bl=0,bj=0;bj<T;bj++){bl+=t[bj]+bm[bj];t[bj]=bl&aw;bl=(bl-t[bj])/E}for(bj=T;bl&&bj<t.length;bj++){bl+=t[bj];t[bj]=bl&aw;bl=(bl-t[bj])/E}}function aY(t,bj){var T;if(aT.length!=2*t.length){aT=new Array(2*t.length)}y(aT,0);for(T=0;T<bj.length;T++){if(bj[T]){av(aT,t,bj[T],T)}}ax(t,aT)}function aB(t,T){if(h.length!=t.length){h=K(t)}else{ax(h,t)}if(g.length!=t.length){g=K(t)}c(h,T,g,t)}function aU(t,bk,bj){var T;if(n.length!=2*t.length){n=new Array(2*t.length)}y(n,0);for(T=0;T<bk.length;T++){if(bk[T]){av(n,t,bk[T],T)}}aB(n,bj);ax(t,n)}function aJ(bo,t){var bk,bj,bm,bn,bl,bp,T;for(bl=bo.length;bl>0&&!bo[bl-1];bl--){}T=bl>t.length?2*bl:2*t.length;if(n.length!=T){n=new Array(T)}y(n,0);for(bk=0;bk<bl;bk++){bn=n[2*bk]+bo[bk]*bo[bk];n[2*bk]=bn&aw;bn=(bn-n[2*bk])/E;for(bj=bk+1;bj<bl;bj++){bn=n[bk+bj]+2*bo[bk]*bo[bj]+bn;n[bk+bj]=(bn&aw);bn=(bn-n[bk+bj])/E}n[bk+bl]=bn}aB(n,t);ax(bo,n)}function a4(t,T){var bj,bk;for(bj=t.length;bj>0&&!t[bj-1];bj--){}bk=new Array(bj+T);ax(bk,t);return bk}function aS(t,bn,bm){var bl,bk,T,bj;if(e.length!=bm.length){e=K(bm)}if((bm[0]&1)==0){ax(e,t);y(t,1);while(!z(bn,0)){if(bn[0]&1){aU(t,e,bm)}ac(bn,2);aJ(e,bm)}return}y(e,0);for(T=bm.length;T>0&&!bm[T-1];T--){}bj=E-aX(be(bm,E),E);e[T]=1;aU(t,e,bm);if(i.length!=t.length){i=K(t)}else{ax(i,t)}for(bl=bn.length-1;bl>0&!bn[bl];bl--){}if(bn[bl]==0){y(t,1);return}for(bk=1<<(x-1);bk&&!(bn[bl]&bk);bk>>=1){}for(;;){if(!(bk>>=1)){bl--;if(bl<0){au(t,o,bm,bj);return}bk=1<<(x-1)}au(t,t,bm,bj);if(bk&bn[bl]){au(t,i,bm,bj)}}}function au(br,bo,T,bs){var bk,bj,bn,bp,bt,bl,bq;var bu=T.length;var bm=bo.length;if(a2.length!=bu){a2=new Array(bu)}y(a2,0);for(;bu>0&&T[bu-1]==0;bu--){}for(;bm>0&&bo[bm-1]==0;bm--){}bq=a2.length-1;for(bk=0;bk<bu;bk++){bt=a2[0]+br[bk]*bo[0];bp=((bt&aw)*bs)&aw;bn=(bt+bp*T[0]);bn=(bn-(bn&aw))/E;bt=br[bk];bj=1;for(;bj<bm-4;){bn+=a2[bj]+bp*T[bj]+bt*bo[bj];bl=a2[bj-1]=bn&aw;bn=(bn-bl)/E;bj++;bn+=a2[bj]+bp*T[bj]+bt*bo[bj];bl=a2[bj-1]=bn&aw;bn=(bn-bl)/E;bj++;bn+=a2[bj]+bp*T[bj]+bt*bo[bj];bl=a2[bj-1]=bn&aw;bn=(bn-bl)/E;bj++;bn+=a2[bj]+bp*T[bj]+bt*bo[bj];bl=a2[bj-1]=bn&aw;bn=(bn-bl)/E;bj++;bn+=a2[bj]+bp*T[bj]+bt*bo[bj];bl=a2[bj-1]=bn&aw;bn=(bn-bl)/E;bj++}for(;bj<bm;){bn+=a2[bj]+bp*T[bj]+bt*bo[bj];bl=a2[bj-1]=bn&aw;bn=(bn-bl)/E;bj++}for(;bj<bu-4;){bn+=a2[bj]+bp*T[bj];bl=a2[bj-1]=bn&aw;bn=(bn-bl)/E;bj++;bn+=a2[bj]+bp*T[bj];bl=a2[bj-1]=bn&aw;bn=(bn-bl)/E;bj++;bn+=a2[bj]+bp*T[bj];bl=a2[bj-1]=bn&aw;bn=(bn-bl)/E;bj++;bn+=a2[bj]+bp*T[bj];bl=a2[bj-1]=bn&aw;bn=(bn-bl)/E;bj++;bn+=a2[bj]+bp*T[bj];bl=a2[bj-1]=bn&aw;bn=(bn-bl)/E;bj++}for(;bj<bu;){bn+=a2[bj]+bp*T[bj];bl=a2[bj-1]=bn&aw;bn=(bn-bl)/E;bj++}for(;bj<bq;){bn+=a2[bj];bl=a2[bj-1]=bn&aw;bn=(bn-bl)/E;bj++}a2[bj-1]=bn&aw}if(!B(T,a2)){bc(a2,T)}ax(br,a2)}function bb(t,bj,T){return an(t,bg(bj,T),T)}function aj(T,t,bj){T=b(T,bj);t=b(t,bj);if(B(t,T)){T=w(T,bj)}return a5(T,t)}function I(bj){var T=Math.floor(bj/x)+2;var bl=new Array(T);for(var bk=0;bk<T;bk++){bl[bk]=0}bl[T-2]=1<<(bj%x);return bl}var bh=(function(){var t=0,T={};for(;t<256;++t){T[t]=String.fromCharCode(t)}return T}());function ai(t,T){T||(T=0);t=K(t);var bj="";while(!aZ(t)){bj=bh[t[0]&255]+bj;G(t,8)}while(bj.length<T){bj="\x00"+bj}return bj}function aK(T){var t=a6("0",10,T.length);T.forEach(function(bk,bj){if(bj){bi(t,8)}t[0]|=bk});return t}var a3=(function(){if(typeof v!=="undefined"&&typeof v.randomBytes==="function"){return function(bj){try{var t=v.randomBytes(bj)}catch(T){throw T}return Array.prototype.slice.call(t,0)}}else{if(typeof v!=="undefined"&&typeof v.getRandomValues==="function"){return function(T){var t=new Uint8Array(T);v.getRandomValues(t);return Array.prototype.slice.call(t,0)}}else{throw new Error("Keys should not be generated without CSPRNG.")}}}());function aF(){return a3(40)}function am(){return a3(1)[0]}function aV(bj){if(bj>31){throw new Error("Too many bits.")}var bk=0,bl=0;var t=Math.floor(bj/8);var T=(1<<(bj%8))-1;if(T){bl=am()&T}for(;bk<t;bk++){bl=(256*bl)+am()}return bl}return{str2bigInt:a6,bigInt2str:aM,int2bigInt:a0,multMod:an,powMod:aP,inverseMod:bg,randBigInt:aO,randBigInt_:a1,equals:Q,equalsInt:z,sub:a5,mod:b,modInt:be,mult:d,divInt_:ac,rightShift_:G,dup:K,greater:B,add:w,isZero:aZ,bitSize:ay,millerRabin:aN,divide_:c,trim:a4,primes:N,findPrimes:ba,getSeed:aF,divMod:bb,subMod:aj,twoToThe:I,bigInt2bits:ai,ba2bigInt:aK}}));(function(a,b){if(typeof define==="function"&&define.amd){define(b)}else{if(typeof module!=="undefined"&&module.exports){module.exports=b()}else{a.CryptoJS=b()}}}(this,function(){var a=a||(function(f,h){var b={};var c=b.lib={};var k=c.Base=(function(){function o(){}return{extend:function(q){o.prototype=this;var p=new o();if(q){p.mixIn(q)}if(!p.hasOwnProperty("init")){p.init=function(){p.$super.init.apply(this,arguments)}}p.init.prototype=p;p.$super=this;return p},create:function(){var p=this.extend();p.init.apply(p,arguments);return p},init:function(){},mixIn:function(q){for(var p in q){if(q.hasOwnProperty(p)){this[p]=q[p]}}if(q.hasOwnProperty("toString")){this.toString=q.toString}},clone:function(){return this.init.prototype.extend(this)}}}());var m=c.WordArray=k.extend({init:function(p,o){p=this.words=p||[];if(o!=h){this.sigBytes=o}else{this.sigBytes=p.length*4}},toString:function(o){return(o||i).stringify(this)},concat:function(u){var r=this.words;var q=u.words;var o=this.sigBytes;var t=u.sigBytes;this.clamp();if(o%4){for(var s=0;s<t;s++){var p=(q[s>>>2]>>>(24-(s%4)*8))&255;r[(o+s)>>>2]|=p<<(24-((o+s)%4)*8)}}else{if(q.length>65535){for(var s=0;s<t;s+=4){r[(o+s)>>>2]=q[s>>>2]}}else{r.push.apply(r,q)}}this.sigBytes+=t;return this},clamp:function(){var p=this.words;var o=this.sigBytes;p[o>>>2]&=4294967295<<(32-(o%4)*8);p.length=f.ceil(o/4)},clone:function(){var o=k.clone.call(this);o.words=this.words.slice(0);return o},random:function(q){var p=[];for(var o=0;o<q;o+=4){p.push((f.random()*4294967296)|0)}return new m.init(p,q)}});var n=b.enc={};var i=n.Hex={stringify:function(q){var s=q.words;var p=q.sigBytes;var r=[];for(var o=0;o<p;o++){var t=(s[o>>>2]>>>(24-(o%4)*8))&255;r.push((t>>>4).toString(16));r.push((t&15).toString(16))}return r.join("")},parse:function(q){var o=q.length;var r=[];for(var p=0;p<o;p+=2){r[p>>>3]|=parseInt(q.substr(p,2),16)<<(24-(p%8)*4)}return new m.init(r,o/2)}};var e=n.Latin1={stringify:function(r){var s=r.words;var q=r.sigBytes;var o=[];for(var p=0;p<q;p++){var t=(s[p>>>2]>>>(24-(p%4)*8))&255;o.push(String.fromCharCode(t))}return o.join("")},parse:function(q){var o=q.length;var r=[];for(var p=0;p<o;p++){r[p>>>2]|=(q.charCodeAt(p)&255)<<(24-(p%4)*8)}return new m.init(r,o)}};var d=n.Utf8={stringify:function(o){try{return decodeURIComponent(escape(e.stringify(o)))}catch(p){throw new Error("Malformed UTF-8 data")}},parse:function(o){return e.parse(unescape(encodeURIComponent(o)))}};var j=c.BufferedBlockAlgorithm=k.extend({reset:function(){this._data=new m.init();this._nDataBytes=0},_append:function(o){if(typeof o=="string"){o=d.parse(o)}this._data.concat(o);this._nDataBytes+=o.sigBytes},_process:function(x){var r=this._data;var y=r.words;var o=r.sigBytes;var u=this.blockSize;var w=u*4;var v=o/w;if(x){v=f.ceil(v)}else{v=f.max((v|0)-this._minBufferSize,0)}var t=v*u;var s=f.min(t*4,o);if(t){for(var q=0;q<t;q+=u){this._doProcessBlock(y,q)}var p=y.splice(0,t);r.sigBytes-=s}return new m.init(p,s)},clone:function(){var o=k.clone.call(this);o._data=this._data.clone();return o},_minBufferSize:0});var g=c.Hasher=j.extend({cfg:k.extend(),init:function(o){this.cfg=this.cfg.extend(o);this.reset()},reset:function(){j.reset.call(this);this._doReset()},update:function(o){this._append(o);this._process();return this},finalize:function(o){if(o){this._append(o)}var p=this._doFinalize();return p},blockSize:512/32,_createHelper:function(o){return function(q,p){return new o.init(p).finalize(q)}},_createHmacHelper:function(o){return function(q,p){return new l.HMAC.init(o,p).finalize(q)}}});var l=b.algo={};return b}(Math));(function(){var f=a;var b=f.lib;var c=b.WordArray;var e=f.enc;var d=e.Base64={stringify:function(m){var o=m.words;var q=m.sigBytes;var h=this._map;m.clamp();var n=[];for(var l=0;l<q;l+=3){var t=(o[l>>>2]>>>(24-(l%4)*8))&255;var r=(o[(l+1)>>>2]>>>(24-((l+1)%4)*8))&255;var p=(o[(l+2)>>>2]>>>(24-((l+2)%4)*8))&255;var s=(t<<16)|(r<<8)|p;for(var k=0;(k<4)&&(l+k*0.75<q);k++){n.push(h.charAt((s>>>(6*(3-k)))&63))}}var g=h.charAt(64);if(g){while(n.length%4){n.push(g)}}return n.join("")},parse:function(p){var n=p.length;var h=this._map;var g=h.charAt(64);if(g){var q=p.indexOf(g);if(q!=-1){n=q}}var o=[];var m=0;for(var l=0;l<n;l++){if(l%4){var k=h.indexOf(p.charAt(l-1))<<((l%4)*2);var j=h.indexOf(p.charAt(l))>>>(6-(l%4)*2);o[m>>>2]|=(k|j)<<(24-(m%4)*8);m++}}return c.create(o,m)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}}());a.lib.Cipher||(function(e){var n=a;var x=n.lib;var j=x.Base;var u=x.WordArray;var w=x.BufferedBlockAlgorithm;var s=n.enc;var g=s.Utf8;var m=s.Base64;var c=n.algo;var i=c.EvpKDF;var k=x.Cipher=w.extend({cfg:j.extend(),createEncryptor:function(C,B){return this.create(this._ENC_XFORM_MODE,C,B)},createDecryptor:function(C,B){return this.create(this._DEC_XFORM_MODE,C,B)},init:function(D,C,B){this.cfg=this.cfg.extend(B);this._xformMode=D;this._key=C;this.reset()},reset:function(){w.reset.call(this);this._doReset()},process:function(B){this._append(B);return this._process()},finalize:function(C){if(C){this._append(C)}var B=this._doFinalize();return B},keySize:128/32,ivSize:128/32,_ENC_XFORM_MODE:1,_DEC_XFORM_MODE:2,_createHelper:(function(){function B(C){if(typeof C=="string"){return h}else{return A}}return function(C){return{encrypt:function(F,E,D){return B(E).encrypt(C,F,E,D)},decrypt:function(F,E,D){return B(E).decrypt(C,F,E,D)}}}}())});var q=x.StreamCipher=k.extend({_doFinalize:function(){var B=this._process(!!"flush");return B},blockSize:1});var t=n.mode={};var z=x.BlockCipherMode=j.extend({createEncryptor:function(B,C){return this.Encryptor.create(B,C)},createDecryptor:function(B,C){return this.Decryptor.create(B,C)},init:function(B,C){this._cipher=B;this._iv=C}});var d=t.CBC=(function(){var B=z.extend();B.Encryptor=B.extend({processBlock:function(G,F){var D=this._cipher;var E=D.blockSize;C.call(this,G,F,E);D.encryptBlock(G,F);this._prevBlock=G.slice(F,F+E)}});B.Decryptor=B.extend({processBlock:function(H,G){var D=this._cipher;var F=D.blockSize;var E=H.slice(G,G+F);D.decryptBlock(H,G);C.call(this,H,G,F);this._prevBlock=E}});function C(I,H,F){var D=this._iv;if(D){var G=D;this._iv=e}else{var G=this._prevBlock}for(var E=0;E<F;E++){I[H+E]^=G[E]}}return B}());var f=n.pad={};var b=f.Pkcs7={pad:function(G,E){var F=E*4;var I=F-G.sigBytes%F;var B=(I<<24)|(I<<16)|(I<<8)|I;var D=[];for(var C=0;C<I;C+=4){D.push(B)}var H=u.create(D,I);G.concat(H)},unpad:function(B){var C=B.words[(B.sigBytes-1)>>>2]&255;B.sigBytes-=C}};var r=x.BlockCipher=k.extend({cfg:k.cfg.extend({mode:d,padding:b}),reset:function(){k.reset.call(this);var B=this.cfg;var C=B.iv;var E=B.mode;if(this._xformMode==this._ENC_XFORM_MODE){var D=E.createEncryptor}else{var D=E.createDecryptor;this._minBufferSize=1}this._mode=D.call(E,this,C&&C.words)},_doProcessBlock:function(C,B){this._mode.processBlock(C,B)},_doFinalize:function(){var C=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){C.pad(this._data,this.blockSize);var B=this._process(!!"flush")}else{var B=this._process(!!"flush");C.unpad(B)}return B},blockSize:128/32});var p=x.CipherParams=j.extend({init:function(B){this.mixIn(B)},toString:function(B){return(B||this.formatter).stringify(this)}});var o=n.format={};var v=o.OpenSSL={stringify:function(B){var E=B.ciphertext;var C=B.salt;if(C){var D=u.create([1398893684,1701076831]).concat(C).concat(E)}else{var D=E}return D.toString(m)},parse:function(D){var C=m.parse(D);var E=C.words;if(E[0]==1398893684&&E[1]==1701076831){var B=u.create(E.slice(2,4));E.splice(0,4);C.sigBytes-=16}return p.create({ciphertext:C,salt:B})}};var A=x.SerializableCipher=j.extend({cfg:j.extend({format:v}),encrypt:function(B,G,E,C){C=this.cfg.extend(C);var D=B.createEncryptor(E,C);var H=D.finalize(G);var F=D.cfg;return p.create({ciphertext:H,key:E,iv:F.iv,algorithm:B,mode:F.mode,padding:F.padding,blockSize:B.blockSize,formatter:C.format})},decrypt:function(B,F,D,C){C=this.cfg.extend(C);F=this._parse(F,C.format);var E=B.createDecryptor(D,C).finalize(F.ciphertext);return E},_parse:function(B,C){if(typeof B=="string"){return C.parse(B,this)}else{return B}}});var l=n.kdf={};var y=l.OpenSSL={execute:function(D,G,B,F){if(!F){F=u.random(64/8)}var E=i.create({keySize:G+B}).compute(D,F);var C=u.create(E.words.slice(G),B*4);E.sigBytes=G*4;return p.create({key:E,iv:C,salt:F})}};var h=x.PasswordBasedCipher=A.extend({cfg:A.cfg.extend({kdf:y}),encrypt:function(B,E,D,C){C=this.cfg.extend(C);var G=C.kdf.execute(D,B.keySize,B.ivSize);C.iv=G.iv;var F=A.encrypt.call(this,B,E,G.key,C);F.mixIn(G);return F},decrypt:function(B,F,D,C){C=this.cfg.extend(C);F=this._parse(F,C.format);var G=C.kdf.execute(D,B.keySize,B.ivSize,F.salt);C.iv=G.iv;var E=A.decrypt.call(this,B,F,G.key,C);return E}})}());(function(){var b=a;var c=b.lib;var q=c.BlockCipher;var l=b.algo;var e=[];var m=[];var p=[];var o=[];var n=[];var k=[];var j=[];var i=[];var h=[];var g=[];(function(){var u=[];for(var s=0;s<256;s++){if(s<128){u[s]=s<<1}else{u[s]=(s<<1)^283}}var y=0;var v=0;for(var s=0;s<256;s++){var w=v^(v<<1)^(v<<2)^(v<<3)^(v<<4);w=(w>>>8)^(w&255)^99;e[y]=w;m[w]=y;var r=u[y];var B=u[r];var z=u[B];var A=(u[w]*257)^(w*16843008);p[y]=(A<<24)|(A>>>8);o[y]=(A<<16)|(A>>>16);n[y]=(A<<8)|(A>>>24);k[y]=A;var A=(z*16843009)^(B*65537)^(r*257)^(y*16843008);j[w]=(A<<24)|(A>>>8);i[w]=(A<<16)|(A>>>16);h[w]=(A<<8)|(A>>>24);g[w]=A;if(!y){y=v=1}else{y=r^u[u[u[z^r]]];v^=u[u[v]]}}}());var d=[0,1,2,4,8,16,32,64,128,27,54];var f=l.AES=q.extend({_doReset:function(){var A=this._key;var s=A.words;var z=A.sigBytes/4;var y=this._nRounds=z+6;var r=(y+1)*4;var u=this._keySchedule=[];for(var x=0;x<r;x++){if(x<z){u[x]=s[x]}else{var B=u[x-1];if(!(x%z)){B=(B<<8)|(B>>>24);B=(e[B>>>24]<<24)|(e[(B>>>16)&255]<<16)|(e[(B>>>8)&255]<<8)|e[B&255];B^=d[(x/z)|0]<<24}else{if(z>6&&x%z==4){B=(e[B>>>24]<<24)|(e[(B>>>16)&255]<<16)|(e[(B>>>8)&255]<<8)|e[B&255]}}u[x]=u[x-z]^B}}var v=this._invKeySchedule=[];for(var w=0;w<r;w++){var x=r-w;if(w%4){var B=u[x]}else{var B=u[x-4]}if(w<4||x<=4){v[w]=B}else{v[w]=j[e[B>>>24]]^i[e[(B>>>16)&255]]^h[e[(B>>>8)&255]]^g[e[B&255]]}}},encryptBlock:function(s,r){this._doCryptBlock(s,r,this._keySchedule,p,o,n,k,e)},decryptBlock:function(u,s){var r=u[s+1];u[s+1]=u[s+3];u[s+3]=r;this._doCryptBlock(u,s,this._invKeySchedule,j,i,h,g,m);var r=u[s+1];u[s+1]=u[s+3];u[s+3]=r},_doCryptBlock:function(A,z,I,w,u,s,r,H){var F=this._nRounds;var y=A[z]^I[0];var x=A[z+1]^I[1];var v=A[z+2]^I[2];var t=A[z+3]^I[3];var G=4;for(var J=1;J<F;J++){var E=w[y>>>24]^u[(x>>>16)&255]^s[(v>>>8)&255]^r[t&255]^I[G++];var D=w[x>>>24]^u[(v>>>16)&255]^s[(t>>>8)&255]^r[y&255]^I[G++];var C=w[v>>>24]^u[(t>>>16)&255]^s[(y>>>8)&255]^r[x&255]^I[G++];var B=w[t>>>24]^u[(y>>>16)&255]^s[(x>>>8)&255]^r[v&255]^I[G++];y=E;x=D;v=C;t=B}var E=((H[y>>>24]<<24)|(H[(x>>>16)&255]<<16)|(H[(v>>>8)&255]<<8)|H[t&255])^I[G++];var D=((H[x>>>24]<<24)|(H[(v>>>16)&255]<<16)|(H[(t>>>8)&255]<<8)|H[y&255])^I[G++];var C=((H[v>>>24]<<24)|(H[(t>>>16)&255]<<16)|(H[(y>>>8)&255]<<8)|H[x&255])^I[G++];var B=((H[t>>>24]<<24)|(H[(y>>>16)&255]<<16)|(H[(x>>>8)&255]<<8)|H[v&255])^I[G++];A[z]=E;A[z+1]=D;A[z+2]=C;A[z+3]=B},keySize:256/32});b.AES=q._createHelper(f)}());(function(){var h=a;var e=h.lib;var g=e.WordArray;var c=e.Hasher;var f=h.algo;var b=[];var d=f.SHA1=c.extend({_doReset:function(){this._hash=new g.init([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(o,k){var u=this._hash.words;var s=u[0];var r=u[1];var q=u[2];var p=u[3];var m=u[4];for(var l=0;l<80;l++){if(l<16){b[l]=o[k+l]|0}else{var j=b[l-3]^b[l-8]^b[l-14]^b[l-16];b[l]=(j<<1)|(j>>>31)}var v=((s<<5)|(s>>>27))+m+b[l];if(l<20){v+=((r&q)|(~r&p))+1518500249}else{if(l<40){v+=(r^q^p)+1859775393}else{if(l<60){v+=((r&q)|(r&p)|(q&p))-1894007588}else{v+=(r^q^p)-899497514}}}m=p;p=q;q=(r<<30)|(r>>>2);r=s;s=v}u[0]=(u[0]+s)|0;u[1]=(u[1]+r)|0;u[2]=(u[2]+q)|0;u[3]=(u[3]+p)|0;u[4]=(u[4]+m)|0},_doFinalize:function(){var k=this._data;var l=k.words;var i=this._nDataBytes*8;var j=k.sigBytes*8;l[j>>>5]|=128<<(24-j%32);l[(((j+64)>>>9)<<4)+14]=Math.floor(i/4294967296);l[(((j+64)>>>9)<<4)+15]=i;k.sigBytes=l.length*4;this._process();return this._hash},clone:function(){var i=c.clone.call(this);i._hash=this._hash.clone();return i}});h.SHA1=c._createHelper(d);h.HmacSHA1=c._createHmacHelper(d)}());(function(d){var b=a;var c=b.lib;var h=c.WordArray;var f=c.Hasher;var i=b.algo;var k=[];var j=[];(function(){function o(s){var r=d.sqrt(s);for(var q=2;q<=r;q++){if(!(s%q)){return false}}return true}function m(q){return((q-(q|0))*4294967296)|0}var p=2;var l=0;while(l<64){if(o(p)){if(l<8){k[l]=m(d.pow(p,1/2))}j[l]=m(d.pow(p,1/3));l++}p++}}());var e=[];var g=i.SHA256=f.extend({_doReset:function(){this._hash=new h.init(k.slice(0))},_doProcessBlock:function(o,n){var r=this._hash.words;var E=r[0];var D=r[1];var C=r[2];var B=r[3];var A=r[4];var z=r[5];var y=r[6];var x=r[7];for(var w=0;w<64;w++){if(w<16){e[w]=o[n+w]|0}else{var m=e[w-15];var G=((m<<25)|(m>>>7))^((m<<14)|(m>>>18))^(m>>>3);var s=e[w-2];var F=((s<<15)|(s>>>17))^((s<<13)|(s>>>19))^(s>>>10);e[w]=G+e[w-7]+F+e[w-16]}var t=(A&z)^(~A&y);var l=(E&D)^(E&C)^(D&C);var v=((E<<30)|(E>>>2))^((E<<19)|(E>>>13))^((E<<10)|(E>>>22));var u=((A<<26)|(A>>>6))^((A<<21)|(A>>>11))^((A<<7)|(A>>>25));var q=x+u+t+j[w]+e[w];var p=v+l;x=y;y=z;z=A;A=(B+q)|0;B=C;C=D;D=E;E=(q+p)|0}r[0]=(r[0]+E)|0;r[1]=(r[1]+D)|0;r[2]=(r[2]+C)|0;r[3]=(r[3]+B)|0;r[4]=(r[4]+A)|0;r[5]=(r[5]+z)|0;r[6]=(r[6]+y)|0;r[7]=(r[7]+x)|0},_doFinalize:function(){var n=this._data;var o=n.words;var l=this._nDataBytes*8;var m=n.sigBytes*8;o[m>>>5]|=128<<(24-m%32);o[(((m+64)>>>9)<<4)+14]=d.floor(l/4294967296);o[(((m+64)>>>9)<<4)+15]=l;n.sigBytes=o.length*4;this._process();return this._hash},clone:function(){var l=f.clone.call(this);l._hash=this._hash.clone();return l}});b.SHA256=f._createHelper(g);b.HmacSHA256=f._createHmacHelper(g)}(Math));(function(){var h=a;var e=h.lib;var d=e.Base;var g=h.enc;var c=g.Utf8;var f=h.algo;var b=f.HMAC=d.extend({init:function(r,o){r=this._hasher=new r.init();if(typeof o=="string"){o=c.parse(o)}var l=r.blockSize;var j=l*4;if(o.sigBytes>j){o=r.finalize(o)}o.clamp();var q=this._oKey=o.clone();var n=this._iKey=o.clone();var p=q.words;var k=n.words;for(var m=0;m<l;m++){p[m]^=1549556828;k[m]^=909522486}q.sigBytes=n.sigBytes=j;this.reset()},reset:function(){var i=this._hasher;i.reset();i.update(this._iKey)},update:function(i){this._hasher.update(i);return this},finalize:function(i){var j=this._hasher;var l=j.finalize(i);j.reset();var k=j.finalize(this._oKey.clone().concat(l));return k}})}());a.pad.NoPadding={pad:function(){},unpad:function(){}};a.mode.CTR=(function(){var c=a.lib.BlockCipherMode.extend();var b=c.Encryptor=c.extend({processBlock:function(l,k){var d=this._cipher;var h=d.blockSize;var f=this._iv;var e=this._counter;if(f){e=this._counter=f.slice(0);this._iv=undefined}var j=e.slice(0);d.encryptBlock(j,0);e[h-1]=(e[h-1]+1)|0;for(var g=0;g<h;g++){l[k+g]^=j[g]}}});c.Decryptor=b;return c}());return a}));/*!
+ * EventEmitter v4.2.3 - git.io/ee
+ * Oliver Caldwell
+ * MIT license
+ * @preserve
+ */
+(function(){function c(){}var l=c.prototype;function h(w,x){var v=w.length;while(v--){if(w[v].listener===x){return v}}return -1}function j(v){return function w(){return this[v].apply(this,arguments)}}l.getListeners=function t(v){var y=this._getEvents();var w;var x;if(typeof v==="object"){w={};for(x in y){if(y.hasOwnProperty(x)&&v.test(x)){w[x]=y[x]}}}else{w=y[v]||(y[v]=[])}return w};l.flattenListeners=function r(x){var v=[];var w;for(w=0;w<x.length;w+=1){v.push(x[w].listener)}return v};l.getListenersAsObject=function e(v){var x=this.getListeners(v);var w;if(x instanceof Array){w={};w[v]=x}return w||x};l.addListener=function f(v,y){var x=this.getListenersAsObject(v);var z=typeof y==="object";var w;for(w in x){if(x.hasOwnProperty(w)&&h(x[w],y)===-1){x[w].push(z?y:{listener:y,once:false})}}return this};l.on=j("addListener");l.addOnceListener=function a(v,w){return this.addListener(v,{listener:w,once:true})};l.once=j("addOnceListener");l.defineEvent=function p(v){this.getListeners(v);return this};l.defineEvents=function q(v){for(var w=0;w<v.length;w+=1){this.defineEvent(v[w])}return this};l.removeListener=function b(v,z){var y=this.getListenersAsObject(v);var w;var x;for(x in y){if(y.hasOwnProperty(x)){w=h(y[x],z);if(w!==-1){y[x].splice(w,1)}}}return this};l.off=j("removeListener");l.addListeners=function m(v,w){return this.manipulateListeners(false,v,w)};l.removeListeners=function s(v,w){return this.manipulateListeners(true,v,w)};l.manipulateListeners=function g(w,x,z){var y;var A;var B=w?this.removeListener:this.addListener;var v=w?this.removeListeners:this.addListeners;if(typeof x==="object"&&!(x instanceof RegExp)){for(y in x){if(x.hasOwnProperty(y)&&(A=x[y])){if(typeof A==="function"){B.call(this,y,A)}else{v.call(this,y,A)}}}}else{y=z.length;while(y--){B.call(this,x,z[y])}}return this};l.removeEvent=function o(v){var y=typeof v;var x=this._getEvents();var w;if(y==="string"){delete x[v]}else{if(y==="object"){for(w in x){if(x.hasOwnProperty(w)&&v.test(w)){delete x[w]}}}else{delete this._events}}return this};l.emitEvent=function u(v,x){var A=this.getListenersAsObject(v);var B;var z;var y;var w;for(y in A){if(A.hasOwnProperty(y)){z=A[y].length;while(z--){B=A[y][z];if(B.once===true){this.removeListener(v,B.listener)}w=B.listener.apply(this,x||[]);if(w===this._getOnceReturnValue()){this.removeListener(v,B.listener)}}}}return this};l.trigger=j("emitEvent");l.emit=function k(v){var w=Array.prototype.slice.call(arguments,1);return this.emitEvent(v,w)};l.setOnceReturnValue=function i(v){this._onceReturnValue=v;return this};l._getOnceReturnValue=function n(){if(this.hasOwnProperty("_onceReturnValue")){return this._onceReturnValue}else{return true}};l._getEvents=function d(){return this._events||(this._events={})};if(typeof define==="function"&&define.amd){define(function(){return c})}else{if(typeof module==="object"&&module.exports){module.exports=c}else{this.EventEmitter=c}}}.call(this));/*!
+
+  otr.js v0.2.12 - 2014-04-15
+  (c) 2014 - Arlo Breault <arlolra@gmail.com>
+  Freely distributed under the MPL v2.0 license.
+
+  This file is concatenated for the browser.
+  Please see: https://github.com/arlolra/otr
+
+*/
+
+!function(root,factory){"function"==typeof define&&define.amd?define(["bigint","crypto","eventemitter"],function(BigInt,CryptoJS,EventEmitter){var root={BigInt:BigInt,CryptoJS:CryptoJS,EventEmitter:EventEmitter,OTR:{},DSA:{}};return factory.call(root)}):(root.OTR={},root.DSA={},factory.call(root))}(this,function(){return function(){"use strict";var root=this,CONST={N:"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF",G:"2",MSGSTATE_PLAINTEXT:0,MSGSTATE_ENCRYPTED:1,MSGSTATE_FINISHED:2,AUTHSTATE_NONE:0,AUTHSTATE_AWAITING_DHKEY:1,AUTHSTATE_AWAITING_REVEALSIG:2,AUTHSTATE_AWAITING_SIG:3,WHITESPACE_TAG:" 	  				 	 	 	  ",WHITESPACE_TAG_V2:"  		  	 ",WHITESPACE_TAG_V3:"  		  		",OTR_TAG:"?OTR",OTR_VERSION_1:"\x00",OTR_VERSION_2:"\x00",OTR_VERSION_3:"\x00",SMPSTATE_EXPECT0:0,SMPSTATE_EXPECT1:1,SMPSTATE_EXPECT2:2,SMPSTATE_EXPECT3:3,SMPSTATE_EXPECT4:4,STATUS_SEND_QUERY:0,STATUS_AKE_INIT:1,STATUS_AKE_SUCCESS:2,STATUS_END_OTR:3};"undefined"!=typeof module&&module.exports?module.exports=CONST:root.OTR.CONST=CONST}.call(this),function(){"use strict";var CryptoJS,BigInt,root=this,HLP={};"undefined"!=typeof module&&module.exports?(module.exports=HLP={},CryptoJS=require("../vendor/crypto.js"),BigInt=require("../vendor/bigint.js")):(root.OTR&&(root.OTR.HLP=HLP),root.DSA&&(root.DSA.HLP=HLP),CryptoJS=root.CryptoJS,BigInt=root.BigInt);var DTS={BYTE:1,SHORT:2,INT:4,CTR:8,MAC:20,SIG:40},WRAPPER_BEGIN="?OTR",WRAPPER_END=".",TWO=BigInt.str2bigInt("2",10);HLP.debug=function(msg){this.debug&&"function"!=typeof this.debug&&"undefined"!=typeof console&&console.log(msg)},HLP.extend=function(child,parent){function Ctor(){this.constructor=child}for(var key in parent)Object.hasOwnProperty.call(parent,key)&&(child[key]=parent[key]);Ctor.prototype=parent.prototype,child.prototype=new Ctor,child.__super__=parent.prototype},HLP.compare=function(str1,str2){if(str1.length!==str2.length)return!1;for(var i=0,result=0;i<str1.length;i++)result|=str1[i].charCodeAt(0)^str2[i].charCodeAt(0);return 0===result},HLP.randomExponent=function(){return BigInt.randBigInt(1536)},HLP.smpHash=function(version,fmpi,smpi){var sha256=CryptoJS.algo.SHA256.create();sha256.update(CryptoJS.enc.Latin1.parse(HLP.packBytes(version,DTS.BYTE))),sha256.update(CryptoJS.enc.Latin1.parse(HLP.packMPI(fmpi))),smpi&&sha256.update(CryptoJS.enc.Latin1.parse(HLP.packMPI(smpi)));var hash=sha256.finalize();return HLP.bits2bigInt(hash.toString(CryptoJS.enc.Latin1))},HLP.makeMac=function(aesctr,m){var pass=CryptoJS.enc.Latin1.parse(m),mac=CryptoJS.HmacSHA256(CryptoJS.enc.Latin1.parse(aesctr),pass);return HLP.mask(mac.toString(CryptoJS.enc.Latin1),0,160)},HLP.make1Mac=function(aesctr,m){var pass=CryptoJS.enc.Latin1.parse(m),mac=CryptoJS.HmacSHA1(CryptoJS.enc.Latin1.parse(aesctr),pass);return mac.toString(CryptoJS.enc.Latin1)},HLP.encryptAes=function(msg,c,iv){var opts={mode:CryptoJS.mode.CTR,iv:CryptoJS.enc.Latin1.parse(iv),padding:CryptoJS.pad.NoPadding},aesctr=CryptoJS.AES.encrypt(msg,CryptoJS.enc.Latin1.parse(c),opts),aesctr_decoded=CryptoJS.enc.Base64.parse(aesctr.toString());return CryptoJS.enc.Latin1.stringify(aesctr_decoded)},HLP.decryptAes=function(msg,c,iv){msg=CryptoJS.enc.Latin1.parse(msg);var opts={mode:CryptoJS.mode.CTR,iv:CryptoJS.enc.Latin1.parse(iv),padding:CryptoJS.pad.NoPadding};return CryptoJS.AES.decrypt(CryptoJS.enc.Base64.stringify(msg),CryptoJS.enc.Latin1.parse(c),opts)},HLP.multPowMod=function(a,b,c,d,e){return BigInt.multMod(BigInt.powMod(a,b,e),BigInt.powMod(c,d,e),e)},HLP.ZKP=function(v,c,d,e){return BigInt.equals(c,HLP.smpHash(v,d,e))},HLP.GTOE=function(a,b){return BigInt.equals(a,b)||BigInt.greater(a,b)},HLP.between=function(x,a,b){return BigInt.greater(x,a)&&BigInt.greater(b,x)},HLP.checkGroup=function(g,N_MINUS_2){return HLP.GTOE(g,TWO)&&HLP.GTOE(N_MINUS_2,g)},HLP.h1=function(b,secbytes){var sha1=CryptoJS.algo.SHA1.create();return sha1.update(CryptoJS.enc.Latin1.parse(b)),sha1.update(CryptoJS.enc.Latin1.parse(secbytes)),sha1.finalize().toString(CryptoJS.enc.Latin1)},HLP.h2=function(b,secbytes){var sha256=CryptoJS.algo.SHA256.create();return sha256.update(CryptoJS.enc.Latin1.parse(b)),sha256.update(CryptoJS.enc.Latin1.parse(secbytes)),sha256.finalize().toString(CryptoJS.enc.Latin1)},HLP.mask=function(bytes,start,n){return bytes.substr(start/8,n/8)};var _toString=String.fromCharCode;HLP.packBytes=function(val,bytes){val=val.toString(16);for(var nex,res="";bytes>0;bytes--)nex=val.length?val.substr(-2,2):"0",val=val.substr(0,val.length-2),res=_toString(parseInt(nex,16))+res;return res},HLP.packINT=function(d){return HLP.packBytes(d,DTS.INT)},HLP.packCtr=function(d){return HLP.padCtr(HLP.packBytes(d,DTS.CTR))},HLP.padCtr=function(ctr){return ctr+"\x00\x00\x00\x00\x00\x00\x00\x00"},HLP.unpackCtr=function(d){return d=HLP.toByteArray(d.substring(0,8)),HLP.unpack(d)},HLP.unpack=function(arr){for(var val=0,i=0,len=arr.length;len>i;i++)val=256*val+arr[i];return val},HLP.packData=function(d){return HLP.packINT(d.length)+d},HLP.bits2bigInt=function(bits){return bits=HLP.toByteArray(bits),BigInt.ba2bigInt(bits)},HLP.packMPI=function(mpi){return HLP.packData(BigInt.bigInt2bits(BigInt.trim(mpi,0)))},HLP.packSHORT=function(short){return HLP.packBytes(short,DTS.SHORT)},HLP.unpackSHORT=function(short){return short=HLP.toByteArray(short),HLP.unpack(short)},HLP.packTLV=function(type,value){return HLP.packSHORT(type)+HLP.packSHORT(value.length)+value},HLP.readLen=function(msg){return msg=HLP.toByteArray(msg.substring(0,4)),HLP.unpack(msg)},HLP.readData=function(data){var n=HLP.unpack(data.splice(0,4));return[n,data]},HLP.readMPI=function(data){return data=HLP.toByteArray(data),data=HLP.readData(data),BigInt.ba2bigInt(data[1])},HLP.packMPIs=function(arr){return arr.reduce(function(prv,cur){return prv+HLP.packMPI(cur)},"")},HLP.unpackMPIs=function(num,mpis){for(var i=0,arr=[];num>i;i++)arr.push("MPI");return HLP.splitype(arr,mpis).map(function(m){return HLP.readMPI(m)})},HLP.wrapMsg=function(msg,fs,v3,our_it,their_it){msg=CryptoJS.enc.Base64.stringify(CryptoJS.enc.Latin1.parse(msg)),msg=WRAPPER_BEGIN+":"+msg+WRAPPER_END;var its;if(v3&&(its="|",its+=HLP.readLen(our_it).toString(16),its+="|",its+=HLP.readLen(their_it).toString(16)),!fs)return[null,msg];var n=Math.ceil(msg.length/fs);if(n>65535)return["Too many fragments"];if(1==n)return[null,msg];var k,bi,ei,frag,mf,mfs=[];for(k=1;n>=k;k++)bi=(k-1)*fs,ei=k*fs,frag=msg.slice(bi,ei),mf=WRAPPER_BEGIN,v3&&(mf+=its),mf+=","+k+",",mf+=n+",",mf+=frag+",",mfs.push(mf);return[null,mfs]},HLP.splitype=function splitype(arr,msg){var data=[];return arr.forEach(function(a){var str;switch(a){case"PUBKEY":str=splitype(["SHORT","MPI","MPI","MPI","MPI"],msg).join("");break;case"DATA":case"MPI":str=msg.substring(0,HLP.readLen(msg)+4);break;default:str=msg.substring(0,DTS[a])}data.push(str),msg=msg.substring(str.length)}),data};var _bin2num=function(){for(var i=0,_bin2num={};256>i;++i)_bin2num[String.fromCharCode(i)]=i;for(i=128;256>i;++i)_bin2num[String.fromCharCode(63232+i)]=i;return _bin2num}();HLP.toByteArray=function(data){for(var rv=[],ary=data.split(""),i=-1,iz=ary.length,remain=iz%8;remain--;)++i,rv[i]=_bin2num[ary[i]];for(remain=iz>>3;remain--;)rv.push(_bin2num[ary[++i]],_bin2num[ary[++i]],_bin2num[ary[++i]],_bin2num[ary[++i]],_bin2num[ary[++i]],_bin2num[ary[++i]],_bin2num[ary[++i]],_bin2num[ary[++i]]);return rv}}.call(this),function(){"use strict";function timer(){var start=(new Date).getTime();return function(s){if(DEBUG&&"undefined"!=typeof console){var t=(new Date).getTime();console.log(s+": "+(t-start)),start=t}}}function makeRandom(min,max){var c=BigInt.randBigInt(BigInt.bitSize(max));return HLP.between(c,min,max)?c:makeRandom(min,max)}function isProbPrime(k,n){var i,B=3e4,l=BigInt.bitSize(k),primes=BigInt.primes;for(0===primes.length&&(primes=BigInt.findPrimes(B)),rpprb.length!=k.length&&(rpprb=BigInt.dup(k)),i=0;i<primes.length&&primes[i]<=B;i++)if(0===BigInt.modInt(k,primes[i])&&!BigInt.equalsInt(k,primes[i]))return 0;for(i=0;n>i;i++){for(BigInt.randBigInt_(rpprb,l,0);!BigInt.greater(k,rpprb);)BigInt.randBigInt_(rpprb,l,0);if(!BigInt.millerRabin(k,rpprb))return 0}return 1}function generatePrimes(bit_length){for(var q,p,rem,counter,t=timer(),repeat=bit_lengths[bit_length].repeat,N=bit_lengths[bit_length].N,LM1=BigInt.twoToThe(bit_length-1),bl4=4*bit_length,brk=!1;;)if(q=BigInt.randBigInt(N,1),q[0]|=1,isProbPrime(q,repeat)){for(t("q"),counter=0;bl4>counter;counter++)if(p=BigInt.randBigInt(bit_length,1),p[0]|=1,rem=BigInt.mod(p,q),rem=BigInt.sub(rem,ONE),p=BigInt.sub(p,rem),!BigInt.greater(LM1,p)&&isProbPrime(p,repeat)){t("p"),primes[bit_length]={p:p,q:q},brk=!0;break}if(brk)break}for(var g,h=BigInt.dup(TWO),pm1=BigInt.sub(p,ONE),e=BigInt.multMod(pm1,BigInt.inverseMod(q,p),p);;){g=BigInt.powMod(h,e,p);{if(!BigInt.equals(g,ONE))return primes[bit_length].g=g,void t("g");h=BigInt.add(h,ONE)}}throw new Error("Unreachable!")}function DSA(obj,opts){if(!(this instanceof DSA))return new DSA(obj,opts);if(opts=opts||{},obj){var self=this;return["p","q","g","y","x"].forEach(function(prop){self[prop]=obj[prop]}),void(this.type=obj.type||KEY_TYPE)}var bit_length=parseInt(opts.bit_length?opts.bit_length:1024,10);if(!bit_lengths[bit_length])throw new Error("Unsupported bit length.");primes[bit_length]||generatePrimes(bit_length),this.p=primes[bit_length].p,this.q=primes[bit_length].q,this.g=primes[bit_length].g,this.type=KEY_TYPE,this.x=makeRandom(ZERO,this.q),this.y=BigInt.powMod(this.g,this.x,this.p),opts.nocache&&(primes[bit_length]=null)}function tokenizeStr(str){var start,end;if(start=str.indexOf("("),end=str.lastIndexOf(")"),0>start||0>end)throw new Error("Malformed S-Expression");str=str.substring(start+1,end);var splt=str.search(/\s/),obj={type:str.substring(0,splt),val:[]};if(str=str.substring(splt+1,end),start=str.indexOf("("),0>start)obj.val.push(str);else for(var i,len,ss,es;start>-1;){for(i=start+1,len=str.length,ss=1,es=0;len>i&&ss>es;i++)"("===str[i]&&ss++,")"===str[i]&&es++;obj.val.push(tokenizeStr(str.substring(start,++i))),str=str.substring(++i),start=str.indexOf("(")}return obj}function parseLibotr(obj){if(!obj.type)throw new Error("Parse error.");var o,val;return"privkeys"===obj.type?(o=[],obj.val.forEach(function(i){o.push(parseLibotr(i))}),o):(o={},obj.val.forEach(function(i){val=i.val[0],"string"==typeof val?0===val.indexOf("#")&&(val=val.substring(1,val.lastIndexOf("#")),val=BigInt.str2bigInt(val,16)):val=parseLibotr(i),o[i.type]=val}),o)}var CryptoJS,BigInt,Worker,WWPath,HLP,root=this;"undefined"!=typeof module&&module.exports?(module.exports=DSA,CryptoJS=require("../vendor/crypto.js"),BigInt=require("../vendor/bigint.js"),WWPath=require("path").join(__dirname,"/dsa-webworker.js"),HLP=require("./helpers.js")):(Object.keys(root.DSA).forEach(function(k){DSA[k]=root.DSA[k]}),root.DSA=DSA,CryptoJS=root.CryptoJS,BigInt=root.BigInt,Worker=root.Worker,WWPath="dsa-webworker.js",HLP=DSA.HLP);var ZERO=BigInt.str2bigInt("0",10),ONE=BigInt.str2bigInt("1",10),TWO=BigInt.str2bigInt("2",10),KEY_TYPE="\x00\x00",DEBUG=!1,rpprb=[],bit_lengths={1024:{N:160,repeat:40},2048:{N:224,repeat:56}},primes={};DSA.prototype={constructor:DSA,packPublic:function(){var str=this.type;return str+=HLP.packMPI(this.p),str+=HLP.packMPI(this.q),str+=HLP.packMPI(this.g),str+=HLP.packMPI(this.y)},packPrivate:function(){var str=this.packPublic()+HLP.packMPI(this.x);return str=CryptoJS.enc.Latin1.parse(str),str.toString(CryptoJS.enc.Base64)},generateNonce:function(m){var priv=BigInt.bigInt2bits(BigInt.trim(this.x,0)),rand=BigInt.bigInt2bits(BigInt.randBigInt(256)),sha256=CryptoJS.algo.SHA256.create();sha256.update(CryptoJS.enc.Latin1.parse(priv)),sha256.update(m),sha256.update(CryptoJS.enc.Latin1.parse(rand));var hash=sha256.finalize();return hash=HLP.bits2bigInt(hash.toString(CryptoJS.enc.Latin1)),BigInt.rightShift_(hash,256-BigInt.bitSize(this.q)),HLP.between(hash,ZERO,this.q)?hash:this.generateNonce(m)},sign:function(m){m=CryptoJS.enc.Latin1.parse(m);for(var k,b=BigInt.str2bigInt(m.toString(CryptoJS.enc.Hex),16),r=ZERO,s=ZERO;BigInt.isZero(s)||BigInt.isZero(r);)k=this.generateNonce(m),r=BigInt.mod(BigInt.powMod(this.g,k,this.p),this.q),BigInt.isZero(r)||(s=BigInt.inverseMod(k,this.q),s=BigInt.mult(s,BigInt.add(b,BigInt.mult(this.x,r))),s=BigInt.mod(s,this.q));return[r,s]},fingerprint:function(){var pk=this.packPublic();return this.type===KEY_TYPE&&(pk=pk.substring(2)),pk=CryptoJS.enc.Latin1.parse(pk),CryptoJS.SHA1(pk).toString(CryptoJS.enc.Hex)}},DSA.parsePublic=function(str,priv){var fields=["SHORT","MPI","MPI","MPI","MPI"];priv&&fields.push("MPI"),str=HLP.splitype(fields,str);var obj={type:str[0],p:HLP.readMPI(str[1]),q:HLP.readMPI(str[2]),g:HLP.readMPI(str[3]),y:HLP.readMPI(str[4])};return priv&&(obj.x=HLP.readMPI(str[5])),new DSA(obj)},DSA.parsePrivate=function(str,libotr){return libotr?parseLibotr(tokenizeStr(str))[0]["private-key"].dsa:(str=CryptoJS.enc.Base64.parse(str),str=str.toString(CryptoJS.enc.Latin1),DSA.parsePublic(str,!0))},DSA.verify=function(key,m,r,s){if(!HLP.between(r,ZERO,key.q)||!HLP.between(s,ZERO,key.q))return!1;var hm=CryptoJS.enc.Latin1.parse(m);hm=BigInt.str2bigInt(hm.toString(CryptoJS.enc.Hex),16);var w=BigInt.inverseMod(s,key.q),u1=BigInt.multMod(hm,w,key.q),u2=BigInt.multMod(r,w,key.q);u1=BigInt.powMod(key.g,u1,key.p),u2=BigInt.powMod(key.y,u2,key.p);var v=BigInt.mod(BigInt.multMod(u1,u2,key.p),key.q);return BigInt.equals(v,r)},DSA.createInWebWorker=function(options,cb){var opts={path:WWPath,seed:BigInt.getSeed};options&&"object"==typeof options&&Object.keys(options).forEach(function(k){opts[k]=options[k]}),"undefined"!=typeof module&&module.exports&&(Worker=require("webworker-threads").Worker);var worker=new Worker(opts.path);worker.onmessage=function(e){var data=e.data;switch(data.type){case"debug":if(!DEBUG||"undefined"==typeof console)return;console.log(data.val);break;case"data":worker.terminate(),cb(DSA.parsePrivate(data.val));break;default:throw new Error("Unrecognized type.")}},worker.postMessage({seed:opts.seed(),imports:opts.imports,debug:DEBUG})}}.call(this),function(){"use strict";var CryptoJS,CONST,HLP,root=this,Parse={};"undefined"!=typeof module&&module.exports?(module.exports=Parse,CryptoJS=require("../vendor/crypto.js"),CONST=require("./const.js"),HLP=require("./helpers.js")):(root.OTR.Parse=Parse,CryptoJS=root.CryptoJS,CONST=root.OTR.CONST,HLP=root.OTR.HLP);var tags={};tags[CONST.WHITESPACE_TAG_V2]=CONST.OTR_VERSION_2,tags[CONST.WHITESPACE_TAG_V3]=CONST.OTR_VERSION_3,Parse.parseMsg=function(otr,msg){var ver=[],start=msg.indexOf(CONST.OTR_TAG);if(!~start){if(this.initFragment(otr),ind=msg.indexOf(CONST.WHITESPACE_TAG),~ind){msg=msg.split(""),msg.splice(ind,16);for(var tag,len=msg.length;len>ind;)tag=msg.slice(ind,ind+8).join(""),Object.hasOwnProperty.call(tags,tag)?(msg.splice(ind,8),ver.push(tags[tag])):ind+=8;msg=msg.join("")}return{msg:msg,ver:ver}}var ind=start+CONST.OTR_TAG.length,com=msg[ind];if(","===com||"|"===com)return this.msgFragment(otr,msg.substring(ind+1),"|"===com);if(this.initFragment(otr),~["?","v"].indexOf(com)){"?"===msg[ind]&&(ver.push(CONST.OTR_VERSION_1),ind+=1);var vers={2:CONST.OTR_VERSION_2,3:CONST.OTR_VERSION_3},qs=msg.substring(ind+1),qi=qs.indexOf("?");return qi>=1&&(qs=qs.substring(0,qi).split(""),"v"===msg[ind]&&qs.forEach(function(q){Object.hasOwnProperty.call(vers,q)&&ver.push(vers[q])})),{cls:"query",ver:ver}}if(":"===com){ind+=1;var info=msg.substring(ind,ind+4);if(info.length<4)return{msg:msg};info=CryptoJS.enc.Base64.parse(info).toString(CryptoJS.enc.Latin1);var version=info.substring(0,2),type=info.substring(2);if(!otr["ALLOW_V"+HLP.unpackSHORT(version)])return{msg:msg};ind+=4;var end=msg.substring(ind).indexOf(".");if(!~end)return{msg:msg};msg=CryptoJS.enc.Base64.parse(msg.substring(ind,ind+end)),msg=CryptoJS.enc.Latin1.stringify(msg);var instance_tags;version===CONST.OTR_VERSION_3&&(instance_tags=msg.substring(0,8),msg=msg.substring(8));var cls;return~["","\n","",""].indexOf(type)?cls="ake":""===type&&(cls="data"),{version:version,type:type,msg:msg,cls:cls,instance_tags:instance_tags}}return" Error:"===msg.substring(ind,ind+7)?(otr.ERROR_START_AKE&&otr.sendQueryMsg(),{msg:msg.substring(ind+7),cls:"error"}):{msg:msg}},Parse.initFragment=function(otr){otr.fragment={s:"",j:0,k:0}},Parse.msgFragment=function(otr,msg,v3){if(msg=msg.split(","),v3){var its=msg.shift().split("|"),their_it=HLP.packINT(parseInt(its[0],16)),our_it=HLP.packINT(parseInt(its[1],16));if(otr.checkInstanceTags(their_it+our_it))return}if(!(msg.length<4||isNaN(parseInt(msg[0],10))||isNaN(parseInt(msg[1],10)))){var k=parseInt(msg[0],10),n=parseInt(msg[1],10);return msg=msg[2],k>n||0===n||0===k?void this.initFragment(otr):(1===k?(this.initFragment(otr),otr.fragment={k:1,n:n,s:msg}):n===otr.fragment.n&&k===otr.fragment.k+1?(otr.fragment.s+=msg,otr.fragment.k+=1):this.initFragment(otr),n===k?(msg=otr.fragment.s,this.initFragment(otr),this.parseMsg(otr,msg)):void 0)}}}.call(this),function(){"use strict";function hMac(gx,gy,pk,kid,m){var pass=CryptoJS.enc.Latin1.parse(m),hmac=CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256,pass);return hmac.update(CryptoJS.enc.Latin1.parse(HLP.packMPI(gx))),hmac.update(CryptoJS.enc.Latin1.parse(HLP.packMPI(gy))),hmac.update(CryptoJS.enc.Latin1.parse(pk)),hmac.update(CryptoJS.enc.Latin1.parse(kid)),hmac.finalize().toString(CryptoJS.enc.Latin1)}function AKE(otr){if(!(this instanceof AKE))return new AKE(otr);this.otr=otr,this.our_dh=otr.our_old_dh,this.our_keyid=otr.our_keyid-1,this.their_y=null,this.their_keyid=null,this.their_priv_pk=null,this.ssid=null,this.transmittedRS=!1,this.r=null;var self=this;["sendMsg"].forEach(function(meth){self[meth]=self[meth].bind(self)})}var CryptoJS,BigInt,CONST,HLP,DSA,root=this;"undefined"!=typeof module&&module.exports?(module.exports=AKE,CryptoJS=require("../vendor/crypto.js"),BigInt=require("../vendor/bigint.js"),CONST=require("./const.js"),HLP=require("./helpers.js"),DSA=require("./dsa.js")):(root.OTR.AKE=AKE,CryptoJS=root.CryptoJS,BigInt=root.BigInt,CONST=root.OTR.CONST,HLP=root.OTR.HLP,DSA=root.DSA);var N=BigInt.str2bigInt(CONST.N,16),N_MINUS_2=BigInt.sub(N,BigInt.str2bigInt("2",10));AKE.prototype={constructor:AKE,createKeys:function(g){var s=BigInt.powMod(g,this.our_dh.privateKey,N),secbytes=HLP.packMPI(s);this.ssid=HLP.mask(HLP.h2("\x00",secbytes),0,64);var tmp=HLP.h2("",secbytes);this.c=HLP.mask(tmp,0,128),this.c_prime=HLP.mask(tmp,128,128),this.m1=HLP.h2("",secbytes),this.m2=HLP.h2("",secbytes),this.m1_prime=HLP.h2("",secbytes),this.m2_prime=HLP.h2("",secbytes)},verifySignMac:function(mac,aesctr,m2,c,their_y,our_dh_pk,m1,ctr){var vmac=HLP.makeMac(aesctr,m2);if(!HLP.compare(mac,vmac))return["MACs do not match."];var x=HLP.decryptAes(aesctr.substring(4),c,ctr);x=HLP.splitype(["PUBKEY","INT","SIG"],x.toString(CryptoJS.enc.Latin1));var m=hMac(their_y,our_dh_pk,x[0],x[1],m1),pub=DSA.parsePublic(x[0]),r=HLP.bits2bigInt(x[2].substring(0,20)),s=HLP.bits2bigInt(x[2].substring(20));return DSA.verify(pub,m,r,s)?[null,HLP.readLen(x[1]),pub]:["Cannot verify signature of m."]},makeM:function(their_y,m1,c,m2){var pk=this.otr.priv.packPublic(),kid=HLP.packINT(this.our_keyid),m=hMac(this.our_dh.publicKey,their_y,pk,kid,m1);m=this.otr.priv.sign(m);var msg=pk+kid;msg+=BigInt.bigInt2bits(m[0],20),msg+=BigInt.bigInt2bits(m[1],20),msg=CryptoJS.enc.Latin1.parse(msg);var aesctr=HLP.packData(HLP.encryptAes(msg,c,HLP.packCtr(0))),mac=HLP.makeMac(aesctr,m2);return aesctr+mac},akeSuccess:function(version){return HLP.debug.call(this.otr,"success"),BigInt.equals(this.their_y,this.our_dh.publicKey)?this.otr.error("equal keys - we have a problem.",!0):(this.otr.our_old_dh=this.our_dh,this.otr.their_priv_pk=this.their_priv_pk,this.their_keyid===this.otr.their_keyid&&BigInt.equals(this.their_y,this.otr.their_y)||this.their_keyid===this.otr.their_keyid-1&&BigInt.equals(this.their_y,this.otr.their_old_y)||(this.otr.their_y=this.their_y,this.otr.their_old_y=null,this.otr.their_keyid=this.their_keyid,this.otr.sessKeys[0]=[new this.otr.DHSession(this.otr.our_dh,this.otr.their_y),null],this.otr.sessKeys[1]=[new this.otr.DHSession(this.otr.our_old_dh,this.otr.their_y),null]),this.otr.ssid=this.ssid,this.otr.transmittedRS=this.transmittedRS,this.otr_version=version,this.otr.authstate=CONST.AUTHSTATE_NONE,this.otr.msgstate=CONST.MSGSTATE_ENCRYPTED,this.r=null,this.myhashed=null,this.dhcommit=null,this.encrypted=null,this.hashed=null,this.otr.trigger("status",[CONST.STATUS_AKE_SUCCESS]),void this.otr.sendStored())},handleAKE:function(msg){var send,vsm,type,version=msg.version;switch(msg.type){case"":if(HLP.debug.call(this.otr,"d-h key message"),msg=HLP.splitype(["DATA","DATA"],msg.msg),this.otr.authstate===CONST.AUTHSTATE_AWAITING_DHKEY){var ourHash=HLP.readMPI(this.myhashed),theirHash=HLP.readMPI(msg[1]);if(BigInt.greater(ourHash,theirHash)){type="",send=this.dhcommit;break}this.our_dh=this.otr.dh(),this.otr.authstate=CONST.AUTHSTATE_NONE,this.r=null,this.myhashed=null}else this.otr.authstate===CONST.AUTHSTATE_AWAITING_SIG&&(this.our_dh=this.otr.dh());this.otr.authstate=CONST.AUTHSTATE_AWAITING_REVEALSIG,this.encrypted=msg[0].substring(4),this.hashed=msg[1].substring(4),type="\n",send=HLP.packMPI(this.our_dh.publicKey);break;case"\n":if(HLP.debug.call(this.otr,"reveal signature message"),msg=HLP.splitype(["MPI"],msg.msg),this.otr.authstate!==CONST.AUTHSTATE_AWAITING_DHKEY){if(this.otr.authstate!==CONST.AUTHSTATE_AWAITING_SIG)return;if(!BigInt.equals(this.their_y,HLP.readMPI(msg[0])))return}if(this.otr.authstate=CONST.AUTHSTATE_AWAITING_SIG,this.their_y=HLP.readMPI(msg[0]),!HLP.checkGroup(this.their_y,N_MINUS_2))return this.otr.error("Illegal g^y.",!0);this.createKeys(this.their_y),type="",send=HLP.packMPI(this.r),send+=this.makeM(this.their_y,this.m1,this.c,this.m2),this.m1=null,this.m2=null,this.c=null;break;case"":if(HLP.debug.call(this.otr,"signature message"),this.otr.authstate!==CONST.AUTHSTATE_AWAITING_REVEALSIG)return;msg=HLP.splitype(["DATA","DATA","MAC"],msg.msg),this.r=HLP.readMPI(msg[0]);var key=CryptoJS.enc.Hex.parse(BigInt.bigInt2str(this.r,16));key=CryptoJS.enc.Latin1.stringify(key);var gxmpi=HLP.decryptAes(this.encrypted,key,HLP.packCtr(0));gxmpi=gxmpi.toString(CryptoJS.enc.Latin1),this.their_y=HLP.readMPI(gxmpi);var hash=CryptoJS.SHA256(CryptoJS.enc.Latin1.parse(gxmpi));return HLP.compare(this.hashed,hash.toString(CryptoJS.enc.Latin1))?HLP.checkGroup(this.their_y,N_MINUS_2)?(this.createKeys(this.their_y),vsm=this.verifySignMac(msg[2],msg[1],this.m2,this.c,this.their_y,this.our_dh.publicKey,this.m1,HLP.packCtr(0)),vsm[0]?this.otr.error(vsm[0],!0):(this.their_keyid=vsm[1],this.their_priv_pk=vsm[2],send=this.makeM(this.their_y,this.m1_prime,this.c_prime,this.m2_prime),this.m1=null,this.m2=null,this.m1_prime=null,this.m2_prime=null,this.c=null,this.c_prime=null,this.sendMsg(version,"",send),void this.akeSuccess(version))):this.otr.error("Illegal g^x.",!0):this.otr.error("Hashed g^x does not match.",!0);case"":if(HLP.debug.call(this.otr,"data message"),this.otr.authstate!==CONST.AUTHSTATE_AWAITING_SIG)return;return msg=HLP.splitype(["DATA","MAC"],msg.msg),vsm=this.verifySignMac(msg[1],msg[0],this.m2_prime,this.c_prime,this.their_y,this.our_dh.publicKey,this.m1_prime,HLP.packCtr(0)),vsm[0]?this.otr.error(vsm[0],!0):(this.their_keyid=vsm[1],this.their_priv_pk=vsm[2],this.m1_prime=null,this.m2_prime=null,this.c_prime=null,this.transmittedRS=!0,void this.akeSuccess(version));default:return}this.sendMsg(version,type,send)},sendMsg:function(version,type,msg){var send=version+type,v3=version===CONST.OTR_VERSION_3;return v3&&(HLP.debug.call(this.otr,"instance tags"),send+=this.otr.our_instance_tag,send+=this.otr.their_instance_tag),send+=msg,send=HLP.wrapMsg(send,this.otr.fragment_size,v3,this.otr.our_instance_tag,this.otr.their_instance_tag),send[0]?this.otr.error(send[0]):void this.otr.io(send[1])},initiateAKE:function(version){HLP.debug.call(this.otr,"d-h commit message"),this.otr.trigger("status",[CONST.STATUS_AKE_INIT]),this.otr.authstate=CONST.AUTHSTATE_AWAITING_DHKEY;var gxmpi=HLP.packMPI(this.our_dh.publicKey);gxmpi=CryptoJS.enc.Latin1.parse(gxmpi),this.r=BigInt.randBigInt(128);var key=CryptoJS.enc.Hex.parse(BigInt.bigInt2str(this.r,16));key=CryptoJS.enc.Latin1.stringify(key),this.myhashed=CryptoJS.SHA256(gxmpi),this.myhashed=HLP.packData(this.myhashed.toString(CryptoJS.enc.Latin1)),this.dhcommit=HLP.packData(HLP.encryptAes(gxmpi,key,HLP.packCtr(0))),this.dhcommit+=this.myhashed,this.sendMsg(version,"",this.dhcommit)}}}.call(this),function(){"use strict";function SM(reqs){return this instanceof SM?(this.version=1,this.our_fp=reqs.our_fp,this.their_fp=reqs.their_fp,this.ssid=reqs.ssid,this.debug=!!reqs.debug,void this.init()):new SM(reqs)}var CryptoJS,BigInt,EventEmitter,CONST,HLP,root=this;"undefined"!=typeof module&&module.exports?(module.exports=SM,CryptoJS=require("../vendor/crypto.js"),BigInt=require("../vendor/bigint.js"),EventEmitter=require("../vendor/eventemitter.js"),CONST=require("./const.js"),HLP=require("./helpers.js")):(root.OTR.SM=SM,CryptoJS=root.CryptoJS,BigInt=root.BigInt,EventEmitter=root.EventEmitter,CONST=root.OTR.CONST,HLP=root.OTR.HLP);var G=BigInt.str2bigInt(CONST.G,10),N=BigInt.str2bigInt(CONST.N,16),N_MINUS_2=BigInt.sub(N,BigInt.str2bigInt("2",10)),Q=BigInt.sub(N,BigInt.str2bigInt("1",10));BigInt.divInt_(Q,2),HLP.extend(SM,EventEmitter),SM.prototype.init=function(){this.smpstate=CONST.SMPSTATE_EXPECT1,this.secret=null},SM.prototype.makeSecret=function(our,secret){var sha256=CryptoJS.algo.SHA256.create();sha256.update(CryptoJS.enc.Latin1.parse(HLP.packBytes(this.version,1))),sha256.update(CryptoJS.enc.Hex.parse(our?this.our_fp:this.their_fp)),sha256.update(CryptoJS.enc.Hex.parse(our?this.their_fp:this.our_fp)),sha256.update(CryptoJS.enc.Latin1.parse(this.ssid)),sha256.update(CryptoJS.enc.Latin1.parse(secret));var hash=sha256.finalize();this.secret=HLP.bits2bigInt(hash.toString(CryptoJS.enc.Latin1))},SM.prototype.makeG2s=function(){this.a2=HLP.randomExponent(),this.a3=HLP.randomExponent(),this.g2a=BigInt.powMod(G,this.a2,N),this.g3a=BigInt.powMod(G,this.a3,N),HLP.checkGroup(this.g2a,N_MINUS_2)&&HLP.checkGroup(this.g3a,N_MINUS_2)||this.makeG2s()},SM.prototype.computeGs=function(g2a,g3a){this.g2=BigInt.powMod(g2a,this.a2,N),this.g3=BigInt.powMod(g3a,this.a3,N)},SM.prototype.computePQ=function(r){this.p=BigInt.powMod(this.g3,r,N),this.q=HLP.multPowMod(G,r,this.g2,this.secret,N)},SM.prototype.computeR=function(){this.r=BigInt.powMod(this.QoQ,this.a3,N)},SM.prototype.computeRab=function(r){return BigInt.powMod(r,this.a3,N)},SM.prototype.computeC=function(v,r){return HLP.smpHash(v,BigInt.powMod(G,r,N))},SM.prototype.computeD=function(r,a,c){return BigInt.subMod(r,BigInt.multMod(a,c,Q),Q)},SM.prototype.handleSM=function(msg){var send,r2,r3,r7,t1,t2,t3,t4,rab,tmp2,cR,d7,ms,trust,expectStates={2:CONST.SMPSTATE_EXPECT1,3:CONST.SMPSTATE_EXPECT2,4:CONST.SMPSTATE_EXPECT3,5:CONST.SMPSTATE_EXPECT4,7:CONST.SMPSTATE_EXPECT1};if(6===msg.type)return this.init(),void this.trigger("abort");if(this.smpstate!==expectStates[msg.type])return this.abort();switch(this.smpstate){case CONST.SMPSTATE_EXPECT1:HLP.debug.call(this,"smp tlv 2");var ind,question;return 7===msg.type&&(ind=msg.msg.indexOf("\x00"),question=msg.msg.substring(0,ind),msg.msg=msg.msg.substring(ind+1)),ms=HLP.readLen(msg.msg.substr(0,4)),6!==ms?this.abort():(msg=HLP.unpackMPIs(6,msg.msg.substring(4)),HLP.checkGroup(msg[0],N_MINUS_2)&&HLP.checkGroup(msg[3],N_MINUS_2)&&HLP.ZKP(1,msg[1],HLP.multPowMod(G,msg[2],msg[0],msg[1],N))&&HLP.ZKP(2,msg[4],HLP.multPowMod(G,msg[5],msg[3],msg[4],N))?(this.g3ao=msg[3],this.makeG2s(),r2=HLP.randomExponent(),r3=HLP.randomExponent(),this.c2=this.computeC(3,r2),this.c3=this.computeC(4,r3),this.d2=this.computeD(r2,this.a2,this.c2),this.d3=this.computeD(r3,this.a3,this.c3),this.computeGs(msg[0],msg[3]),this.smpstate=CONST.SMPSTATE_EXPECT0,question=CryptoJS.enc.Latin1.parse(question).toString(CryptoJS.enc.Utf8),void this.trigger("question",[question])):this.abort());case CONST.SMPSTATE_EXPECT2:if(HLP.debug.call(this,"smp tlv 3"),ms=HLP.readLen(msg.msg.substr(0,4)),11!==ms)return this.abort();if(msg=HLP.unpackMPIs(11,msg.msg.substring(4)),!(HLP.checkGroup(msg[0],N_MINUS_2)&&HLP.checkGroup(msg[3],N_MINUS_2)&&HLP.checkGroup(msg[6],N_MINUS_2)&&HLP.checkGroup(msg[7],N_MINUS_2)))return this.abort();if(!HLP.ZKP(3,msg[1],HLP.multPowMod(G,msg[2],msg[0],msg[1],N)))return this.abort();if(!HLP.ZKP(4,msg[4],HLP.multPowMod(G,msg[5],msg[3],msg[4],N)))return this.abort();if(this.g3ao=msg[3],this.computeGs(msg[0],msg[3]),t1=HLP.multPowMod(this.g3,msg[9],msg[6],msg[8],N),t2=HLP.multPowMod(G,msg[9],this.g2,msg[10],N),t2=BigInt.multMod(t2,BigInt.powMod(msg[7],msg[8],N),N),!HLP.ZKP(5,msg[8],t1,t2))return this.abort();var r4=HLP.randomExponent();this.computePQ(r4);var r5=HLP.randomExponent(),r6=HLP.randomExponent(),tmp=HLP.multPowMod(G,r5,this.g2,r6,N),cP=HLP.smpHash(6,BigInt.powMod(this.g3,r5,N),tmp),d5=this.computeD(r5,r4,cP),d6=this.computeD(r6,this.secret,cP);this.QoQ=BigInt.divMod(this.q,msg[7],N),this.PoP=BigInt.divMod(this.p,msg[6],N),this.computeR(),r7=HLP.randomExponent(),tmp2=BigInt.powMod(this.QoQ,r7,N),cR=HLP.smpHash(7,BigInt.powMod(G,r7,N),tmp2),d7=this.computeD(r7,this.a3,cR),this.smpstate=CONST.SMPSTATE_EXPECT4,send=HLP.packINT(8)+HLP.packMPIs([this.p,this.q,cP,d5,d6,this.r,cR,d7]),send=HLP.packTLV(4,send);break;case CONST.SMPSTATE_EXPECT3:if(HLP.debug.call(this,"smp tlv 4"),ms=HLP.readLen(msg.msg.substr(0,4)),8!==ms)return this.abort();if(msg=HLP.unpackMPIs(8,msg.msg.substring(4)),!HLP.checkGroup(msg[0],N_MINUS_2)||!HLP.checkGroup(msg[1],N_MINUS_2)||!HLP.checkGroup(msg[5],N_MINUS_2))return this.abort();if(t1=HLP.multPowMod(this.g3,msg[3],msg[0],msg[2],N),t2=HLP.multPowMod(G,msg[3],this.g2,msg[4],N),t2=BigInt.multMod(t2,BigInt.powMod(msg[1],msg[2],N),N),!HLP.ZKP(6,msg[2],t1,t2))return this.abort();if(t3=HLP.multPowMod(G,msg[7],this.g3ao,msg[6],N),this.QoQ=BigInt.divMod(msg[1],this.q,N),t4=HLP.multPowMod(this.QoQ,msg[7],msg[5],msg[6],N),!HLP.ZKP(7,msg[6],t3,t4))return this.abort();this.computeR(),r7=HLP.randomExponent(),tmp2=BigInt.powMod(this.QoQ,r7,N),cR=HLP.smpHash(8,BigInt.powMod(G,r7,N),tmp2),d7=this.computeD(r7,this.a3,cR),send=HLP.packINT(3)+HLP.packMPIs([this.r,cR,d7]),send=HLP.packTLV(5,send),rab=this.computeRab(msg[5]),trust=!!BigInt.equals(rab,BigInt.divMod(msg[0],this.p,N)),this.trigger("trust",[trust,"answered"]),this.init();break;case CONST.SMPSTATE_EXPECT4:return HLP.debug.call(this,"smp tlv 5"),ms=HLP.readLen(msg.msg.substr(0,4)),3!==ms?this.abort():(msg=HLP.unpackMPIs(3,msg.msg.substring(4)),HLP.checkGroup(msg[0],N_MINUS_2)?(t3=HLP.multPowMod(G,msg[2],this.g3ao,msg[1],N),t4=HLP.multPowMod(this.QoQ,msg[2],msg[0],msg[1],N),HLP.ZKP(8,msg[1],t3,t4)?(rab=this.computeRab(msg[0]),trust=!!BigInt.equals(rab,this.PoP),this.trigger("trust",[trust,"asked"]),void this.init()):this.abort()):this.abort())}this.sendMsg(send)},SM.prototype.sendMsg=function(send){this.trigger("send",[this.ssid,"\x00"+send])},SM.prototype.rcvSecret=function(secret,question){HLP.debug.call(this,"receive secret");var fn,our=!1;this.smpstate===CONST.SMPSTATE_EXPECT0?fn=this.answer:(fn=this.initiate,our=!0),this.makeSecret(our,secret),fn.call(this,question)},SM.prototype.answer=function(){HLP.debug.call(this,"smp answer");var r4=HLP.randomExponent();this.computePQ(r4);var r5=HLP.randomExponent(),r6=HLP.randomExponent(),tmp=HLP.multPowMod(G,r5,this.g2,r6,N),cP=HLP.smpHash(5,BigInt.powMod(this.g3,r5,N),tmp),d5=this.computeD(r5,r4,cP),d6=this.computeD(r6,this.secret,cP);this.smpstate=CONST.SMPSTATE_EXPECT3;var send=HLP.packINT(11)+HLP.packMPIs([this.g2a,this.c2,this.d2,this.g3a,this.c3,this.d3,this.p,this.q,cP,d5,d6]);this.sendMsg(HLP.packTLV(3,send))
+},SM.prototype.initiate=function(question){HLP.debug.call(this,"smp initiate"),this.smpstate!==CONST.SMPSTATE_EXPECT1&&this.abort(),this.makeG2s();var r2=HLP.randomExponent(),r3=HLP.randomExponent();this.c2=this.computeC(1,r2),this.c3=this.computeC(2,r3),this.d2=this.computeD(r2,this.a2,this.c2),this.d3=this.computeD(r3,this.a3,this.c3),this.smpstate=CONST.SMPSTATE_EXPECT2;var send="",type=2;question&&(send+=question,send+="\x00",type=7),send+=HLP.packINT(6)+HLP.packMPIs([this.g2a,this.c2,this.d2,this.g3a,this.c3,this.d3]),this.sendMsg(HLP.packTLV(type,send))},SM.prototype.abort=function(){this.init(),this.sendMsg(HLP.packTLV(6,"")),this.trigger("abort")}}.call(this),function(){"use strict";function OTR(options){if(!(this instanceof OTR))return new OTR(options);if(options=options||{},options.priv&&!(options.priv instanceof DSA))throw new Error("Requires long-lived DSA key.");if(this.priv=options.priv?options.priv:new DSA,this.fragment_size=options.fragment_size||0,this.fragment_size<0)throw new Error("Fragment size must be a positive integer.");if(this.send_interval=options.send_interval||0,this.send_interval<0)throw new Error("Send interval must be a positive integer.");this.outgoing=[],this.our_instance_tag=options.instance_tag||OTR.makeInstanceTag(),this.debug=!!options.debug,this.smw=options.smw,this.init();var self=this;["sendMsg","receiveMsg"].forEach(function(meth){self[meth]=self[meth].bind(self)}),EventEmitter.call(this)}var CryptoJS,BigInt,EventEmitter,Worker,SMWPath,CONST,HLP,Parse,AKE,SM,DSA,root=this;"undefined"!=typeof module&&module.exports?(module.exports=OTR,CryptoJS=require("../vendor/crypto.js"),BigInt=require("../vendor/bigint.js"),EventEmitter=require("../vendor/eventemitter.js"),SMWPath=require("path").join(__dirname,"/sm-webworker.js"),CONST=require("./const.js"),HLP=require("./helpers.js"),Parse=require("./parse.js"),AKE=require("./ake.js"),SM=require("./sm.js"),DSA=require("./dsa.js"),OTR.CONST=CONST):(Object.keys(root.OTR).forEach(function(k){OTR[k]=root.OTR[k]}),root.OTR=OTR,CryptoJS=root.CryptoJS,BigInt=root.BigInt,EventEmitter=root.EventEmitter,Worker=root.Worker,SMWPath="sm-webworker.js",CONST=OTR.CONST,HLP=OTR.HLP,Parse=OTR.Parse,AKE=OTR.AKE,SM=OTR.SM,DSA=root.DSA);var G=BigInt.str2bigInt(CONST.G,10),N=BigInt.str2bigInt(CONST.N,16),MAX_INT=Math.pow(2,53)-1,MAX_UINT=Math.pow(2,31)-1;HLP.extend(OTR,EventEmitter),OTR.prototype.init=function(){this.msgstate=CONST.MSGSTATE_PLAINTEXT,this.authstate=CONST.AUTHSTATE_NONE,this.ALLOW_V2=!0,this.ALLOW_V3=!0,this.REQUIRE_ENCRYPTION=!1,this.SEND_WHITESPACE_TAG=!1,this.WHITESPACE_START_AKE=!1,this.ERROR_START_AKE=!1,Parse.initFragment(this),this.their_y=null,this.their_old_y=null,this.their_keyid=0,this.their_priv_pk=null,this.their_instance_tag="\x00\x00\x00\x00",this.our_dh=this.dh(),this.our_old_dh=this.dh(),this.our_keyid=2,this.sessKeys=[new Array(2),new Array(2)],this.storedMgs=[],this.oldMacKeys=[],this.sm=null,this._akeInit(),this.receivedPlaintext=!1},OTR.prototype._akeInit=function(){this.ake=new AKE(this),this.transmittedRS=!1,this.ssid=null},OTR.prototype._SMW=function(otr,reqs){this.otr=otr;var opts={path:SMWPath,seed:BigInt.getSeed};"object"==typeof otr.smw&&Object.keys(otr.smw).forEach(function(k){opts[k]=otr.smw[k]}),"undefined"!=typeof module&&module.exports&&(Worker=require("webworker-threads").Worker),this.worker=new Worker(opts.path);var self=this;this.worker.onmessage=function(e){var d=e.data;d&&self.trigger(d.method,d.args)},this.worker.postMessage({type:"seed",seed:opts.seed(),imports:opts.imports}),this.worker.postMessage({type:"init",reqs:reqs})},HLP.extend(OTR.prototype._SMW,EventEmitter),["handleSM","rcvSecret","abort"].forEach(function(m){OTR.prototype._SMW.prototype[m]=function(){this.worker.postMessage({type:"method",method:m,args:Array.prototype.slice.call(arguments,0)})}}),OTR.prototype._smInit=function(){var reqs={ssid:this.ssid,our_fp:this.priv.fingerprint(),their_fp:this.their_priv_pk.fingerprint(),debug:this.debug};this.smw?(this.sm&&this.sm.worker.terminate(),this.sm=new this._SMW(this,reqs)):this.sm=new SM(reqs);var self=this;["trust","abort","question"].forEach(function(e){self.sm.on(e,function(){self.trigger("smp",[e].concat(Array.prototype.slice.call(arguments)))})}),this.sm.on("send",function(ssid,send){self.ssid===ssid&&(send=self.prepareMsg(send),self.io(send))})},OTR.prototype.io=function(msg,meta){msg=[].concat(msg).map(function(m){return{msg:m,meta:meta}}),this.outgoing=this.outgoing.concat(msg);var self=this;!function send(first){if(!first){if(!self.outgoing.length)return;var elem=self.outgoing.shift();self.trigger("io",[elem.msg,elem.meta])}setTimeout(send,first?0:self.send_interval)}(!0)},OTR.prototype.dh=function(){var keys={privateKey:BigInt.randBigInt(320)};return keys.publicKey=BigInt.powMod(G,keys.privateKey,N),keys},OTR.prototype.DHSession=function DHSession(our_dh,their_y){if(!(this instanceof DHSession))return new DHSession(our_dh,their_y);var s=BigInt.powMod(their_y,our_dh.privateKey,N),secbytes=HLP.packMPI(s);this.id=HLP.mask(HLP.h2("\x00",secbytes),0,64);var sq=BigInt.greater(our_dh.publicKey,their_y),sendbyte=sq?"":"",rcvbyte=sq?"":"";this.sendenc=HLP.mask(HLP.h1(sendbyte,secbytes),0,128),this.sendmac=CryptoJS.SHA1(CryptoJS.enc.Latin1.parse(this.sendenc)),this.sendmac=this.sendmac.toString(CryptoJS.enc.Latin1),this.rcvenc=HLP.mask(HLP.h1(rcvbyte,secbytes),0,128),this.rcvmac=CryptoJS.SHA1(CryptoJS.enc.Latin1.parse(this.rcvenc)),this.rcvmac=this.rcvmac.toString(CryptoJS.enc.Latin1),this.rcvmacused=!1,this.extra_symkey=HLP.h2("ÿ",secbytes),this.send_counter=0,this.rcv_counter=0},OTR.prototype.rotateOurKeys=function(){var self=this;this.sessKeys[1].forEach(function(sk){sk&&sk.rcvmacused&&self.oldMacKeys.push(sk.rcvmac)}),this.our_old_dh=this.our_dh,this.our_dh=this.dh(),this.our_keyid+=1,this.sessKeys[1][0]=this.sessKeys[0][0],this.sessKeys[1][1]=this.sessKeys[0][1],this.sessKeys[0]=[this.their_y?new this.DHSession(this.our_dh,this.their_y):null,this.their_old_y?new this.DHSession(this.our_dh,this.their_old_y):null]},OTR.prototype.rotateTheirKeys=function(their_y){this.their_keyid+=1;var self=this;this.sessKeys.forEach(function(sk){sk[1]&&sk[1].rcvmacused&&self.oldMacKeys.push(sk[1].rcvmac)}),this.their_old_y=this.their_y,this.sessKeys[0][1]=this.sessKeys[0][0],this.sessKeys[1][1]=this.sessKeys[1][0],this.their_y=their_y,this.sessKeys[0][0]=new this.DHSession(this.our_dh,this.their_y),this.sessKeys[1][0]=new this.DHSession(this.our_old_dh,this.their_y)},OTR.prototype.prepareMsg=function(msg,esk){if(this.msgstate!==CONST.MSGSTATE_ENCRYPTED||0===this.their_keyid)return this.error("Not ready to encrypt.");var sessKeys=this.sessKeys[1][0];if(sessKeys.send_counter>=MAX_INT)return this.error("Should have rekeyed by now.");sessKeys.send_counter+=1;var ctr=HLP.packCtr(sessKeys.send_counter),send=this.ake.otr_version+"",v3=this.ake.otr_version===CONST.OTR_VERSION_3;if(v3&&(send+=this.our_instance_tag,send+=this.their_instance_tag),send+="\x00",send+=HLP.packINT(this.our_keyid-1),send+=HLP.packINT(this.their_keyid),send+=HLP.packMPI(this.our_dh.publicKey),send+=ctr.substring(0,8),Math.ceil(msg.length/8)>=MAX_UINT)return this.error("Message is too long.");var aes=HLP.encryptAes(CryptoJS.enc.Latin1.parse(msg),sessKeys.sendenc,ctr);return send+=HLP.packData(aes),send+=HLP.make1Mac(send,sessKeys.sendmac),send+=HLP.packData(this.oldMacKeys.splice(0).join("")),send=HLP.wrapMsg(send,this.fragment_size,v3,this.our_instance_tag,this.their_instance_tag),send[0]?this.error(send[0]):(esk&&this.trigger("file",["send",sessKeys.extra_symkey,esk]),send[1])},OTR.prototype.handleDataMsg=function(msg){var vt=msg.version+msg.type;this.ake.otr_version===CONST.OTR_VERSION_3&&(vt+=msg.instance_tags);var types=["BYTE","INT","INT","MPI","CTR","DATA","MAC","DATA"];msg=HLP.splitype(types,msg.msg);var ign=""===msg[0];if(this.msgstate!==CONST.MSGSTATE_ENCRYPTED||8!==msg.length)return void(ign||this.error("Received an unreadable encrypted message.",!0));var our_keyid=this.our_keyid-HLP.readLen(msg[2]),their_keyid=this.their_keyid-HLP.readLen(msg[1]);if(0>our_keyid||our_keyid>1)return void(ign||this.error("Not of our latest keys.",!0));if(0>their_keyid||their_keyid>1)return void(ign||this.error("Not of your latest keys.",!0));var their_y=their_keyid?this.their_old_y:this.their_y;if(1===their_keyid&&!their_y)return void(ign||this.error("Do not have that key."));var sessKeys=this.sessKeys[our_keyid][their_keyid],ctr=HLP.unpackCtr(msg[4]);if(ctr<=sessKeys.rcv_counter)return void(ign||this.error("Counter in message is not larger."));sessKeys.rcv_counter=ctr,vt+=msg.slice(0,6).join("");var vmac=HLP.make1Mac(vt,sessKeys.rcvmac);if(!HLP.compare(msg[6],vmac))return void(ign||this.error("MACs do not match."));sessKeys.rcvmacused=!0;var out=HLP.decryptAes(msg[5].substring(4),sessKeys.rcvenc,HLP.padCtr(msg[4]));out=out.toString(CryptoJS.enc.Latin1),our_keyid||this.rotateOurKeys(),their_keyid||this.rotateTheirKeys(HLP.readMPI(msg[3]));var ind=out.indexOf("\x00");return~ind&&(this.handleTLVs(out.substring(ind+1),sessKeys),out=out.substring(0,ind)),out=CryptoJS.enc.Latin1.parse(out),out.toString(CryptoJS.enc.Utf8)},OTR.prototype.handleTLVs=function(tlvs,sessKeys){for(var type,len,msg;tlvs.length&&(type=HLP.unpackSHORT(tlvs.substr(0,2)),len=HLP.unpackSHORT(tlvs.substr(2,2)),msg=tlvs.substr(4,len),!(msg.length<len));){switch(type){case 1:this.msgstate=CONST.MSGSTATE_FINISHED,this.trigger("status",[CONST.STATUS_END_OTR]);break;case 2:case 3:case 4:case 5:case 6:case 7:if(this.msgstate!==CONST.MSGSTATE_ENCRYPTED)return void(this.sm&&this.sm.abort());this.sm||this._smInit(),this.sm.handleSM({msg:msg,type:type});break;case 8:msg=msg.substring(4),msg=CryptoJS.enc.Latin1.parse(msg),msg=msg.toString(CryptoJS.enc.Utf8),this.trigger("file",["receive",sessKeys.extra_symkey,msg])}tlvs=tlvs.substring(4+len)}},OTR.prototype.smpSecret=function(secret,question){return this.msgstate!==CONST.MSGSTATE_ENCRYPTED?this.error("Must be encrypted for SMP."):"string"!=typeof secret||secret.length<1?this.error("Secret is required."):(this.sm||this._smInit(),secret=CryptoJS.enc.Utf8.parse(secret).toString(CryptoJS.enc.Latin1),question=CryptoJS.enc.Utf8.parse(question).toString(CryptoJS.enc.Latin1),void this.sm.rcvSecret(secret,question))},OTR.prototype.sendQueryMsg=function(){var versions={},msg=CONST.OTR_TAG;this.ALLOW_V2&&(versions[2]=!0),this.ALLOW_V3&&(versions[3]=!0);var vs=Object.keys(versions);vs.length&&(msg+="v",vs.forEach(function(v){"1"!==v&&(msg+=v)}),msg+="?"),this.io(msg),this.trigger("status",[CONST.STATUS_SEND_QUERY])},OTR.prototype.sendMsg=function(msg,meta){switch((this.REQUIRE_ENCRYPTION||this.msgstate!==CONST.MSGSTATE_PLAINTEXT)&&(msg=CryptoJS.enc.Utf8.parse(msg),msg=msg.toString(CryptoJS.enc.Latin1)),this.msgstate){case CONST.MSGSTATE_PLAINTEXT:if(this.REQUIRE_ENCRYPTION)return this.storedMgs.push({msg:msg,meta:meta}),void this.sendQueryMsg();this.SEND_WHITESPACE_TAG&&!this.receivedPlaintext&&(msg+=CONST.WHITESPACE_TAG,this.ALLOW_V3&&(msg+=CONST.WHITESPACE_TAG_V3),this.ALLOW_V2&&(msg+=CONST.WHITESPACE_TAG_V2));break;case CONST.MSGSTATE_FINISHED:return this.storedMgs.push({msg:msg,meta:meta}),void this.error("Message cannot be sent at this time.");case CONST.MSGSTATE_ENCRYPTED:msg=this.prepareMsg(msg);break;default:throw new Error("Unknown message state.")}msg&&this.io(msg,meta)},OTR.prototype.receiveMsg=function(msg){if(msg=Parse.parseMsg(this,msg)){switch(msg.cls){case"error":return void this.error(msg.msg);case"ake":if(msg.version===CONST.OTR_VERSION_3&&this.checkInstanceTags(msg.instance_tags))return;return void this.ake.handleAKE(msg);case"data":if(msg.version===CONST.OTR_VERSION_3&&this.checkInstanceTags(msg.instance_tags))return;msg.msg=this.handleDataMsg(msg),msg.encrypted=!0;break;case"query":this.msgstate===CONST.MSGSTATE_ENCRYPTED&&this._akeInit(),this.doAKE(msg);break;default:(this.REQUIRE_ENCRYPTION||this.msgstate!==CONST.MSGSTATE_PLAINTEXT)&&this.error("Received an unencrypted message."),this.receivedPlaintext=!0,this.WHITESPACE_START_AKE&&msg.ver.length>0&&this.doAKE(msg)}msg.msg&&this.trigger("ui",[msg.msg,!!msg.encrypted])}},OTR.prototype.checkInstanceTags=function(it){var their_it=HLP.readLen(it.substr(0,4)),our_it=HLP.readLen(it.substr(4,4));if(our_it&&our_it!==HLP.readLen(this.our_instance_tag))return!0;if(HLP.readLen(this.their_instance_tag)){if(HLP.readLen(this.their_instance_tag)!==their_it)return!0}else{if(100>their_it)return!0;this.their_instance_tag=HLP.packINT(their_it)}},OTR.prototype.doAKE=function(msg){this.ALLOW_V3&&~msg.ver.indexOf(CONST.OTR_VERSION_3)?this.ake.initiateAKE(CONST.OTR_VERSION_3):this.ALLOW_V2&&~msg.ver.indexOf(CONST.OTR_VERSION_2)?this.ake.initiateAKE(CONST.OTR_VERSION_2):this.error("OTR conversation requested, but no compatible protocol version found.")},OTR.prototype.error=function(err,send){return send?(this.debug||(err="An OTR error has occurred."),err="?OTR Error:"+err,void this.io(err)):void this.trigger("error",[err])},OTR.prototype.sendStored=function(){var self=this;this.storedMgs.splice(0).forEach(function(elem){var msg=self.prepareMsg(elem.msg);self.io(msg,elem.meta)})},OTR.prototype.sendFile=function(filename){if(this.msgstate!==CONST.MSGSTATE_ENCRYPTED)return this.error("Not ready to encrypt.");if(this.ake.otr_version!==CONST.OTR_VERSION_3)return this.error("Protocol v3 required.");if(!filename)return this.error("Please specify a filename.");var l1name=CryptoJS.enc.Utf8.parse(filename);if(l1name=l1name.toString(CryptoJS.enc.Latin1),l1name.length>=65532)return this.error("filename is too long.");var msg="\x00";msg+="\x00\b",msg+=HLP.packSHORT(4+l1name.length),msg+="\x00\x00\x00",msg+=l1name,msg=this.prepareMsg(msg,filename),this.io(msg)},OTR.prototype.endOtr=function(){this.msgstate===CONST.MSGSTATE_ENCRYPTED&&(this.sendMsg("\x00\x00\x00\x00"),this.sm&&(this.smw&&this.sm.worker.terminate(),this.sm=null)),this.msgstate=CONST.MSGSTATE_PLAINTEXT,this.receivedPlaintext=!1,this.trigger("status",[CONST.STATUS_END_OTR])},OTR.makeInstanceTag=function(){var num=BigInt.randBigInt(32);return BigInt.greater(BigInt.str2bigInt("100",16),num)?OTR.makeInstanceTag():HLP.packINT(parseInt(BigInt.bigInt2str(num,10),10))}}.call(this),{OTR:this.OTR,DSA:this.DSA}});
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/browser/otr.min.js_README	Tue Sep 02 21:28:42 2014 +0200
@@ -0,0 +1,9 @@
+The file otr.min.js includes:
+    - minified versions of the following otr.js dependencies:
+      otr/dep/bigint.js otr/dep/crypto.js otr/dep/eventemitter.js
+      The following minification tool has been used: yui compressor
+    - minified version of otr.js taken from the project homepage
+
+All original files can be retrieved from otr.js repository:
+    https://github.com/arlolra/otr/tree/master/build
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/browser/sat_browser/otrjs_wrapper.py	Tue Sep 02 21:28:42 2014 +0200
@@ -0,0 +1,228 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Libervia wrapper for otr.js
+# Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 Jérôme Poisson (goffi@goffi.org)
+# Copyright (C) 2013, 2014 Adrien Cossa (souliane@mailoo.org)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# 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 Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""This file is a wrapper for otr.js. It partially reproduces the usage
+(modules, classes and attributes names) and behavior of potr, so you
+can easily adapt some code based on potr to Pyjamas applications.
+
+potr is released under the GNU LESSER GENERAL PUBLIC LICENSE Version 3
+    - https://github.com/python-otr/pure-python-otr/blob/master/LICENSE
+
+otr.js is released under the Mozilla Public Licence Version 2.0
+    - https://github.com/arlolra/otr/blob/master/license
+"""
+
+from __pyjamas__ import JS
+
+# should you re-use this class outside SàT, you can import __pyjamas__.console as log instead
+from sat.core.log import getLogger
+log = getLogger(__name__)
+
+
+# XXX: pyjamas can't probably import more than one JS file, it messes the order.
+# XXX: pyjamas needs the file to be in the compilation directory - no submodule.
+# XXX: pyjamas needs the imported file to end with a empty line or semi-column.
+# FIXME: fix these bugs upstream in Pyjamas
+import otr.min.js
+
+
+class context(object):
+
+    # Pre-declare these attributes to avoid the pylint "undefined variable" errors
+    STATUS_SEND_QUERY = None
+    STATUS_AKE_INIT = None
+    STATUS_AKE_SUCCESS = None
+    STATUS_END_OTR = None
+    STATE_PLAINTEXT = None
+    STATE_ENCRYPTED = None
+    STATE_FINISHED = None
+    OTR_VERSION_2 = None
+    OTR_VERSION_3 = None
+
+    JS("""
+    $cls_definition['STATUS_SEND_QUERY'] = OTR.CONST.STATUS_SEND_QUERY;
+    $cls_definition['STATUS_AKE_INIT'] = OTR.CONST.STATUS_AKE_INIT;
+    $cls_definition['STATUS_AKE_SUCCESS'] = OTR.CONST.STATUS_AKE_SUCCESS;
+    $cls_definition['STATUS_END_OTR'] = OTR.CONST.STATUS_END_OTR;
+    $cls_definition['STATE_PLAINTEXT'] = OTR.CONST.MSGSTATE_PLAINTEXT;
+    $cls_definition['STATE_ENCRYPTED'] = OTR.CONST.MSGSTATE_ENCRYPTED;
+    $cls_definition['STATE_FINISHED'] = OTR.CONST.MSGSTATE_FINISHED;
+    $cls_definition['OTR_VERSION_2'] = OTR.CONST.OTR_VERSION_2;
+    $cls_definition['OTR_VERSION_3'] = OTR.CONST.OTR_VERSION_3;
+    """)
+
+    class UnencryptedMessage(Exception):
+        pass
+
+    class Context(object):
+
+        def __init__(self, account, peername):
+            self.user = account
+            self.peer = peername
+            self.trustName = self.peer
+            options = {'fragment_size': 140,
+                       'send_interval': 200,
+                       'priv': account.getPrivkey(),  # this would generate the account key if it hasn't been done yet
+                       'debug': False,
+                       }
+            JS("""self.otr = new OTR(options);""")
+
+            for policy in ('ALLOW_V2', 'ALLOW_V3', 'REQUIRE_ENCRYPTION'):
+                setattr(self.otr, policy, self.getPolicy(policy))
+
+            self.otr.on('ui', self.receiveMessageCb)
+            self.otr.on('io', self.sendMessageCb)
+            self.otr.on('error', self.messageErrorCb)
+            self.otr.on('status', lambda status: self.setStateCb(self.otr.msgstate, status))
+            self.otr.on('smp', self.smpAuthCb)
+
+        @property
+        def state(self):
+            return self.otr.msgstate
+
+        @state.setter
+        def state(self, state):
+            self.otr.msgstate = state
+
+        def getCurrentKey(self):
+            return self.otr.their_priv_pk
+
+        def setTrust(self, fingerprint, trustLevel):
+            self.user.setTrust(self.trustName, fingerprint, trustLevel)
+
+        def setCurrentTrust(self, trustLevel):
+            self.setTrust(self.otr.their_priv_pk.fingerprint(), trustLevel)
+
+        def getTrust(self, fingerprint, default=None):
+            return self.user.getTrust(self.trustName, fingerprint, default)
+
+        def getCurrentTrust(self):
+            # XXX: the docstring of potr for the return value of this method is incorrect
+            if self.otr.their_priv_pk is None:
+                return None
+            return self.getTrust(self.otr.their_priv_pk.fingerprint(), None)
+
+        def getUsedVersion(self):
+            """Return the otr version that is beeing used"""
+            # this method doesn't exist in potr, it has been added for convenience
+            try:
+                return self.otr.ake.otr_version
+            except AttributeError:
+                return None
+
+        def disconnect(self):
+            self.otr.endOtr()
+
+        def receiveMessage(self, msg):
+            """Received a message, ask otr.js to (try to) decrypt it"""
+            self.otr.receiveMsg(msg)
+
+        def sendMessage(self, msg):
+            """Ask otr.js to encrypt a message for sending"""
+            self.otr.sendMsg(msg)
+
+        def sendQueryMessage(self):
+            """Start or refresh an encryption communication"""
+            # otr.js offers this method, with potr you have to build the query message yourself
+            self.otr.sendQueryMsg()
+
+        def inject(self, msg, appdata=None):
+            return self.sendMessageCb(msg, appdata)
+
+        def getPolicy(self, key):
+            raise NotImplementedError
+
+        def smpAuthSecret(self, secret, question=None):
+            return self.otr.smpSecret(secret, question)
+
+        def smpAuthAbort(self, act=None):
+            # XXX: dirty hack to let the triggered method know who aborted the
+            # authentication. We need it to display the proper feedback and,
+            # if the buddy aborted, set the conversation 'unverified'.
+            self.otr.sm.init()
+            JS("""self.otr.sm.sendMsg(OTR.HLP.packTLV(6, ''))""")
+            self.smpAuthCb('abort', '', act)
+
+        def sendMessageCb(self, msg, meta):
+            """Actually send the message after it's been encrypted"""
+            raise NotImplementedError
+
+        def receiveMessageCb(self, msg, encrypted):
+            """Display the message after it's been eventually decrypted"""
+            raise NotImplementedError
+
+        def messageErrorCb(self, error):
+            """Message error callback"""
+            raise NotImplementedError
+
+        def setStateCb(self, newstate):
+            raise NotImplementedError
+
+        def smpAuthCb(self, newstate):
+            raise NotImplementedError
+
+    class Account(object):
+
+        def __init__(self, host):
+            self.host = host
+            self.privkey = None
+            self.trusts = {}
+
+        def getPrivkey(self):
+            # the return value must have a method serializePrivateKey()
+            # if the key is not saved yet, call savePrivkey to generate it
+            if self.privkey is None:
+                self.privkey = self.loadPrivkey()
+            if self.privkey is None:
+                JS("""self.privkey = new DSA();""")
+                self.savePrivkey()
+            return self.privkey
+
+        def setTrust(self, key, fingerprint, trustLevel):
+            if key not in self.trusts:
+                self.trusts[key] = {}
+            self.trusts[key][fingerprint] = trustLevel
+            self.saveTrusts()
+
+        def getTrust(self, key, fingerprint, default=None):
+            if key not in self.trusts:
+                return default
+            return self.trusts[key].get(fingerprint, default)
+
+        def loadPrivkey(self):
+            raise NotImplementedError
+
+        def savePrivkey(self):
+            raise NotImplementedError
+
+        def saveTrusts(self):
+            raise NotImplementedError
+
+
+class crypt(object):
+
+    class PK(object):
+
+        def parsePrivateKey(self, key):
+            JS("""return DSA.parsePrivate(key);""")
+
+
+# serialazePrivateKey is the method name in potr
+JS("""DSA.serializePrivateKey = DSA.packPrivate;""")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/browser/sat_browser/plugin_sec_otr.py	Tue Sep 02 21:28:42 2014 +0200
@@ -0,0 +1,428 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Libervia plugin for OTR encryption
+# Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 Jérôme Poisson (goffi@goffi.org)
+# Copyright (C) 2013, 2014 Adrien Cossa (souliane@mailoo.org)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# 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 Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""
+This file is adapted from sat.plugins.plugin.sec_otr. It offers browser-side OTR encryption using otr.js.
+The text messages to display are mostly taken from the Pidgin OTR plugin (GPL 2.0, see http://otr.cypherpunks.ca).
+"""
+
+from sat.core.i18n import _, D_
+from sat.core.log import getLogger
+from sat.core import exceptions
+log = getLogger(__name__)
+
+from constants import Const as C
+import jid
+import otrjs_wrapper as otr
+import dialog
+
+NS_OTR = "otr_plugin"
+PRIVATE_KEY = "PRIVATE KEY"
+MAIN_MENU = D_('OTR')
+DIALOG_EOL = "<br />"
+AUTH_INFO_TXT = D_("Authenticating a buddy helps ensure that the person you are talking to is who he or she claims to be.{eol}{eol}").format(eol=DIALOG_EOL)
+AUTH_FINGERPRINT_TXT = D_("<i>To verify the fingerprint, contact your buddy via some other authenticated channel (i.e. not in this chat), such as the telephone or GPG-signed email. Each of you should tell your fingerprint to the other.</i>{eol}{eol}").format(eol=DIALOG_EOL)
+AUTH_QUEST_DEF = D_("<i>To authenticate using a question, pick a question whose answer is known only to you and your buddy. Enter this question and this answer, then wait for your buddy to enter the answer too. If the answers don't match, then you may be talking to an imposter.</i>{eol}{eol}").format(eol=DIALOG_EOL)
+AUTH_QUEST_ASK = D_("<i>Your buddy is attempting to determine if he or she is really talking to you, or if it's someone pretending to be you. Your buddy has asked a question, indicated below. To authenticate to your buddy, enter the answer and click OK.</i>{eol}{eol}").format(eol=DIALOG_EOL)
+AUTH_SECRET_TXT = D_("{eol}{eol}Enter secret answer here: (case sensitive){eol}").format(eol=DIALOG_EOL)
+
+
+DROP_TXT = D_("You private key is used to encrypt messages for your correspondent, nobody except you must know it, if you are in doubt, you should drop it!{eol}{eol}Are you sure you want to drop your private key?").format(eol=DIALOG_EOL)
+
+DEFAULT_POLICY_FLAGS = {
+    'ALLOW_V2': True,
+    'ALLOW_V3': True,
+    'REQUIRE_ENCRYPTION': False,
+}
+
+
+class Context(otr.context.Context):
+
+    def __init__(self, host, account, other_jid):
+        """
+
+        @param host (satWebFrontend)
+        @param account (Account)
+        @param other_jid (JID): JID of the person your chat buddy
+        """
+        super(Context, self).__init__(account, other_jid)
+        self.host = host
+
+    def getPolicy(self, key):
+        """Get the value of the specified policy
+
+        @param key (str): a value in:
+            - ALLOW_V1 (apriori removed from otr.js)
+            - ALLOW_V2
+            - ALLOW_V3
+            - REQUIRE_ENCRYPTION
+            - SEND_WHITESPACE_TAG
+            - WHITESPACE_START_AKE
+            - ERROR_START_AKE
+        @return: str
+        """
+        if key in DEFAULT_POLICY_FLAGS:
+            return DEFAULT_POLICY_FLAGS[key]
+        else:
+            return False
+
+    def receiveMessageCb(self, msg, encrypted):
+        assert isinstance(self.peer, jid.JID)
+        log.debug("message received (was %s): %s" % ('encrypted' if encrypted else 'plain', msg))
+        if not encrypted:
+            if self.state == otr.context.STATE_ENCRYPTED:
+                log.warning(u"Received unencrypted message in an encrypted context (from %(jid)s)" % {'jid': self.peer.full()})
+                feedback = _(u"WARNING: received unencrypted data in a supposedly encrypted context"),
+                self.host.newMessageCb(self.peer, feedback, "headline", self.host.whoami, {})
+        self.host.newMessageCb(self.peer, msg, "chat", self.host.whoami, {})
+
+    def sendMessageCb(self, msg, meta=None):
+        assert isinstance(self.peer, jid.JID)
+        log.debug("message to send%s: %s" % ((' (attached meta data: %s)' % meta) if meta else '', msg))
+        self.host.bridge.call('sendMessage', (None, self.host.sendError), self.peer.full(), msg, '', 'chat', {'send_only': 'true'})
+
+    def messageErrorCb(self, error):
+        log.error('error occured: %s' % error)
+
+    def setStateCb(self, msg_state, status):
+        other_jid_s = self.peer.full()
+        feedback = _(u"Error: the state of the conversation with %s is unknown!")
+
+        if status == otr.context.STATUS_AKE_INIT:
+            return
+
+        elif status == otr.context.STATUS_SEND_QUERY:
+            if msg_state in (otr.context.STATE_PLAINTEXT, otr.context.STATE_FINISHED):
+                feedback = _('Attempting to start a private conversation with %s...')
+            elif msg_state == otr.context.STATE_ENCRYPTED:
+                feedback = _('Attempting to refresh the private conversation with %s...')
+
+        elif status == otr.context.STATUS_AKE_SUCCESS:
+            trusted_str = _(u"Verified") if self.getCurrentTrust() else _(u"Unverified")
+            if msg_state == otr.context.STATE_ENCRYPTED:
+                feedback = trusted_str + (u" conversation with %s started. Your client is not logging this conversation.")
+            else:
+                feedback = _("Error: successfully ake'd with %s but the conversation is not private!")
+
+        elif status == otr.context.STATUS_END_OTR:
+            if msg_state == otr.context.STATE_PLAINTEXT:
+                feedback = _("You haven't start any private conversation with %s yet.")
+            elif msg_state == otr.context.STATE_ENCRYPTED:
+                feedback = _("%s has ended his/her private conversation with you; you should do the same.")
+            elif msg_state == otr.context.STATE_FINISHED:
+                feedback = _("Private conversation with %s lost.")
+
+        self.host.newMessageCb(self.peer, feedback % other_jid_s, "headline", self.host.whoami, {})
+
+    def setCurrentTrust(self, new_trust='', act='asked', type_='trust'):
+        log.debug("setCurrentTrust: trust={trust}, act={act}, type={type}".format(type=type_, trust=new_trust, act=act))
+        title = (_("Authentication of {jid}") if act == "asked" else _("Authentication to {jid}")).format(jid=self.peer.full())
+        if type_ == 'abort':
+            msg = _("Authentication aborted.")
+        elif new_trust:
+            if act == "asked":
+                msg = _("Authentication successful.")
+            else:
+                msg = _("Your buddy has successfully authenticated you. You may want to authenticate your buddy as well by asking your own question.")
+        else:
+            msg = _("Authentication failed.")
+        dialog.InfoDialog(title, msg).show()
+        if act != "asked":
+            return
+        old_trust = self.getCurrentTrust()
+        otr.context.Context.setCurrentTrust(self, new_trust)
+        if old_trust != new_trust:
+            feedback = _("The privacy status of the current conversation is now: {state}").format(state='Private' if new_trust else 'Unverified')
+            self.host.newMessageCb(self.peer, feedback, "headline", self.host.whoami, {})
+
+    def fingerprintAuthCb(self):
+        """OTR v2 authentication using manual fingerprint comparison"""
+        priv_key = self.user.privkey
+
+        if priv_key is None:  # OTR._authenticate should not let us arrive here
+            raise exceptions.InternalError
+            return
+
+        other_key = self.getCurrentKey()
+        if other_key is None:
+            # we have a private key, but not the fingerprint of our correspondent
+            msg = AUTH_INFO_TXT + ("Your fingerprint is:{eol}{fingerprint}{eol}{eol}Start an OTR conversation to have your correspondent one.").format(fingerprint=priv_key.fingerprint(), eol=DIALOG_EOL)
+            dialog.InfoDialog(_("Fingerprint"), msg).show()
+            return
+
+        def setTrust(confirm):
+            self.setCurrentTrust('fingerprint' if confirm else '')
+
+        text = AUTH_INFO_TXT + AUTH_FINGERPRINT_TXT + _("Fingerprint for you, {jid}:{eol}{fingerprint}{eol}{eol}").format(jid=self.host.whoami, fingerprint=priv_key.fingerprint(), eol=DIALOG_EOL)
+        text += _("Purported fingerprint for {jid}:{eol}{fingerprint}{eol}{eol}").format(jid=self.peer, fingerprint=other_key.fingerprint(), eol=DIALOG_EOL)
+        text += _("Did you verify that this is in fact the correct fingerprint for {jid}?").format(jid=self.peer)
+        title = _('Authentication of {jid}').format(jid=self.peer.full())
+        dialog.ConfirmDialog(setTrust, text, title).show()
+
+    def smpAuthCb(self, type_, data, act=None):
+        """OTR v3 authentication using the socialist millionaire protocol.
+
+        @param type_ (str): a value in ('question', 'trust', 'abort')
+        @param data (str, bool): this could be:
+            - a string containing the question if type_ is 'question'
+            - a boolean value telling if the authentication succeed when type_ is 'trust'
+        @param act (str): a value in ('asked', 'answered')
+        """
+        log.debug("smpAuthCb: type={type}, data={data}, act={act}".format(type=type_, data=data, act=act))
+        if act is None:
+            if type_ == 'question':
+                act = 'answered'  # OTR._authenticate calls this method with act="asked"
+            elif type_ == 'abort':
+                act = 'asked'  # smpAuthAbort triggers this method with act='answered' when needed
+
+                # FIXME upstream: if buddy uses Pidgin and use fingerprint to authenticate us,
+                # we will reach this code... that's wrong, this method is for SMP! There's
+                # probably a bug to fix in otr.js. Do it together with the issue that make
+                # us need the dirty self.smpAuthAbort.
+            else:
+                log.error("FIXME: unmanaged ambiguous 'act' value in Context.smpAuthCb!")
+        title = (_("Authentication of {jid}") if act == "asked" else _("Authentication to {jid}")).format(jid=self.peer.full())
+        if type_ == 'question':
+            if act == 'asked':
+                def cb(question, answer=None):
+                    if question is False or not answer:  # dialog cancelled or the answer is empty
+                        return
+                    self.smpAuthSecret(answer, question)
+                text = AUTH_INFO_TXT + AUTH_QUEST_DEF + _("Enter question here:{eol}").format(eol=DIALOG_EOL, question=data)
+                dialog.PromptDialog(cb, [text, AUTH_SECRET_TXT], title=title).show()
+            else:
+                def cb(answer):
+                    if not answer:  # dialog cancelled or the answer is empty
+                        self.smpAuthAbort('answered')
+                        return
+                    self.smpAuthSecret(answer)
+                text = AUTH_INFO_TXT + AUTH_QUEST_ASK + _("This is the question asked by your buddy:{eol}{question}").format(eol=DIALOG_EOL, question=data)
+                dialog.PromptDialog(cb, text + AUTH_SECRET_TXT, title=title).show()
+        elif type_ == 'trust':
+            self.setCurrentTrust('smp' if data else '', act)
+        elif type_ == 'abort':
+            self.setCurrentTrust('', act, 'abort')
+
+
+class Account(otr.context.Account):
+
+    def __init__(self, host):
+        log.debug(u"new account: %s" % host.whoami.full())
+        if not host.whoami.resource:
+            log.warning("Account created without resource")
+        super(Account, self).__init__(host.whoami)
+        self.host = host
+
+    def loadPrivkey(self):
+        return self.privkey
+
+    def savePrivkey(self):
+        # TODO: serialize and encrypt the private key and save it to a HTML5 persistent storage
+        # We need to ask the user before saving the key (e.g. if he's not on his private machine)
+        # self.privkey.serializePrivateKey() --> encrypt --> store
+        if self.privkey is None:
+            raise exceptions.InternalError(_("Save is called but privkey is None !"))
+        pass
+
+    def saveTrusts(self):
+        # TODO save the trusts as it would be done for the private key
+        pass
+
+
+class ContextManager(object):
+
+    def __init__(self, host):
+        self.host = host
+        self.account = Account(host)
+        self.contexts = {}
+
+    def startContext(self, other_jid):
+        assert isinstance(other_jid, jid.JID)
+        # FIXME upstream: apparently pyjamas doesn't implement setdefault well, it ignores JID.__hash__ redefinition
+        #context = self.contexts.setdefault(other_jid, Context(self.host, self.account, other_jid))
+        if other_jid not in self.contexts:
+            self.contexts[other_jid] = Context(self.host, self.account, other_jid)
+        return self.contexts[other_jid]
+
+    def getContextForUser(self, other):
+        log.debug(u"getContextForUser [%s]" % other)
+        if not other.resource:
+            log.error("getContextForUser called with a bare jid")
+        return self.startContext(other)
+
+
+class OTR(object):
+
+    def __init__(self, host):
+        log.info(_(u"OTR plugin initialization"))
+        self.host = host
+        self.context_manager = None
+        self.last_resources = {}
+        self.host.bridge._registerMethods(["skipOTR"])
+
+    def inhibitMenus(self):
+        """Tell the caller which dynamic menus should be inhibited"""
+        return ["OTR"]  # menu categories name to inhibit
+
+    def extraMenus(self):
+        # FIXME: handle help strings too
+        return [(self._startRefresh, C.MENU_SINGLE, (MAIN_MENU, "Start/Refresh"), (MAIN_MENU, D_("Start/Refresh"))),
+                (self._endSession, C.MENU_SINGLE, (MAIN_MENU, "End session"), (MAIN_MENU, D_("End session"))),
+                (self._authenticate, C.MENU_SINGLE, (MAIN_MENU, "Authenticate buddy"), (MAIN_MENU, D_("Authenticate buddy"))),
+                (self._dropPrivkey, C.MENU_SINGLE, (MAIN_MENU, "Drop private key"), (MAIN_MENU, D_("Drop private key")))]
+
+    def profileConnected(self):
+        self.host.bridge.call('skipOTR', None)
+        self.context_manager = ContextManager(self.host)
+        # TODO: retrieve the encrypted private key from a HTML5 persistent storage,
+        # decrypt it, parse it with otr.crypt.PK.parsePrivateKey(privkey) and
+        # assign it to self.context_manager.account.privkey
+
+    def fixResource(self, jid, cb):
+        # FIXME: it's dirty, but libervia doesn't manage resources correctly now, refactoring is planed
+        if jid.resource:
+            cb(jid)
+        elif jid.bare in self.last_resources:
+            jid.resource = self.last_resources[jid.bare]
+            cb(jid)
+        else:
+            def gotResource(resource):
+                jid.setResource(resource)
+                cb(jid)
+            self.host.bridge.call('getLastResource', gotResource, jid.full())
+
+    def messageReceivedTrigger(self, from_jid, msg, msg_type, to_jid, extra):
+        other_jid = to_jid if from_jid.bare == self.host.whoami.bare else from_jid
+
+        def cb(jid):
+            otrctx = self.context_manager.getContextForUser(jid)
+            otrctx.receiveMessage(msg)
+            return False  # interrupt the main process
+
+        self.fixResource(other_jid, cb)
+
+    def sendMessageTrigger(self, to_jid, msg, msg_type, extra):
+        def cb(jid):
+            otrctx = self.context_manager.getContextForUser(jid)
+            if msg_type != 'groupchat' and otrctx.state == otr.context.STATE_ENCRYPTED:
+                log.debug(u"encrypting message")
+                otrctx.sendMessage(msg)
+                self.host.newMessageCb(self.host.whoami, msg, msg_type, jid, extra)
+            else:
+                log.debug(u"sending message unencrypted")
+                self.host.bridge.call('sendMessage', (None, self.host.sendError), to_jid.full(), msg, '', msg_type, extra)
+
+        if msg_type != 'groupchat':
+            self.fixResource(to_jid, cb)
+        else:
+            cb(to_jid)
+        return False  # interrupt the main process
+
+    # Menu callbacks
+
+    def _startRefresh(self, menu_data):
+        """Start or refresh an OTR session
+
+        @param menu_data: %(menu_data)s
+        """
+        def cb(other_jid):
+            otrctx = self.context_manager.getContextForUser(other_jid)
+            otrctx.sendQueryMessage()
+
+        try:
+            other_jid = menu_data['jid']
+            self.fixResource(other_jid, cb)
+        except KeyError:
+            log.error(_("jid key is not present !"))
+            return None
+
+    def _endSession(self, menu_data):
+        """End an OTR session
+
+        @param menu_data: %(menu_data)s
+        """
+        def cb(other_jid):
+            otrctx = self.context_manager.getContextForUser(other_jid)
+            otrctx.disconnect()
+        try:
+            other_jid = menu_data['jid']
+            self.fixResource(other_jid, cb)
+        except KeyError:
+            log.error(_("jid key is not present !"))
+            return None
+
+    def _authenticate(self, menu_data, profile):
+        """Authenticate other user and see our own fingerprint
+
+        @param menu_data: %(menu_data)s
+        @param profile: %(doc_profile)s
+        """
+        def cb(to_jid):
+            otrctx = self.context_manager.getContextForUser(to_jid)
+            otr_version = otrctx.getUsedVersion()
+            if otr_version == otr.context.OTR_VERSION_2:
+                otrctx.fingerprintAuthCb()
+            elif otr_version == otr.context.OTR_VERSION_3:
+                otrctx.smpAuthCb('question', None, 'asked')
+            else:
+                dialog.InfoDialog(_("No running session"), _("You must start a private conversation before authenticating your buddy.")).show()
+
+        try:
+            to_jid = menu_data['jid']
+            self.fixResource(to_jid, cb)
+        except KeyError:
+            log.error(_("jid key is not present !"))
+            return None
+
+    def _dropPrivkey(self, menu_data, profile):
+        """Drop our private Key
+
+        @param menu_data: %(menu_data)s
+        @param profile: %(doc_profile)s
+        """
+        def cb(to_jid):
+            priv_key = self.context_manager.account.privkey
+
+            if priv_key is None:
+                # we have no private key yet
+                dialog.InfoDialog(_("No private key"), _("You don't have any private key yet!")).show()
+                return
+
+            def dropKey(confirm):
+                if confirm:
+                    # we end all sessions
+                    for context in self.context_manager.contexts.values():
+                        if context.state not in (otr.context.STATE_FINISHED, otr.context.STATE_PLAINTEXT):
+                            context.disconnect()
+                    self.context_manager.account.privkey = None
+                    self.context_manager.account.getPrivkey()  # as account.privkey are None, getPrivkey will generate a new key, and save it
+                    dialog.InfoDialog(_("Your private key has been dropped"), _('Drop')).show()
+
+            text = _(DROP_TXT)
+            title = _('Confirm private key drop')
+            dialog.ConfirmDialog(dropKey, text, title).show()
+
+        try:
+            to_jid = menu_data['jid']
+            self.fixResource(to_jid, cb)
+        except KeyError:
+            log.error(_("jid key is not present !"))
+            return None
+
--- a/src/server/server.py	Tue Sep 02 21:26:32 2014 +0200
+++ b/src/server/server.py	Tue Sep 02 21:28:42 2014 +0200
@@ -557,6 +557,12 @@
         profile = ISATSession(self.session).profile
         return self.sat_host.bridge.getLastResource(jid_s, profile)
 
+    # FIXME: as this belong to a plugin, it should be managed dynamically
+    def jsonrpc_skipOTR(self):
+        """Tell the backend to leave OTR handling to Libervia."""
+        profile = ISATSession(self.session).profile
+        return self.sat_host.bridge.skipOTR(profile)
+
 
 class Register(JSONRPCMethodManager):
     """This class manage the registration procedure with SàT