function StrToUtf8( s )
{
  var utf8 = new Array() ;
  for( var i = 0, j = 0, l = s.length ; i < l ; i++ ) {
    var c = s.charCodeAt( i ) ;
    if( c < 0x80 ) utf8[ j++ ] = c ;
    else if( c < 0x800 ) {
      utf8[ j++ ] = ( c >> 6 ) | 0xC0 ;
      utf8[ j++ ] = ( c & 0x3F ) | 0x80 ;
    }
    else {
      utf8[ j++ ] = ( c >> 12 ) | 0xE0 ;
      utf8[ j++ ] = ( ( c >> 6 ) & 0x3F ) | 0x80 ;
      utf8[ j++ ] = ( c & 0x3F ) | 0x80 ;
    }
  }
  return utf8 ;
}

function Utf8ToStr( a ) 
{
  function c2s0( c ) { return String.fromCharCode( c ) ; }
  function c2s1( c0, c1 ) 
  { 
    return c2s0( ( ( c0 & 0x1F ) << 6 ) | ( c1 & 0x3F ) ) ; 
  }
  function c2s2( c0, c1, c2 )
  {
    return c2s0( ( ( c0 & 0xF ) << 12 ) | ( ( c1 & 0x3F ) << 6 ) | 
        ( c2 & 0x3F ) ) ;
  }
  var s = new Array() ;
  for( var i = 0, j = 0, l = a.length ; i < l ; i++ ) {
    var u0 = a[ i ] ; 
    if( u0 < 0x80 ) s[ j++ ] = c2s0( u0 ) ;
    else if( ++i >= l ) break ;
    else if( u0 < 0xE0 ) s[ j++ ] = c2s1( u0, a[ i ] ) ;
    else if( ++i >= l ) break ;
    else s[ j++ ] = c2s2( u0, a[ i - 1 ], a[ i ] ) ;
  }
  return s.join( '' ) ;
}

function BAToXX( a )
{
  var s = new Array() ;
  var x = new Array( "0", "1", "2", "3", "4", "5", "6", "7", 
                      "8", "9", "A", "B", "C", "D", "E", "F" ) ;
  for( var i = 0, j = 0, l = a.length ; i < l ; i++ ) {
    s[ j++ ] = x[ ( a[ i ] >> 4 ) & 0xF ] ;
    s[ j++ ] = x[ a[ i ] & 0xF ] ;
  }
  return s.join( "" ) ;
}

function SAToXX( a )
{
  var s = new Array() ;
  var x = new Array( "0", "1", "2", "3", "4", "5", "6", "7", 
                      "8", "9", "A", "B", "C", "D", "E", "F" ) ;
  for( var i = 0, j = 0, l = a.length ; i < l ; i++ ) {
    s[ j++ ] = x[ ( a[ i ] >> 4 ) & 0xF ] ;
    s[ j++ ] = x[ a[ i ] & 0xF ] ;
    s[ j++ ] = x[ ( a[ i ] >> 12 ) & 0xF ] ;
    s[ j++ ] = x[ ( a[ i ] >> 8 ) & 0xF ] ;
  }
  return s.join( "" ) ;
}

function LAToXX( a )
{
  var s = new Array() ;
  var x = new Array( "0", "1", "2", "3", "4", "5", "6", "7", 
                      "8", "9", "A", "B", "C", "D", "E", "F" ) ;
  for( var i = 0, j = 0, l = a.length ; i < l ; i++ ) {
    s[ j++ ] = x[ ( a[ i ] >> 4 ) & 0xF ] ;
    s[ j++ ] = x[ a[ i ] & 0xF ] ;
    s[ j++ ] = x[ ( a[ i ] >> 12 ) & 0xF ] ;
    s[ j++ ] = x[ ( a[ i ] >> 8 ) & 0xF ] ;
    s[ j++ ] = x[ ( a[ i ] >> 20 ) & 0xF ] ;
    s[ j++ ] = x[ ( a[ i ] >> 16 ) & 0xF ] ;
    s[ j++ ] = x[ ( a[ i ] >> 28 ) & 0xF ] ;
    s[ j++ ] = x[ ( a[ i ] >> 24 ) & 0xF ] ;
  }
  return s.join( "" ) ;
}

