WHAT: HTML form with clientside javascript to encrypt/decrypt selected-text in browser editbox.

(Click here to view Live demo)

The code:

<html>

<head>
<title>TEA JavaScript</title>
<meta HTTP-EQUIV="Pragma" CONTENT="no-cache">
<script type="text/javascript">

/**
* WHAT: HTML form with clientside javascript to encrypt/decrypt
* selected-text in browser editbox.
* AUTHOR: GPL(C) Moshahmed/at/gmail
* $Header: c:/cvs/repo/mosh/jscript/tea4.htm,v 1.10 2010-02-06 05:51:36 b Exp $
* Other component Authors as listed below.
**/

/*
 * Blowfish.js from http://dren.ch/js_blowfish/
 * JavaScript encryption module ver. 2.0 by Daniel Rench
 * Based on existing code:
 * Copyright (c) 2003 by Andre Mueller.
 * Init of blowfish constants with a function (init/backup errors)
 * Copyright (c) 2003 by Rainer Wollmann
 * This Object is open source. You can redistribute it and/or modify
 * it under the terms of the Universal General Public License (UGPL).
 * http://www.ugpl.de/
**/
function Blowfish(k){
    if (k.length==0) throw "0 length key";
    this.bf_P=this.Fbf_P();
    this.bf_S0=this.Fbf_S0();
    this.bf_S1=this.Fbf_S1();
    this.bf_S2=this.Fbf_S2();
    this.bf_S3=this.Fbf_S3();

    this.wordbyte0=function(w){return Math.floor(Math.floor(Math.floor(w/256)/256)/256)%256};
    this.wordbyte1=function(w){return Math.floor(Math.floor(w/256)/256)%256};
    this.wordbyte2=function(w){return Math.floor(w/256)%256};
    this.wordbyte3=function(w){return w%256};
    this.key=k; // (k.length>56)?k.substr(0,56):k;
    var j=0;
    for(var i=0;i<18;++i){
        var d=((this.key.charCodeAt(j%this.key.length)*256 +
      this.key.charCodeAt((j+1)%this.key.length))*256 +
      this.key.charCodeAt((j+2)%this.key.length))*256 +
      this.key.charCodeAt((j+3)%this.key.length);
        this.bf_P[i] = this.bf_xor(this.bf_P[i],d);
        j=(j+4)%this.key.length;
    }
    this.key=this.bf_escape(this.key);
    this.xl_par=0x00000000;
    this.xr_par=0x00000000;
    for(var i=0;i<18;i+=2){
        this.encipher();
        this.bf_P[i]=this.xl_par;
        this.bf_P[i+1]=this.xr_par;
    }
    for(j=0;j<256;j+=2){
        this.encipher();
        this.bf_S0[j]=this.xl_par;
        this.bf_S0[j+1]=this.xr_par;
    }
    for(j=0;j<256;j+=2){
        this.encipher();
        this.bf_S1[j]=this.xl_par;
        this.bf_S1[j+1]=this.xr_par;
    }
    for(j=0;j<256;j+=2){
        this.encipher();
        this.bf_S2[j]=this.xl_par;
        this.bf_S2[j+1]=this.xr_par;
    }
    for (j=0;j<256;j+=2){
        this.encipher();
        this.bf_S3[j]=this.xl_par;
        this.bf_S3[j+1]=this.xr_par;
    }
};
Blowfish.prototype.bf_unescape=function(t){
  var r='';
  for(i=0;i<t.length;i++){
    var t1=t.charCodeAt(i++);
    var t2=t.charCodeAt(i);
    if (t1<58) t1-=48;
    else {
      if (t1>96) t1-=87;
      else t1-=55;
    }
    if (t2<58) t2-=48;
    else {
      if (t2>96) t2-=87;
      else t2-=55;
    }
    r+=String.fromCharCode(t1*16+t2);
  }
  return r;
};
Blowfish.prototype.bf_xor = function(w1,w2){
  var r=w1^w2;
  if (r<0)
    r=0xffffffff+1+r;
  return r
};
Blowfish.prototype.bf_escape = function(t){
  var r='';
  for(var i=0;i<t.length;i++){
    var c=t.charCodeAt(i);
    var t1=Math.floor(c/16);
    var t2=c%16;
    if (t1<10) t1+=48;
    else t1+=55;
    if (t2<10) t2+=48;
    else t2+=55;
    r+=String.fromCharCode(t1)+String.fromCharCode(t2);
  }
  return r;
};
Blowfish.prototype.Fbf_P=function(){return [
    0x243f6a88,0x85a308d3,0x13198a2e,0x03707344,0xa4093822,0x299f31d0,
    0x082efa98,0xec4e6c89,0x452821e6,0x38d01377,0xbe5466cf,0x34e90c6c,
    0xc0ac29b7,0xc97c50dd,0x3f84d5b5,0xb5470917,0x9216d5d9,0x8979fb1b
];};
Blowfish.prototype.Fbf_S0=function(){return [
    0xd1310ba6,0x98dfb5ac,0x2ffd72db,0xd01adfb7,0xb8e1afed,0x6a267e96,
    0xba7c9045,0xf12c7f99,0x24a19947,0xb3916cf7,0x0801f2e2,0x858efc16,
    0x636920d8,0x71574e69,0xa458fea3,0xf4933d7e,0x0d95748f,0x728eb658,
    0x718bcd58,0x82154aee,0x7b54a41d,0xc25a59b5,0x9c30d539,0x2af26013,
    0xc5d1b023,0x286085f0,0xca417918,0xb8db38ef,0x8e79dcb0,0x603a180e,
    0x6c9e0e8b,0xb01e8a3e,0xd71577c1,0xbd314b27,0x78af2fda,0x55605c60,
    0xe65525f3,0xaa55ab94,0x57489862,0x63e81440,0x55ca396a,0x2aab10b6,
    0xb4cc5c34,0x1141e8ce,0xa15486af,0x7c72e993,0xb3ee1411,0x636fbc2a,
    0x2ba9c55d,0x741831f6,0xce5c3e16,0x9b87931e,0xafd6ba33,0x6c24cf5c,
    0x7a325381,0x28958677,0x3b8f4898,0x6b4bb9af,0xc4bfe81b,0x66282193,
    0x61d809cc,0xfb21a991,0x487cac60,0x5dec8032,0xef845d5d,0xe98575b1,
    0xdc262302,0xeb651b88,0x23893e81,0xd396acc5,0x0f6d6ff3,0x83f44239,
    0x2e0b4482,0xa4842004,0x69c8f04a,0x9e1f9b5e,0x21c66842,0xf6e96c9a,
    0x670c9c61,0xabd388f0,0x6a51a0d2,0xd8542f68,0x960fa728,0xab5133a3,
    0x6eef0b6c,0x137a3be4,0xba3bf050,0x7efb2a98,0xa1f1651d,0x39af0176,
    0x66ca593e,0x82430e88,0x8cee8619,0x456f9fb4,0x7d84a5c3,0x3b8b5ebe,
    0xe06f75d8,0x85c12073,0x401a449f,0x56c16aa6,0x4ed3aa62,0x363f7706,
    0x1bfedf72,0x429b023d,0x37d0d724,0xd00a1248,0xdb0fead3,0x49f1c09b,
    0x075372c9,0x80991b7b,0x25d479d8,0xf6e8def7,0xe3fe501a,0xb6794c3b,
    0x976ce0bd,0x04c006ba,0xc1a94fb6,0x409f60c4,0x5e5c9ec2,0x196a2463,
    0x68fb6faf,0x3e6c53b5,0x1339b2eb,0x3b52ec6f,0x6dfc511f,0x9b30952c,
    0xcc814544,0xaf5ebd09,0xbee3d004,0xde334afd,0x660f2807,0x192e4bb3,
    0xc0cba857,0x45c8740f,0xd20b5f39,0xb9d3fbdb,0x5579c0bd,0x1a60320a,
    0xd6a100c6,0x402c7279,0x679f25fe,0xfb1fa3cc,0x8ea5e9f8,0xdb3222f8,
    0x3c7516df,0xfd616b15,0x2f501ec8,0xad0552ab,0x323db5fa,0xfd238760,
    0x53317b48,0x3e00df82,0x9e5c57bb,0xca6f8ca0,0x1a87562e,0xdf1769db,
    0xd542a8f6,0x287effc3,0xac6732c6,0x8c4f5573,0x695b27b0,0xbbca58c8,
    0xe1ffa35d,0xb8f011a0,0x10fa3d98,0xfd2183b8,0x4afcb56c,0x2dd1d35b,
    0x9a53e479,0xb6f84565,0xd28e49bc,0x4bfb9790,0xe1ddf2da,0xa4cb7e33,
    0x62fb1341,0xcee4c6e8,0xef20cada,0x36774c01,0xd07e9efe,0x2bf11fb4,
    0x95dbda4d,0xae909198,0xeaad8e71,0x6b93d5a0,0xd08ed1d0,0xafc725e0,
    0x8e3c5b2f,0x8e7594b7,0x8ff6e2fb,0xf2122b64,0x8888b812,0x900df01c,
    0x4fad5ea0,0x688fc31c,0xd1cff191,0xb3a8c1ad,0x2f2f2218,0xbe0e1777,
    0xea752dfe,0x8b021fa1,0xe5a0cc0f,0xb56f74e8,0x18acf3d6,0xce89e299,
    0xb4a84fe0,0xfd13e0b7,0x7cc43b81,0xd2ada8d9,0x165fa266,0x80957705,
    0x93cc7314,0x211a1477,0xe6ad2065,0x77b5fa86,0xc75442f5,0xfb9d35cf,
    0xebcdaf0c,0x7b3e89a0,0xd6411bd3,0xae1e7e49,0x00250e2d,0x2071b35e,
    0x226800bb,0x57b8e0af,0x2464369b,0xf009b91e,0x5563911d,0x59dfa6aa,
    0x78c14389,0xd95a537f,0x207d5ba2,0x02e5b9c5,0x83260376,0x6295cfa9,
    0x11c81968,0x4e734a41,0xb3472dca,0x7b14a94a,0x1b510052,0x9a532915,
    0xd60f573f,0xbc9bc6e4,0x2b60a476,0x81e67400,0x08ba6fb5,0x571be91f,
    0xf296ec6b,0x2a0dd915,0xb6636521,0xe7b9f9b6,0xff34052e,0xc5855664,
    0x53b02d5d,0xa99f8fa1,0x08ba4799,0x6e85076a
];};
Blowfish.prototype.Fbf_S1=function(){return [
    0x4b7a70e9,0xb5b32944,0xdb75092e,0xc4192623,0xad6ea6b0,0x49a7df7d,
    0x9cee60b8,0x8fedb266,0xecaa8c71,0x699a17ff,0x5664526c,0xc2b19ee1,
    0x193602a5,0x75094c29,0xa0591340,0xe4183a3e,0x3f54989a,0x5b429d65,
    0x6b8fe4d6,0x99f73fd6,0xa1d29c07,0xefe830f5,0x4d2d38e6,0xf0255dc1,
    0x4cdd2086,0x8470eb26,0x6382e9c6,0x021ecc5e,0x09686b3f,0x3ebaefc9,
    0x3c971814,0x6b6a70a1,0x687f3584,0x52a0e286,0xb79c5305,0xaa500737,
    0x3e07841c,0x7fdeae5c,0x8e7d44ec,0x5716f2b8,0xb03ada37,0xf0500c0d,
    0xf01c1f04,0x0200b3ff,0xae0cf51a,0x3cb574b2,0x25837a58,0xdc0921bd,
    0xd19113f9,0x7ca92ff6,0x94324773,0x22f54701,0x3ae5e581,0x37c2dadc,
    0xc8b57634,0x9af3dda7,0xa9446146,0x0fd0030e,0xecc8c73e,0xa4751e41,
    0xe238cd99,0x3bea0e2f,0x3280bba1,0x183eb331,0x4e548b38,0x4f6db908,
    0x6f420d03,0xf60a04bf,0x2cb81290,0x24977c79,0x5679b072,0xbcaf89af,
    0xde9a771f,0xd9930810,0xb38bae12,0xdccf3f2e,0x5512721f,0x2e6b7124,
    0x501adde6,0x9f84cd87,0x7a584718,0x7408da17,0xbc9f9abc,0xe94b7d8c,
    0xec7aec3a,0xdb851dfa,0x63094366,0xc464c3d2,0xef1c1847,0x3215d908,
    0xdd433b37,0x24c2ba16,0x12a14d43,0x2a65c451,0x50940002,0x133ae4dd,
    0x71dff89e,0x10314e55,0x81ac77d6,0x5f11199b,0x043556f1,0xd7a3c76b,
    0x3c11183b,0x5924a509,0xf28fe6ed,0x97f1fbfa,0x9ebabf2c,0x1e153c6e,
    0x86e34570,0xeae96fb1,0x860e5e0a,0x5a3e2ab3,0x771fe71c,0x4e3d06fa,
    0x2965dcb9,0x99e71d0f,0x803e89d6,0x5266c825,0x2e4cc978,0x9c10b36a,
    0xc6150eba,0x94e2ea78,0xa5fc3c53,0x1e0a2df4,0xf2f74ea7,0x361d2b3d,
    0x1939260f,0x19c27960,0x5223a708,0xf71312b6,0xebadfe6e,0xeac31f66,
    0xe3bc4595,0xa67bc883,0xb17f37d1,0x018cff28,0xc332ddef,0xbe6c5aa5,
    0x65582185,0x68ab9802,0xeecea50f,0xdb2f953b,0x2aef7dad,0x5b6e2f84,
    0x1521b628,0x29076170,0xecdd4775,0x619f1510,0x13cca830,0xeb61bd96,
    0x0334fe1e,0xaa0363cf,0xb5735c90,0x4c70a239,0xd59e9e0b,0xcbaade14,
    0xeecc86bc,0x60622ca7,0x9cab5cab,0xb2f3846e,0x648b1eaf,0x19bdf0ca,
    0xa02369b9,0x655abb50,0x40685a32,0x3c2ab4b3,0x319ee9d5,0xc021b8f7,
    0x9b540b19,0x875fa099,0x95f7997e,0x623d7da8,0xf837889a,0x97e32d77,
    0x11ed935f,0x16681281,0x0e358829,0xc7e61fd6,0x96dedfa1,0x7858ba99,
    0x57f584a5,0x1b227263,0x9b83c3ff,0x1ac24696,0xcdb30aeb,0x532e3054,
    0x8fd948e4,0x6dbc3128,0x58ebf2ef,0x34c6ffea,0xfe28ed61,0xee7c3c73,
    0x5d4a14d9,0xe864b7e3,0x42105d14,0x203e13e0,0x45eee2b6,0xa3aaabea,
    0xdb6c4f15,0xfacb4fd0,0xc742f442,0xef6abbb5,0x654f3b1d,0x41cd2105,
    0xd81e799e,0x86854dc7,0xe44b476a,0x3d816250,0xcf62a1f2,0x5b8d2646,
    0xfc8883a0,0xc1c7b6a3,0x7f1524c3,0x69cb7492,0x47848a0b,0x5692b285,
    0x095bbf00,0xad19489d,0x1462b174,0x23820e00,0x58428d2a,0x0c55f5ea,
    0x1dadf43e,0x233f7061,0x3372f092,0x8d937e41,0xd65fecf1,0x6c223bdb,
    0x7cde3759,0xcbee7460,0x4085f2a7,0xce77326e,0xa6078084,0x19f8509e,
    0xe8efd855,0x61d99735,0xa969a7aa,0xc50c06c2,0x5a04abfc,0x800bcadc,
    0x9e447a2e,0xc3453484,0xfdd56705,0x0e1e9ec9,0xdb73dbd3,0x105588cd,
    0x675fda79,0xe3674340,0xc5c43465,0x713e38d8,0x3d28f89e,0xf16dff20,
    0x153e21e7,0x8fb03d4a,0xe6e39f2b,0xdb83adf7
];};
Blowfish.prototype.Fbf_S2=function(){return [
    0xe93d5a68,0x948140f7,0xf64c261c,0x94692934,0x411520f7,0x7602d4f7,
    0xbcf46b2e,0xd4a20068,0xd4082471,0x3320f46a,0x43b7d4b7,0x500061af,
    0x1e39f62e,0x97244546,0x14214f74,0xbf8b8840,0x4d95fc1d,0x96b591af,
    0x70f4ddd3,0x66a02f45,0xbfbc09ec,0x03bd9785,0x7fac6dd0,0x31cb8504,
    0x96eb27b3,0x55fd3941,0xda2547e6,0xabca0a9a,0x28507825,0x530429f4,
    0x0a2c86da,0xe9b66dfb,0x68dc1462,0xd7486900,0x680ec0a4,0x27a18dee,
    0x4f3ffea2,0xe887ad8c,0xb58ce006,0x7af4d6b6,0xaace1e7c,0xd3375fec,
    0xce78a399,0x406b2a42,0x20fe9e35,0xd9f385b9,0xee39d7ab,0x3b124e8b,
    0x1dc9faf7,0x4b6d1856,0x26a36631,0xeae397b2,0x3a6efa74,0xdd5b4332,
    0x6841e7f7,0xca7820fb,0xfb0af54e,0xd8feb397,0x454056ac,0xba489527,
    0x55533a3a,0x20838d87,0xfe6ba9b7,0xd096954b,0x55a867bc,0xa1159a58,
    0xcca92963,0x99e1db33,0xa62a4a56,0x3f3125f9,0x5ef47e1c,0x9029317c,
    0xfdf8e802,0x04272f70,0x80bb155c,0x05282ce3,0x95c11548,0xe4c66d22,
    0x48c1133f,0xc70f86dc,0x07f9c9ee,0x41041f0f,0x404779a4,0x5d886e17,
    0x325f51eb,0xd59bc0d1,0xf2bcc18f,0x41113564,0x257b7834,0x602a9c60,
    0xdff8e8a3,0x1f636c1b,0x0e12b4c2,0x02e1329e,0xaf664fd1,0xcad18115,
    0x6b2395e0,0x333e92e1,0x3b240b62,0xeebeb922,0x85b2a20e,0xe6ba0d99,
    0xde720c8c,0x2da2f728,0xd0127845,0x95b794fd,0x647d0862,0xe7ccf5f0,
    0x5449a36f,0x877d48fa,0xc39dfd27,0xf33e8d1e,0x0a476341,0x992eff74,
    0x3a6f6eab,0xf4f8fd37,0xa812dc60,0xa1ebddf8,0x991be14c,0xdb6e6b0d,
    0xc67b5510,0x6d672c37,0x2765d43b,0xdcd0e804,0xf1290dc7,0xcc00ffa3,
    0xb5390f92,0x690fed0b,0x667b9ffb,0xcedb7d9c,0xa091cf0b,0xd9155ea3,
    0xbb132f88,0x515bad24,0x7b9479bf,0x763bd6eb,0x37392eb3,0xcc115979,
    0x8026e297,0xf42e312d,0x6842ada7,0xc66a2b3b,0x12754ccc,0x782ef11c,
    0x6a124237,0xb79251e7,0x06a1bbe6,0x4bfb6350,0x1a6b1018,0x11caedfa,
    0x3d25bdd8,0xe2e1c3c9,0x44421659,0x0a121386,0xd90cec6e,0xd5abea2a,
    0x64af674e,0xda86a85f,0xbebfe988,0x64e4c3fe,0x9dbc8057,0xf0f7c086,
    0x60787bf8,0x6003604d,0xd1fd8346,0xf6381fb0,0x7745ae04,0xd736fccc,
    0x83426b33,0xf01eab71,0xb0804187,0x3c005e5f,0x77a057be,0xbde8ae24,
    0x55464299,0xbf582e61,0x4e58f48f,0xf2ddfda2,0xf474ef38,0x8789bdc2,
    0x5366f9c3,0xc8b38e74,0xb475f255,0x46fcd9b9,0x7aeb2661,0x8b1ddf84,
    0x846a0e79,0x915f95e2,0x466e598e,0x20b45770,0x8cd55591,0xc902de4c,
    0xb90bace1,0xbb8205d0,0x11a86248,0x7574a99e,0xb77f19b6,0xe0a9dc09,
    0x662d09a1,0xc4324633,0xe85a1f02,0x09f0be8c,0x4a99a025,0x1d6efe10,
    0x1ab93d1d,0x0ba5a4df,0xa186f20f,0x2868f169,0xdcb7da83,0x573906fe,
    0xa1e2ce9b,0x4fcd7f52,0x50115e01,0xa70683fa,0xa002b5c4,0x0de6d027,
    0x9af88c27,0x773f8641,0xc3604c06,0x61a806b5,0xf0177a28,0xc0f586e0,
    0x006058aa,0x30dc7d62,0x11e69ed7,0x2338ea63,0x53c2dd94,0xc2c21634,
    0xbbcbee56,0x90bcb6de,0xebfc7da1,0xce591d76,0x6f05e409,0x4b7c0188,
    0x39720a3d,0x7c927c24,0x86e3725f,0x724d9db9,0x1ac15bb4,0xd39eb8fc,
    0xed545578,0x08fca5b5,0xd83d7cd3,0x4dad0fc4,0x1e50ef5e,0xb161e6f8,
    0xa28514d9,0x6c51133c,0x6fd5c7e7,0x56e14ec4,0x362abfce,0xddc6c837,
    0xd79a3234,0x92638212,0x670efa8e,0x406000e0
];};
Blowfish.prototype.Fbf_S3=function(){return [
    0x3a39ce37,0xd3faf5cf,0xabc27737,0x5ac52d1b,0x5cb0679e,0x4fa33742,
    0xd3822740,0x99bc9bbe,0xd5118e9d,0xbf0f7315,0xd62d1c7e,0xc700c47b,
    0xb78c1b6b,0x21a19045,0xb26eb1be,0x6a366eb4,0x5748ab2f,0xbc946e79,
    0xc6a376d2,0x6549c2c8,0x530ff8ee,0x468dde7d,0xd5730a1d,0x4cd04dc6,
    0x2939bbdb,0xa9ba4650,0xac9526e8,0xbe5ee304,0xa1fad5f0,0x6a2d519a,
    0x63ef8ce2,0x9a86ee22,0xc089c2b8,0x43242ef6,0xa51e03aa,0x9cf2d0a4,
    0x83c061ba,0x9be96a4d,0x8fe51550,0xba645bd6,0x2826a2f9,0xa73a3ae1,
    0x4ba99586,0xef5562e9,0xc72fefd3,0xf752f7da,0x3f046f69,0x77fa0a59,
    0x80e4a915,0x87b08601,0x9b09e6ad,0x3b3ee593,0xe990fd5a,0x9e34d797,
    0x2cf0b7d9,0x022b8b51,0x96d5ac3a,0x017da67d,0xd1cf3ed6,0x7c7d2d28,
    0x1f9f25cf,0xadf2b89b,0x5ad6b472,0x5a88f54c,0xe029ac71,0xe019a5e6,
    0x47b0acfd,0xed93fa9b,0xe8d3c48d,0x283b57cc,0xf8d56629,0x79132e28,
    0x785f0191,0xed756055,0xf7960e44,0xe3d35e8c,0x15056dd4,0x88f46dba,
    0x03a16125,0x0564f0bd,0xc3eb9e15,0x3c9057a2,0x97271aec,0xa93a072a,
    0x1b3f6d9b,0x1e6321f5,0xf59c66fb,0x26dcf319,0x7533d928,0xb155fdf5,
    0x03563482,0x8aba3cbb,0x28517711,0xc20ad9f8,0xabcc5167,0xccad925f,
    0x4de81751,0x3830dc8e,0x379d5862,0x9320f991,0xea7a90c2,0xfb3e7bce,
    0x5121ce64,0x774fbe32,0xa8b6e37e,0xc3293d46,0x48de5369,0x6413e680,
    0xa2ae0810,0xdd6db224,0x69852dfd,0x09072166,0xb39a460a,0x6445c0dd,
    0x586cdecf,0x1c20c8ae,0x5bbef7dd,0x1b588d40,0xccd2017f,0x6bb4e3bb,
    0xdda26a7e,0x3a59ff45,0x3e350a44,0xbcb4cdd5,0x72eacea8,0xfa6484bb,
    0x8d6612ae,0xbf3c6f47,0xd29be463,0x542f5d9e,0xaec2771b,0xf64e6370,
    0x740e0d8d,0xe75b1357,0xf8721671,0xaf537d5d,0x4040cb08,0x4eb4e2cc,
    0x34d2466a,0x0115af84,0xe1b00428,0x95983a1d,0x06b89fb4,0xce6ea048,
    0x6f3f3b82,0x3520ab82,0x011a1d4b,0x277227f8,0x611560b1,0xe7933fdc,
    0xbb3a792b,0x344525bd,0xa08839e1,0x51ce794b,0x2f32c9b7,0xa01fbac9,
    0xe01cc87e,0xbcc7d1f6,0xcf0111c3,0xa1e8aac7,0x1a908749,0xd44fbd9a,
    0xd0dadecb,0xd50ada38,0x0339c32a,0xc6913667,0x8df9317c,0xe0b12b4f,
    0xf79e59b7,0x43f5bb3a,0xf2d519ff,0x27d9459c,0xbf97222c,0x15e6fc2a,
    0x0f91fc71,0x9b941525,0xfae59361,0xceb69ceb,0xc2a86459,0x12baa8d1,
    0xb6c1075e,0xe3056a0c,0x10d25065,0xcb03a442,0xe0ec6e0e,0x1698db3b,
    0x4c98a0be,0x3278e964,0x9f1f9532,0xe0d392df,0xd3a0342b,0x8971f21e,
    0x1b0a7441,0x4ba3348c,0xc5be7120,0xc37632d8,0xdf359f8d,0x9b992f2e,
    0xe60b6f47,0x0fe3f11d,0xe54cda54,0x1edad891,0xce6279cf,0xcd3e7e6f,
    0x1618b166,0xfd2c1d05,0x848fd2c5,0xf6fb2299,0xf523f357,0xa6327623,
    0x93a83531,0x56cccd02,0xacf08162,0x5a75ebb5,0x6e163697,0x88d273cc,
    0xde966292,0x81b949d0,0x4c50901b,0x71c65614,0xe6c6c7bd,0x327a140a,
    0x45e1d006,0xc3f27b9a,0xc9aa53fd,0x62a80f00,0xbb25bfe2,0x35bdd2f6,
    0x71126905,0xb2040222,0xb6cbcf7c,0xcd769c2b,0x53113ec0,0x1640e3d3,
    0x38abbd60,0x2547adf0,0xba38209c,0xf746ce76,0x77afa1c5,0x20756060,
    0x85cbfe4e,0x8ae88dd8,0x7aaaf9b0,0x4cf9aa7e,0x1948c25c,0x02fb8a8c,
    0x01c36ae4,0xd6ebe1f9,0x90d4f869,0xa65cdea0,0x3f09252d,0xc208e69f,
    0xb74e6132,0xce77e25b,0x578fdfe3,0x3ac372e6
];};
Blowfish.prototype.encrypt=function(t){
    var t=this.bf_escape(t);
  // pad t to 16 char boundary.
    for(var i=0;i<t.length%16;i++) t+='0';
    var r='';

  // First 16 chars of r will be the encrypted iv4[0=xr_par,1=xl_par] of 64bits.
  // The iv4 in header should be decrypted before use.
  var iv4 = initVector64();
  this.xr_par=iv4[0];
  this.xl_par=iv4[1];
  this.encipher();
  r+=this.wordescape(this.xr_par)+this.wordescape(this.xl_par);

  // Next comes the orig_hmac[16 chars] of escape and padded t, encrypted without iv.
  var orig_hmac = SHA256(t);
  this.xr_par =  parseInt(orig_hmac.substr(0,8), 16);
  this.xl_par = parseInt(orig_hmac.substr(8,8), 16);
  this.encipher();
  r+=this.wordescape(this.xr_par)+this.wordescape(this.xl_par);

    for(var i=0;i<t.length;i+=16){
        this.xr_par=this.wordunescape(t.substr(i,8));
        this.xl_par=this.wordunescape(t.substr(i+8,8));
    this.xr_par ^= iv4[0];
    this.xl_par ^= iv4[1];
        this.encipher();
    iv4[0] ^= this.xr_par;
    iv4[1] ^= this.xl_par;
        r+=this.wordescape(this.xr_par)+this.wordescape(this.xl_par);
    }
    return r;
};
Blowfish.prototype.decrypt=function(t){
    for(var i=0;i<t.length%16;i++) t+='0';
    var r='';

  var iv4 = new Array(2);
  var iv4next = new Array(2);
  var orig_hmac;

    for (var i=0;i<t.length;i+=16){
        this.xr_par = this.wordunescape(t.substr(i,8));
        this.xl_par = this.wordunescape(t.substr(i+8,8));
    iv4next[0] = iv4[0] ^ this.xr_par;
    iv4next[1] = iv4[1] ^ this.xl_par;
        this.decipher();
    if (i==0) { // First block of 64 bits is the encrypted iv4.
      iv4[0] = this.xr_par;
      iv4[1] = this.xl_par;
      continue;
    }
    if (i==16) { // Second block of 64 bits is orig_hmac, encrypted without iv.
      orig_hmac = Number(this.xr_par).toHexStr() + Number(this.xl_par).toHexStr();
      continue;
    }
    this.xr_par ^= iv4[0];
    this.xl_par ^= iv4[1];
    iv4[0] = iv4next[0];
    iv4[1] = iv4next[1];
        r += this.wordescape(this.xr_par) + this.wordescape(this.xl_par);
    }
  check_hmac(orig_hmac,r);
    var s = this.bf_unescape(r);
  return s;
};
Blowfish.prototype.wordescape=function(w){
  // Convert to big-endian hex string
  // e.g. bf = new Blowfish("x");
  //   bf.wordescape(15) = "0F000000"
  //   bf.wordescape(0xdeadbeef) = "EFBEADDE"
  //   bf.wordunescape("0F000000") = 15
    var r='';
    // reverse byteorder for intel systems
    var m=new Array (this.wordbyte0(w),this.wordbyte1(w),this.wordbyte2(w),this.wordbyte3(w));
    for(var i=3;i>=0;i--){
        var t1=Math.floor(m[i]/16);
        var t2=m[i]%16;
        if (t1<10) t1+=48;
        else t1+=55;
        if (t2<10) t2+=48;
        else t2+=55;
        r+=String.fromCharCode(t1)+String.fromCharCode(t2);
    }
    return r;
};
Blowfish.prototype.wordunescape=function(t){
    var r=0;
    // reverse byteorder for intel systems
    for(var i=6;i>=0;i-=2){
        var t1=t.charCodeAt(i);
        var t2=t.charCodeAt(i+1);
        if (t1<58) t1-=48;
        else t1-=55;
        if (t2<58) t2-=48;
        else t2-=55;
        r=r*256+(t1*16+t2);
    }
    return r;
};
Blowfish.prototype.round=function(a,b,n){
    var t=this;
    return(t.bf_xor(a,t.bf_xor(((t.bf_xor((t.bf_S0[t.wordbyte0(b)]+t.bf_S1[t.wordbyte1(b)]),t.bf_S2[t.wordbyte2(b)]))+t.bf_S3[t.wordbyte3(b)]),t.bf_P[n])));
};
// mutate this.xl_par and this.xr_par
Blowfish.prototype.encipher=function(){
    var t=this;
    var Xl=t.xl_par;
    var Xr=t.xr_par;
    Xl=t.bf_xor(Xl,t.bf_P[0]);
    Xr=t.round(Xr,Xl,1);Xl=t.round(Xl,Xr,2);
    Xr=t.round(Xr,Xl,3);Xl=t.round(Xl,Xr,4);
    Xr=t.round(Xr,Xl,5);Xl=t.round(Xl,Xr,6);
    Xr=t.round(Xr,Xl,7);Xl=t.round(Xl,Xr,8);
    Xr=t.round(Xr,Xl,9);Xl=t.round(Xl,Xr,10);
    Xr=t.round(Xr,Xl,11);Xl=t.round(Xl,Xr,12);
    Xr=t.round(Xr,Xl,13);Xl=t.round(Xl,Xr,14);
    Xr=t.round(Xr,Xl,15);Xl=t.round(Xl,Xr,16);
    Xr=t.bf_xor(Xr,t.bf_P[17]);
    t.xl_par=Xr;
    t.xr_par=Xl;
};
Blowfish.prototype.decipher=function(){
    var t=this;
    var Xl=t.xl_par;
    var Xr=t.xr_par;
    Xl=t.bf_xor(Xl,t.bf_P[17]);
    Xr=t.round(Xr,Xl,16);Xl=t.round(Xl,Xr,15);
    Xr=t.round(Xr,Xl,14);Xl=t.round(Xl,Xr,13);
    Xr=t.round(Xr,Xl,12);Xl=t.round(Xl,Xr,11);
    Xr=t.round(Xr,Xl,10);Xl=t.round(Xl,Xr,9);
    Xr=t.round(Xr,Xl,8);Xl=t.round(Xl,Xr,7);
    Xr=t.round(Xr,Xl,6);Xl=t.round(Xl,Xr,5);
    Xr=t.round(Xr,Xl,4);Xl=t.round(Xl,Xr,3);
    Xr=t.round(Xr,Xl,2);Xl=t.round(Xl,Xr,1);
    Xr=t.bf_xor(Xr,t.bf_P[0]);
    t.xl_par=Xr;
    t.xr_par=Xl;
};
// End of Blowfish
</script>