function XXToBA( x ) 
{
  function x2b( ch ) 
  {
    if( ch <= 57 && ch >= 48 ) return ch - 48 ;
    if( ch <= 70 && ch >= 65 ) return ch - 55
    if( ch <= 103 && ch >= 97 ) return ch - 87 ;
    return undefined ;
  }

  var v1, v0, d = new Array() ;
  for( var i = 0, j = 0, l = ( x.length >> 1 ) << 1 ; i < l ; ) {
    v1 = x2b( x.charCodeAt( i++ ) ) ;
    v0 = x2b( x.charCodeAt( i++ ) ) ;
    if( v1 == undefined || v0 == undefined ) break ;
    d[ j++ ] = ( v1 << 4 ) | v0 ;
  }
  return d ;
}

function BAToSA( b )
{
  var s = new Array(), k = b.length >> 1, j = 0 ; 
  for( var i = 0 ; i < k ; i++ ) {
    s[ i ] = b[ j++ ] & 0xFF ;
    s[ i ] += ( ( b[ j++ ] & 0xFF ) << 8 ) ;
  }
  if( j < b.length ) s[ k ] = b[ j ] & 0xFF ;
  return s ;
}

function BAToLA( b )
{
  var s = new Array(), k = b.length >> 2, j = 0 ; 
  for( var i = 0 ; i < k ; i++ ) {
    s[ i ] = b[ j++ ] & 0xFF ;
    s[ i ] += ( ( b[ j++ ] & 0xFF ) << 8 ) ;
    s[ i ] += ( ( b[ j++ ] & 0xFF ) << 16 ) ;
    s[ i ] += ( ( b[ j++ ] & 0xFF ) << 24 ) ;
  }
  if( j >= b.length ) return s ;
  for( var v = 0, sh = 0 ; j < b.length ; sh += 8 ) {
    v += ( ( b[ j++ ] & 0xFF ) << sh ) ;
  }
  s[ k ] = v ;
  return s ;
}

function SAToBA( s )
{
  var b = new Array() ;
  for( var j = 0, i = 0, l = s.length ; i < l ; i++ ) { 
    b[ j++ ] = s[ i ] & 0xFF ;
    b[ j++ ] = ( s[ i ] >> 8 ) & 0xFF ;
  }
  return b ;
}

function LAToBA( s )
{
  var b = new Array() ;
  for( var j = 0, i = 0, v, l = s.length ; i < l ; i++ ) { 
    b[ j++ ] = ( v = s[ i ] ) & 0xFF ;
    b[ j++ ] = ( v >> 8 ) & 0xFF ;
    b[ j++ ] = ( v >> 16 ) & 0xFF ;
    b[ j++ ] = ( v >> 24 ) & 0xFF ;
  }
  return b ;
}

function XXToSA( xx ) { return BAToSA( XXToBA( xx ) ) ; }

function XXToLA( xx ) { return BAToLA( XXToBA( xx ) ) ; }

function StrToBA( s )
{
  var a = new Array(), ch ;
  for( var i = 0, j = 0 ; i < s.length ; ) {
    ch = s.charCodeAt( i++ ) ;
    a[ j++ ] = ch & 0xFF ;
    a[ j++ ] = ( ch >> 8 ) & 0xFF ;
  }  
  return a;
}

function BAToStr( a )
{
  var s = new Array() ;
  var l = ( a.length >> 1 ) << 1, ch ;
  for( var i = 0, j = 0 ; i < l ; i += 2) {
    s[ j++ ] = String.fromCharCode( ( a[ i ] & 0xFF ) + 
                       ( 0xFF & ( a[ i + 1 ] << 8 ) ) ) ;
  }
  return s.join( "" ) ;
}