<script type="text/javascript">
/** Base64 encode / decode
*  http://www.webtoolkit.info/
**/
var Base64 = {
    // private property
    _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
 
    // public method for encoding
    encode : function (input) {
        var output = "";
        var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
        var i = 0;
 
        input = Base64._utf8_encode(input);
 
        while (i < input.length) {
 
            chr1 = input.charCodeAt(i++);
            chr2 = input.charCodeAt(i++);
            chr3 = input.charCodeAt(i++);
 
            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
            enc4 = chr3 & 63;
 
            if (isNaN(chr2)) {
                enc3 = enc4 = 64;
            } else if (isNaN(chr3)) {
                enc4 = 64;
            }
            output = output +
            this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
            this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
        }
        return output;
    },
 
    // public method for decoding
    decode : function (input) {
        var output = "";
        var chr1, chr2, chr3;
        var enc1, enc2, enc3, enc4;
        var i = 0;
 
        input = input.replace(/[^A-Za-z0-9+/=]/g, "");
 
        while (i < input.length) {
            enc1 = this._keyStr.indexOf(input.charAt(i++));
            enc2 = this._keyStr.indexOf(input.charAt(i++));
            enc3 = this._keyStr.indexOf(input.charAt(i++));
            enc4 = this._keyStr.indexOf(input.charAt(i++));
 
            chr1 = (enc1 << 2) | (enc2 >> 4);
            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
            chr3 = ((enc3 & 3) << 6) | enc4;
 
            output = output + String.fromCharCode(chr1);
            if (enc3 != 64) {
                output = output + String.fromCharCode(chr2);
            }
            if (enc4 != 64) {
                output = output + String.fromCharCode(chr3);
            }
        }
        output = Base64._utf8_decode(output);
        return output;
    },
 
    // private method for UTF-8 encoding
    _utf8_encode : function (string) {
        string = string.replace(/ /g," ");
        var utftext = "";
 
        for (var n = 0; n < string.length; n++) {
 
            var c = string.charCodeAt(n);
 
            if (c < 128) {
                utftext += String.fromCharCode(c);
            }
            else if((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            }
            else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }
        }
        return utftext;
    },
 
    // private method for UTF-8 decoding
    _utf8_decode : function (utftext) {
        var string = "";
        var i = 0;
        var c = c1 = c2 = 0;
 
        while ( i < utftext.length ) {
            c = utftext.charCodeAt(i);
            if (c < 128) {
                string += String.fromCharCode(c);
                i++;
            }
            else if((c > 191) && (c < 224)) {
                c2 = utftext.charCodeAt(i+1);
                string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
                i += 2;
            }
            else {
                c2 = utftext.charCodeAt(i+1);
                c3 = utftext.charCodeAt(i+2);
                string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
                i += 3;
            }
        }
        return string;
    }
}
</script>

<script type="text/javascript">
/** Secure Hash Algorithm (SHA256)
*  http://www.webtoolkit.info/
*  Original code by Angel Marin, Paul Johnston.
**/
function SHA256(s) {
    var chrsz   = 8;
    var hexcase = 0;
 
    function safe_add (x, y) {
      var lsw = (x & 0xFFFF) + (y & 0xFFFF);
      var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
      return (msw << 16) | (lsw & 0xFFFF);
    }
 
    function S (X, n) { return ( X >>> n ) | (X << (32 - n)); }
    function R (X, n) { return ( X >>> n ); }
    function Ch(x, y, z) { return ((x & y) ^ ((~x) & z)); }
    function Maj(x, y, z) { return ((x & y) ^ (x & z) ^ (y & z)); }
    function Sigma0256(x) { return (S(x, 2) ^ S(x, 13) ^ S(x, 22)); }
    function Sigma1256(x) { return (S(x, 6) ^ S(x, 11) ^ S(x, 25)); }
    function Gamma0256(x) { return (S(x, 7) ^ S(x, 18) ^ R(x, 3)); }
    function Gamma1256(x) { return (S(x, 17) ^ S(x, 19) ^ R(x, 10)); }
 
    function core_sha256 (m, l) {
      var K = new Array(0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786, 0xFC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x6CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2);
      var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19);
      var W = new Array(64);
      var a, b, c, d, e, f, g, h, i, j;
      var T1, T2;
 
      m[l >> 5] |= 0x80 << (24 - l % 32);
      m[((l + 64 >> 9) << 4) + 15] = l;
 
      for ( var i = 0; i<m.length; i+=16 ) {
        a = HASH[0];
        b = HASH[1];
        c = HASH[2];
        d = HASH[3];
        e = HASH[4];
        f = HASH[5];
        g = HASH[6];
        h = HASH[7];
 
        for ( var j = 0; j<64; j++) {
          if (j < 16) W[j] = m[j + i];
          else W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]);
 
          T1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]);
          T2 = safe_add(Sigma0256(a), Maj(a, b, c));
 
          h = g;
          g = f;
          f = e;
          e = safe_add(d, T1);
          d = c;
          c = b;
          b = a;
          a = safe_add(T1, T2);
        }
 
        HASH[0] = safe_add(a, HASH[0]);
        HASH[1] = safe_add(b, HASH[1]);
        HASH[2] = safe_add(c, HASH[2]);
        HASH[3] = safe_add(d, HASH[3]);
        HASH[4] = safe_add(e, HASH[4]);
        HASH[5] = safe_add(f, HASH[5]);
        HASH[6] = safe_add(g, HASH[6]);
        HASH[7] = safe_add(h, HASH[7]);
      }
      return HASH;
    }
 
    function str2binb(str) {
      var bin = Array();
      var mask = (1 << chrsz) - 1;
      for(var i = 0; i < str.length * chrsz; i += chrsz) {
        bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i%32);
      }
      return bin;
    }
 
    function Utf8Encode(string) {
      string = string.replace(/ /g," ");
      var utftext = "";
      for (var n = 0; n < string.length; n++) {
        var c = string.charCodeAt(n);
        if (c < 128) {
          utftext += String.fromCharCode(c);
        }
        else if((c > 127) && (c < 2048)) {
          utftext += String.fromCharCode((c >> 6) | 192);
          utftext += String.fromCharCode((c & 63) | 128);
        }
        else {
          utftext += String.fromCharCode((c >> 12) | 224);
          utftext += String.fromCharCode(((c >> 6) & 63) | 128);
          utftext += String.fromCharCode((c & 63) | 128);
        }
      }
      return utftext;
    }
 
    function binb2hex (binarray) {
      var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
      var str = "";
      for(var i = 0; i < binarray.length * 4; i++) {
        str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
        hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8  )) & 0xF);
      }
      return str;
    }
    s = Utf8Encode(s);
    return binb2hex(core_sha256(str2binb(s), s.length * chrsz));
}
</script>