function StrToSA( s )
{
  var a = new Array(), ch ;
  for( var i = 0 ; i < s.length ; i++ ) a[ i ] = s.charCodeAt( i ) ;
  return a;
}

function SAToStr( a ) 
{ 
  var s = new Array() ;
  for( var i = 0 ; i < a.length ; i++ ) s[ i ] = String.fromCharCode( a[ i ] ) ;
  return s.join( "" ) ;
}

function BRandom() { return Math.floor( 256 * Math.random() ) ; }

function WRandom() { return Math.floor( 0x10000 * Math.random() ) ; }

function LRandom() { return WRandom() + ( WRandom() << 16 ) ; }

function Entrop( N, M, P, x1, x2, l )
{
  var _0 = 0, _1 = 0 ;

  function initRand( s0, s1 )
  {
    _0 = s0 & 0xFFFFFFFF, _1 = s1 & 0xFFFFFFFF ;
  }

  function rand()
  {
    _0 = 0xFFFFFFFF & ( _0 * 0x4E35 + ( _0 & 0xFFFF ) * 0x15A0000 + 1 ) ;
    _1 = 0xFFFFFFFF & ( _1 * 25173 ) + 13849 ;
    return 0xFFFF & ( ( _0 >> 16 ) ^ _1 ) ;
  }

  function norm( a )
  {
    for( var i = 0, l = a.length ; i < l ; i++ ) {
      if( a[ i ] > 0x7FFF ) a[ i ] -= 0x10000 ;
    }
  } 

  function calcSum( sum, a )
  {
    var l = a.length ; 
    if( l > 0 ) sum += a[ 0 ] ; 
    for( var i = 1 ; i < l ; i++ ) {
      sum += ( a[ i ] + ( ( a[ i - 1 ] * a[ i ] ) & 0xFFFFFFFF ) ) ;
    }
    return sum ;
  }

  if( x1 == null ) x1 = new Array() ;
  if( x2 == null ) x2 = new Array() ;
  var r = new Array( l ) ;
  var sum = 0, l1 = x1.length, l2 = x2.length ;
  norm( x1 ) ;
  norm( x2 ) ;
  sum = calcSum( sum, x1 ) ;
  sum = calcSum( sum, x2 ) ;
  initRand( sum + N + M + P + ( ( N * M * P ) & 0xFFFF ), 
      ( 0xFFFFFFFF & ( sum * l * P ) ) + 0xAB17935E + 
      ( 0xFFFF & ( 2 * ( l1 + l2 ) ) ) ) ;   
  var s = new Array( sum & 0xFFFF, ( sum >> 16 ) & 0xFFFF ) ;
//  norm( s ) ;
  if( l1 <= 0 ) l1 = 2, x1 = s ;
  if( l2 <= 0 ) l2 = 2, x2 = s ;
  var l12 = l1 + l2 ;
  for( var i = 0, j = 0, count = Math.max( l12, l ) ; --count >= 0 ; ) {
    r[ j ] = ( ( ( i < l1 ) ? x1[ i ] : x2[ i - l1 ] ) + rand() ) ;
    while( r[ j ] == 0 ) r[ j ] = rand() ;
    if( ++i == l12 ) i = 0 ;
    if( ++j == l ) j = 0 ;
  } 
//  norm( r ) ;
  for( var k = 0 ; k < l ; k++ ) {		
    for( var n = 0 ; n < N ; n++ ) {  
      var e = 0 ;
      for( var m = 0 ; m < M ; m++ ) {  
        var ix = 0xFFFF & ( k * k * k + n * n + m ) ; 
        var c = 0xFFFF & ( ( n * n + m + 1 ) * r[ ix % l ] + m ) ;  
        ix = c % l12 ;  
        e += ( 0xFFFF & ( c * ( ( ix < l1 ) ? x1[ ix ] : x2[ ix - l1 ] ) ) ) ;
      }
      while( ( 0xFFFF & e ) == 0 ) e = rand() ;
      var E = e ;
      for( var m = 0 ; m < P ; m++ ) {
        if( ( E = 0xFFFF & ( E * e ) ) == 0 ) E = 0xFFFF & ( e + rand() ) ;
      }
      r[ k ] = 0xFFFF & ( r[ k ] + E ) ;    
    }
  } 
  return r ;
}