<script type="text/javascript">
// 'Extended' Tiny Encryption Algorithm (TEA)
function code_tea(v, k) {
  // Algorithm: David Wheeler & Roger Needham, Cambridge University Computer Lab
  //            http://www.cl.cam.ac.uk/ftp/papers/djw-rmn/djw-rmn-tea.html (1994)
  //            http://www.cl.cam.ac.uk/ftp/users/djw3/xtea.ps (1997)
  // JavaScript implementation: Chris Veness, Movable Type Ltd: www.movable-type.co.uk
  //
  // Extended TEA: this is the 1997 revised version of Needham & Wheeler''s algorithm
  // params: v[2] 64-bit value block; k[4] 128-bit key
  // Note: unsigned right-shift '>>>' is used in place of original '>>', due to lack
  // of 'unsigned' type declaration in JavaScript (thanks to Karsten Kraus for this)
  var y = v[0], z = v[1];
  var delta = 0x9E3779B9, limit = delta*32, sum = 0;

  while (sum != limit) {
    y += (z<<4 ^ z>>>5)+z ^ sum+k[sum & 3];
    sum += delta;
    z += (y<<4 ^ y>>>5)+y ^ sum+k[sum>>>11 & 3];
  }
  v[0] = y; v[1] = z;
}

function decode_tea(v, k) {
  var y = v[0], z = v[1];
  var delta = 0x9E3779B9, sum = delta*32;

  while (sum != 0) {
    z -= (y<<4 ^ y>>>5)+y ^ sum+k[sum>>>11 & 3];
    sum -= delta;
    y -= (z<<4 ^ z>>>5)+z ^ sum+k[sum & 3];
  }
  v[0] = y; v[1] = z;
}