function TPassword()
{
  this.Data = new Array() ;
  this.InitFromStr = initFromStr ;
  this.InitFromBin = initFromBin ;
  this.LiteHash = liteHash ;
  this.XXLiteHash = xxLiteHash ;

  function initFromStr( s )
  {
    return this.InitFromBin( StrToUtf8( s ) ) ;
  }
  function initFromBin( a )
  {
    var l = a.length ;
    if( ( l & 1 ) != 0 ) a[ l ] = a[ l - 1 ] ;
    this.Data = new Array() ;
    for( var i = 0, j = 0, l = a.length ; i < l ; i += 2, j++ ) {
      this.Data[ j ] = ( a[ i ] & 0xFF ) | ( ( a[ i + 1 ] & 0xFF ) << 8 ) ;
    }
    return this ;
  }
  function liteHash()
  {
    return Entrop( 8, 10, 6, this.Data, null, 4 ) ; 
  }
  function xxLiteHash() { return SAToXX( this.LiteHash() ) ; }
}

function TSVC()
{  
//  this.M = v ;
//  this.W = v ;
//  this.B = v ;
//  this.KW = v ;
//  this.FCRS0 = new Array( 4 ) ;
//  this.FCRS1 = new Array( 4 ) ;
  this.Block = 0 ;
  this.SetStrPswd = setStrPswd ;
  this.SetBinPswd = setBinPswd ;
  this.SetPswd = setPswd ;
  this.WKWHash = wkwHash ;
  this.InitW = initW ;
  this.InitAlgo = initAlgo ;
  this.ProcessBlock = processBlock ;
  this.ProcessData = processData ;
  this.Encrypt = encrypt ;
  this.Decrypt = decrypt ;

  
  function setPswd( pswd )
  {
    this.M = Entrop( 8, 11, 6, pswd.Data, null, 256 ) ;
    this.KW = Entrop( 5, 9, 6, this.M, null, 4 ) ;
  }
  function setStrPswd( s )
  {
    var pswd = new TPassword() ;
    this.SetPswd( pswd.InitFromStr( s ) ) ;
  }
  function setBinPswd( a )
  {
    var pswd = new TPassword() ;
    this.SetPswd( pswd.InitFromBin( a ) ) ;
  }
  function initW( sync )
  {
    this.W = Entrop( 2, 5, 5, this.M, sync, 258 ) ;
    return this.WKW = Entrop( 5, 9, 6, this.W, null, 4 ) ;
  }
  function wkwHash( seed )
  {
    return Entrop( 5, 9, 6, this.WKW, seed, 4 ) ;
  }
  function initAlgo( sync )
  {  
    this.FCRS0 = new Array( 0, 0, 0, 0 ) ;
    this.FCRS1 = new Array( 0, 0, 0, 0 ) ;
    this.InitW( sync ) ;
    this.Block = this.W[ 0 ] ;
    this.B = SAToBA( this.W ) ;
  }
  function q32( r, e0, e1, n, w, b )
  {
    var q = w[ n ] ^ e0 ;
    var i = q & 0xFF, j = 256 + ( ( q >> 8 ) & 0xFF ) ;
    r[ 0 ] = b[ i++ ] ^ b[ j++ ], r[ 1 ] = b[ i++ ] ^ b[ j++ ] ;
    r[ 2 ] = b[ i++ ] ^ b[ j++ ], r[ 3 ] = b[ i ] ^ b[ j ] ;
    i = ( w[ n + 1 ] ^ e1 ) & 0x1FF ;
    r[ 0 ] ^= b[ i ], r[ 1 ] ^= b[ i + 1 ] ;
    r[ 2 ] ^= b[ i + 2 ], r[ 3 ] ^= b[ i + 3 ] ;
  }
  function processBlock( i, j, len )
  {
    var k = this.Block, w = this.W, f0 = this.FCRS0, f1 = this.FCRS1  ;
    var out = this.Out, s = this.In ;
    var ei1 = ( k + w[ k & 0xFF ] + w[ k >> 8 ] ) & 0xFFFF ;
    var e = ( w[ ei1 & 0xFF ] + w[ ei1 >> 8 ] ) & 0xFFFF ;
    var ei0 = 0xFFFF & ( ei1 + e ) ;          

    var ew1 = k + e ;
    var eb2 = ew1 & 0xFF, eb3 = ( ew1 >> 8 ) & 0xFF
    var ew0 = ew1 + w[ eb2 ] + w[ eb3 ] ;
    var eb0 = ew0 & 0xFF, eb1 = ( ew0 >> 8 ) & 0xFF ;
    var r = new Array( 4 ), l = ( len >> 2 ) << 1 ;
    for( var k = 0  ; k < l ; k += 2 ) {
      q32( r, ei0, ei1, k, this.W, this.B ) ;
      f0[ 0 ] += s[ j ]
      f1[ 0 ] += ( out[ i++ ] = s[ j++ ] ^ r[ 0 ] ^ eb0 ) ;
      f0[ 1 ] += s[ j ]
      f1[ 1 ] += ( out[ i++ ] = s[ j++ ] ^ r[ 1 ] ^ eb1 ) ;
      f0[ 2 ] += s[ j ]
      f1[ 2 ] += ( out[ i++ ] = s[ j++ ] ^ r[ 2 ] ^ eb2 ) ;
      f0[ 3 ] += s[ j ]
      f1[ 3 ] += ( out[ i++ ] = s[ j++ ] ^ r[ 3 ] ^ eb3 ) ;
    }
    var n = len & 3 ;
    if( n == 0 ) return ;
    q32( r, ei0, ei1, l, this.W, this.B ) ;
    var eb = new Array( eb0, eb1, eb2 ) ;
    for( var k = 0 ; k < n ; k++ ) {
      f0[ k ] += s[ j ] ;
      f1[ k ] += ( out[ i++ ] = s[ j++ ] ^ r[ k ] ^ eb[ k ] ) ;
    }
  }
  function processData()
  {
    var l = this.In.length, i = 0, bl = 512 ;
    for( ; l >= bl ; l -= bl, i += bl ) {
      this.ProcessBlock( i, i, bl ) ;
      this.Block = 0xFFFF & ( this.Block + 1 ) ;
    }
    this.ProcessBlock( i, i, l ) ;
  }
  function mixFCRS( fcrs ) 
  {
    var x = new Array( 111, 30854, 9007, 873, 5 ) ;
    var f = new Array( fcrs[ 0 ] | ( fcrs[ 1 ] << 8 ),
          fcrs[ 2 ] | ( fcrs[ 3 ] << 8 ) ) ;
    for( var i = 0 ; i < x.length ; i++ ) x[ i ] += ( f[ i % 2 ] + i * 9 ) ;
    var f = Entrop( 3, 5, 5, x, null, 2 ) ;
    return f[ 0 ] | ( f[ 1 ] << 16 ) ;
  }
  function encrypt( out, src, sync )
  {
    this.Out = out, this.In = src ;
    this.InitAlgo( sync ) ;
    this.ProcessData() ;
    return mixFCRS( this.FCRS0 ) ;
  }
  function decrypt( out, src, sync )
  {
    this.Out = out, this.In = src ;
    this.InitAlgo( sync ) ;
    this.ProcessData() ;
    return mixFCRS( this.FCRS1 ) ;
  }
}


function TXXTEA()
{
  this.SetPswd = setPswd ;
  this.SetStrPswd = setStrPswd ;
  this.SetBinPswd = setBinPswd ;
  this.SetXXKey = setXXKey ;
  this.Encrypt = encrypt ;
  this.Decrypt = decrypt ;
  function setPswd( pswd )
  {
    var k, wk = Entrop( 8, 11, 6, pswd.Data, null, 8 ) ;
    k = new Array() ;
    for( var i = 0, m = 0 ; i < 4 ; i++, m += 2 ) {
      k[ i ] = wk[ m ] + ( wk[ m + 1 ] << 16 ) ;
    }
    this.K = k ;
  }
  function setStrPswd( s )
  {
    var pswd = new TPassword() ;
    this.SetPswd( pswd.InitFromStr( s ) ) ;
  }
  function setBinPswd( a )
  {
    var pswd = new TPassword() ;
    this.SetPswd( pswd.InitFromBin( a ) ) ;
  }
  function setXXKey( xxk )
  {
    var xl = ( xxk.length >> 1 ) << 1 ;
    if( xl > 32 ) xl = 32 ;
    this.K = XXToLA( xxk.substr( 0, xl ) ) ;
  }
  function encrypt( t ) // c and t are long
  {
    var n = t.length;
    
    var z, y, delta = 0x9E3779B9, k = this.K, c = new Array() ;
    var mx, e, q = Math.floor( 6 + 52 / n ), sum = 0 ;
    for( var i = 0 ; i < n ; i++ ) c[ i ] = t[ i ] ;
    z = c[ n - 1 ] ;
    while( q-- > 0 ) {  // 6 + 52/n operations gives between 6 & 32 mixes on each word
      sum += delta ;
      e = ( sum >>> 2 ) & 3;
      for( var p = 0 ; p < ( n - 1 ) ; p++ ) {
        y = c[ p + 1 ] ;
        mx = ( ( ( z >>> 5 ) ^ ( y << 2 ) ) + ( ( y >>> 3 ) ^ ( z << 4 ) ) ) ^ 
             ( ( sum ^ y ) + ( k[ ( p & 3 ) ^ e ] ^ z ) ) ;
        z = ( c[ p ] += mx )
      }
      y = c[ 0 ] ;
      mx = ( ( ( z >>> 5 ) ^ ( y << 2 ) ) + ( ( y >>> 3 ) ^ ( z << 4 ) ) ) ^ 
           ( ( sum ^ y ) + ( k[ ( p & 3 ) ^ e ] ^ z ) ) ;
      z = ( c[ n - 1 ] += mx ) ;
    }
    for( var i = 0 ; i < n ; i++ ) c[ i ] = c[ i ] & 0xFFFFFFFF ;
    return c ;
  }
  function decrypt( c ) // c and t are long
  {
    var n = c.length ;
    var z, y, delta = 0x9E3779B9, k = this.K, t = new Array() ;
    var mx, e, q = Math.floor( 6 + 52 / n ), sum = q * delta ;
    for( var i = 0 ; i < n ; i++ ) t[ i ] = c[ i ] ;
    y = t[ 0 ] ;
    while( sum != 0 ) {
      e = ( sum >>> 2 ) & 3 ;
      for( var p = n - 1 ; p > 0 ; p-- ) {
        z = t[ p - 1 ] ;
        mx = ( ( ( z >>> 5 ) ^ ( y << 2 ) ) + ( ( y >>> 3 ) ^ ( z << 4 ) ) ) ^ 
             ( ( sum ^ y ) + ( k[ ( p & 3 ) ^ e ] ^ z ) ) ;
        y = ( t[ p ] -= mx ) ;
      }
      z = t[ n - 1 ]
      mx = ( ( ( z >>> 5 ) ^ ( y << 2 ) ) + ( ( y >>> 3 ) ^ ( z << 4 ) ) ) ^ 
           ( ( sum ^ y ) + ( k[ ( p & 3 ) ^ e ] ^ z ) ) ;
      y = ( t[ 0 ] -= mx ) ;
      sum -= delta;
    }
    for( var i = 0 ; i < n ; i++ ) t[ i ] = 0xFFFFFFFF & t[ i ] ;
    return t ;
  }
}