function Str4ToLong(s) {  // convert 4 chars of s to a numeric long
  var v = s.charCodeAt(0) +
    (s.charCodeAt(1)<<8) +
    (s.charCodeAt(2)<<16) +
    (s.charCodeAt(3)<<24);
  return(isNaN(v) ? 0 : v);
}

function LongToStr4(v) { // convert a numeric long to 4 char string
  var s = String.fromCharCode(v & 0xFF, v>>8 & 0xFF, v>>16 & 0xFF, v>>24 & 0xFF);
  return(s);
}

Number.prototype.toHexStr = function() {
  // From http://www.movable-type.co.uk/scripts/sha1.html
  // extend Number class with a tailored hex-string method
  //   (note toString(16) is implementation-dependant, and
  //   in IE returns signed numbers when used on full words)
  //
    var s="", v;
    for (var i=7; i>=0; i--) {
      v = (this>>>(i*4)) & 0xf; s += v.toString(16);
    }
    return s;
}           
 
</script>
 
<script type="text/javascript">
function initVector64() {
  // Generate a random init vector for cbc encryption.
  var iv4 = new Array(2);
  iv4[0] = randomFromEntropyPool();
  iv4[1] = randomFromEntropyPool();
  return iv4;
}

function salt8(padding) {
  // Return random 8 hex digits as salt to concatenate to password.
  var salt = Number(randomFromEntropyPool()).toHexStr();
  return salt;
}

function strengthen_key(key, salt) {
  //  Add salt to password and hash it mutliple times.
  document.eform.password_salt.value = salt;
  document.eform.password_checksum.value = SHA256(key).substr(0,8);

  var key_strengthening_rounds = 1000;
  key += salt;
  for(var keyround = 0; keyround < key_strengthening_rounds; keyround++) {
    key = SHA256(key);
  }
  //return key;   // 256 bit password
  return key.substr(0,16); // 64 bit password only
}

function sha2TeaKey(key) {
  // Convert SHA256 key to 128 bits in k[4].
    var k = new Array(4);
    for (i=0; i < k.length; i++) {
      k[i] = parseInt(key.substr(i*8, 8), 16);
    }
    return k;
}

var version_mosh = '01';
var version_blowfish = 'b1';
var version_tea = 't1';

function encrypt_value(val, key) {
  // Returns: header + etext =
  //   version_mosh[2 char] + malgo[2 char] + salt[8 char] +
  //   base64(encrypted(iv[16] + val)).
  var salt = salt8(8);
  var skey = strengthen_key(key, salt);
  var malgo;
  var etext;
  var orig_hmac = SHA256(val);

  if (enc_algo_name() == 'blowfish') {
    malgo = version_blowfish;
    bf = new Blowfish(skey);
    etext = bf.encrypt(val);
  } else {
    // TEA
    malgo = version_tea;
    var k = sha2TeaKey(skey);
    var v = new Array(2), s = "", i;
    val = escape(val);  // use escape() so only have single-byte chars to encode

    // The output header is iv4 64 bit encrypted with k.
    // The iv4 in header should be decrypted with k before use.
    var iv4 = initVector64();
    v[0]=iv4[0];
    v[1]=iv4[1];
    code_tea(v, k);
    s += LongToStr4(v[0]) + LongToStr4(v[1]);

    // Next 64 bits are encrypted orig_hmac, without iv.
    v[0] = parseInt(orig_hmac.substr(0,8), 16);
    v[1] = parseInt(orig_hmac.substr(8,8), 16);
    code_tea(v, k);

    s += LongToStr4(v[0]) + LongToStr4(v[1]);

    for (i=0; i<val.length; i+=8) {  // encode val into s in 64-bit (8 char) blocks
      v[0] = Str4ToLong(val.substr(i,4));
      v[1] = Str4ToLong(val.substr(i+4,4));
      v[0] ^= iv4[0];
      v[1] ^= iv4[1];
      code_tea(v, k);
      iv4[0] ^= v[0];
      iv4[1] ^= v[1];
      s += LongToStr4(v[0]) + LongToStr4(v[1]);
    }
    //  return(s)       // deleted NVS  2005.04.27
    // return(Base64.encode(escape(s))) // corrected NVS 2005.04.27
    etext = Base64.encode(escape(s));
    // note: if val or key are passed as string objects, rather than strings, this
    // function will throw an 'Object does not support this property or method' error
  }
  return version_mosh + ',' + malgo + ',' + salt + ',' + etext;
}