function XT1Sig() { return new Array( 0x58, 0x54, 0x31 ) ; }

function XT2Sig() { return new Array( 0x58, 0x54, 0x32 ) ; }

function VerifySig( s1, s2 )
{
  var l1 = s1.length, l2 = s2.length ;
  while( l1 > 0 && l2 > 0 ) if( s1[ --l1 ] != s2[ --l2 ] ) return false ;
  return l1 == l2 ;
}

function UnknownSig() { throw new Error( -1001, 'Unknown signature.' ) ; }

function DataDamaged( err ) 
{ 
  if( err ) throw new Error( -1002, 'Data damaged.' ) ; 
}

function TEncryptor()
{
  this.Encrypt = encrypt ;
  this.Decrypt = decrypt ;

  function pack( m )
  {
    var l = m.length, h ;
    h = SAToBA( Entrop( 8, 10, 6, BAToSA( m ), null, 4 ) ) ;
    return h.concat( new Array( l & 0xFF, ( l >> 8 ) & 0xFF ), m ) ;
  } 

  function unpack( pm )
  {
    DataDamaged( pm.length < 10 ) ;
    var ok, h, m, l = pm[ 8 ] + ( pm[ 9 ] << 8 ) ;
    DataDamaged( pm.length < ( l + 10 ) ) ;
    m = pm.splice( 10, l ) ; 
    h = Entrop( 8, 10, 6, BAToSA( m ), null, 4 ) ;
    DataDamaged( BAToXX( pm.splice( 0, 8 ) ) != SAToXX( h ) ) ;
    return m ;
  }

  function encrypt( xxw, xx )
  {
    var m = pack( XXToBA( xx ) ), k = new Array() ;
    for( var i = 0 ; i < 8 ; ) k[ i++ ] = LRandom() ;
    var r = new Array(), svc = new TSVC(), tea = new TXXTEA() ;
    svc.SetBinPswd( LAToBA( k ) ) ;
    svc.Encrypt( r, m, null ) ;
    tea.SetXXKey( xxw ) ;
    k = LAToBA( tea.Encrypt( k ) ) ;
    return BAToXX( XT2Sig().concat( k, r ) ) ;
  }
  function decrypt( xxw, xx )
  {
    var d = XXToBA( xx ), s, k ;
    s = d.splice( 0, 3 ) ;
    k = d.splice( 0, 32 ) ;
    DataDamaged( k.length < 32 ) ;
    if( VerifySig( s, XT2Sig() ) == false ) UnknownSig() ;
    var tea = new TXXTEA() ;
    tea.SetXXKey( xxw ) ;
    k = LAToBA( tea.Decrypt( BAToLA( k ) ) ) ;
    var r = new Array(), svc = new TSVC() ;
    svc.SetBinPswd( k ) ;
    svc.Decrypt( r, d, null ) ;
    return BAToXX( unpack( r ) ) ;
  }
} 

function TReencryptor()
{
  this.SetEncKey = setEncKey ;
  this.SetDecKey = setDecKey ;
  this.Reencrypt = reencrypt ;
  this.Encryptor = new TXXTEA() ;
  this.Decryptor = new TXXTEA() ;
  function setEncKey( xxk ) { this.Encryptor.SetXXKey( xxk ) ; }
  function setDecKey( xxk ) { this.Decryptor.SetXXKey( xxk ) ; }
  function reencrypt( xxrk )
  {
    var d = XXToBA( xxrk ), s, k ;
    s = d.splice( 0, 3 ) ;
    k = d.splice( 0, 32 ) ;
    DataDamaged( k.length < 32 ) ;
    if( VerifySig( s, XT2Sig() ) == false ) UnknownSig() ;
    k = this.Decryptor.Decrypt( BAToLA( k ) ) ;
    k = LAToBA( this.Encryptor.Encrypt( k ) ) ;
    return BAToXX( XT2Sig().concat( k ) ) ;
  }
} 

function CreateSync()
{
  var sync = new Array() ;
  for( var i = 0 ; i < 4 ; i++ ) {
    sync[ i ] = Math.floor( 0x10000 * Math.random() ) ;
  }
  return sync ;
}

function XXCreateSync() { return SAToXX( CreateSync() ) ; }