function decrypt_value(val, key) {
  // Input: val is header + etext =
  //   vversion, malgo, salt, base64(encrypted(iv[16] + val)).
  // Returns decrypted(salt+val, sha256(key+salt)).
  // Remove the header and look for the version and algorithm to use.
  var header = val.replace(/^{(.*)}$/, '$1').split(',');
  var vversion = header[0];
  var malgo = header[1];
  var salt = header[2];
  val = header[3];
  var skey = strengthen_key(key, salt);

  if (vversion != version_mosh) {
    alert("Text encrypted with version " + version_mosh + ", " +
      "but you are using version " + vversion + ", " +
      "trying to decrypt anyway.");
  }

  if (malgo == version_blowfish) {
    bf = new Blowfish(skey);
    val = bf.decrypt(val);
    val = strip_trailing_null(val);
    return val;
  } else if (malgo == version_tea) {
    var k = sha2TeaKey(skey);
    var v = new Array(2), s = "", i;

    val = Base64.decode(val);
    val = unescape(val); // corrected NVS 2005.04.27
    var iv4 = new Array(2);
    var orig_hmac;
    var iv4next = new Array(2);

    for (i=0; i < val.length; i+=8) {  // decode val into s in 64-bit (8 char) blocks
      v[0] = Str4ToLong(val.substr(i,4));
      v[1] = Str4ToLong(val.substr(i+4,4));
      iv4next[0] = iv4[0] ^ v[0];
      iv4next[1] = iv4[1] ^ v[1];
      decode_tea(v, k);
      if (i==0) { // First 64 bit block is encrypted iv4.
        iv4[0]  = v[0];
        iv4[1]  = v[1];
        continue;
      }
      if (i==8) { // Second 64 bit block is sha256(message) prefix.
         orig_hmac = Number(v[0]).toHexStr() + Number(v[1]).toHexStr();
         continue;
      }
      v[0] ^= iv4[0];
      v[1] ^= iv4[1];
      iv4[0] = iv4next[0];
      iv4[1] = iv4next[1];
      s += LongToStr4(v[0]) + LongToStr4(v[1]);
    }

    s = strip_trailing_null(s);
    s = unescape(s);
    check_hmac(orig_hmac,s);
    return s;
  } else {
    alert('cannot decrypt algo ' + malgo + ' in header, ' +
      ' only ' + version_blowfish + ' and ' + version_tea + ' are supported.');
  }
}

function check_hmac(orig_sha, s) {
  // Warn if the message was tampered.
  // Compare checksum of decrypted string s with, checksum (hmac) in the message.
  var new_sha = SHA256(s).substr(0,16);
  if (orig_sha != new_sha) {
    alert("message changed, original hmac " + orig_sha + " != hmac " + new_sha);
  }
}

function strip_trailing_null(s) {
  // strip trailing null chars resulting from filling 4-char blocks
  if (s.indexOf("x00") != -1) {
    s = s.substr(0, s.indexOf("x00"));
  }
  return s;
}


function encrypt_selection2(str, do_enc) {
  // handle both encrypt and decrypt.
  var eform_passphrase = document.getElementById("eform_id").passphrase.value
  if (do_enc) {
    if (str == "") {
      alert("Please select some text to encrypt");
    } else {
      str = "{" + encrypt_value(str, eform_passphrase) + "}";
    }
  } else {
    if (str.match("^{.*}$")) {
      str = str.replace(/^{(.*)}$/, "$1");
      str = decrypt_value(str, eform_passphrase);
    } else {
      alert("Must select both parenthesis to {decrypt enclosed text}");
    }
  }
  return str;
}

function enc_algo_name() {
  // Returns the enc_algo.value selected by the user in radio button.
  var algo = 'tea';
  var eform_id = document.getElementById("eform_id");
  for (var i=0; i < eform_id.enc_algo.length; i++) {
    if (eform_id.enc_algo[i].checked) {
      algo  = eform_id.enc_algo[i].value;
    }
  }
  return algo;
}

function encrypt_selection(do_enc) {
  // handle both browers.
  var ta = document.getElementById("testtextarea");
  var eform_passphrase = document.getElementById("eform_id").passphrase.value
   if (eform_passphrase.match("s$")) {
     alert("Your password has trailing spaces");
   }
   // IE or Firefox?
   if (document.selection) {
      str = document.selection.createRange().text
      str = encrypt_selection2(str, do_enc);
      if (typeof(str) != "undefined") {
        document.selection.createRange().text = str;
      }
      return true;
   }
   else if (ta.selectionStart >= 0) {
      var startPos = ta.selectionStart;
      var endPos = ta.selectionEnd;
      var str = ta.value.substring(startPos, endPos);
      str = encrypt_selection2(str, do_enc);
      if (typeof(str) != "undefined") {
        ta.value = ta.value.substring(0, startPos) + str + ta.value.substring(endPos, ta.value.length);
      }
      return true;
   }
   else {
      return false;
   }
}