-
/* – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – */
-
/* Block TEA (xxtea) Tiny Encryption Algorithm implementation in JavaScript */
-
/* (c) Chris Veness 2002-2009: www.movable-type.co.uk/tea-block.html */
-
/* – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – */
-
/* – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – */
-
/* Algorithm: David Wheeler & Roger Needham, Cambridge University Computer Lab */
-
/* http://www.cl./ftp/papers/djw-rmn/djw-rmn-tea.html (1994) */
-
/* http://www.cl./ftp/users/djw3/xtea.ps (1997) */
-
/* http://www.cl./ftp/users/djw3/xxtea.ps (1998) */
-
/* – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – */
-
-
var Tea = {}; // Tea namespace
-
-
/*
-
* encrypt text using Corrected Block TEA (xxtea) algorithm
-
*
-
<span id="more-119"></span>
-
* @param {string} plaintext String to be encrypted (multi-byte safe)
-
* @param {string} password Password to be used for encryption (1st 16 chars)
-
* @returns {string} encrypted text
-
*/
-
Tea.encrypt = function(plaintext, password) {
-
if (plaintext.length == 0) return(”); // nothing to encrypt
-
-
// convert string to array of longs after converting any multi-byte chars to UTF-8
-
var v = Tea.strToLongs(Utf8.encode(plaintext));
-
if (v.length <= 1) v[1] = 0; // algorithm doesn’t work for n<2 so fudge by adding a null
-
// simply convert first 16 chars of password as key
-
var k = Tea.strToLongs(Utf8.encode(password).slice(0,16));
-
var n = v.length;
-
-
// —- —-
-
-
var z = v[n-1], y = v[0], delta = 0x9E3779B9;
-
var mx, e, q = Math.floor(6 + 52/n), sum = 0;
-
-
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; p++) {
-
y = v[(p+1)%n];
-
mx = (z>>>5 ^ y<<2) + (y>>>3 ^ z<<4) ^ (sum^y) + (k[p&3 ^ e] ^ z);
-
z = v[p] += mx;
-
}
-
}
-
-
// —- —-
-
-
var ciphertext = Tea.longsToStr(v);
-
-
return Base64.encode(ciphertext);
-
}
-
-
/*
-
* decrypt text using Corrected Block TEA (xxtea) algorithm
-
*
-
* @param {string} ciphertext String to be decrypted
-
* @param {string} password Password to be used for decryption (1st 16 chars)
-
* @returns {string} decrypted text
-
*/
-
Tea.decrypt = function(ciphertext, password) {
-
if (ciphertext.length == 0) return(”);
-
var v = Tea.strToLongs(Base64.decode(ciphertext));
-
var k = Tea.strToLongs(Utf8.encode(password).slice(0,16));
-
var n = v.length;
-
-
// —- —-
-
-
var z = v[n-1], y = v[0], delta = 0x9E3779B9;
-
var mx, e, q = Math.floor(6 + 52/n), sum = q*delta;
-
-
while (sum != 0) {
-
e = sum>>>2 & 3;
-
for (var p = n-1; p >= 0; p–) {
-
z = v[p>0 ? p-1 : n-1];
-
mx = (z>>>5 ^ y<<2) + (y>>>3 ^ z<<4) ^ (sum^y) + (k[p&3 ^ e] ^ z);
-
y = v[p] -= mx;
-
}
-
sum -= delta;
-
}
-
-
// —- —-
-
-
var plaintext = Tea.longsToStr(v);
-
-
// strip trailing null chars resulting from filling 4-char blocks:
-
plaintext = plaintext.replace(/\0+$/,”);
-
-
return Utf8.decode(plaintext);
-
}
-
-
/* – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – */
-
-
// supporting functions
-
-
Tea.strToLongs = function(s) { // convert string to array of longs, each containing 4 chars
-
// note chars must be within ISO-8859-1 (with Unicode code-point < 256) to fit 4/long
-
var l = new Array(Math.ceil(s.length/4));
-
for (var i=0; i // note little-endian encoding – endianness is irrelevant as long as
-
// it is the same in longsToStr()
-
l[i] = s.charCodeAt(i*4) + (s.charCodeAt(i*4+1)<<8) +
-
(s.charCodeAt(i*4+2)<<16) + (s.charCodeAt(i*4+3)<<24);
-
}
-
return l; // note running off the end of the string generates nulls since
-
} // bitwise operators treat NaN as 0
-
-
Tea.longsToStr = function(l) { // convert array of longs back to string
-
var a = new Array(l.length);
-
for (var i=0; i a[i] = String.fromCharCode(l[i] & 0xFF, l[i]>>>8 & 0xFF,
-
l[i]>>>16 & 0xFF, l[i]>>>24 & 0xFF);
-
}
-
return a.join(”); // use Array.join() rather than repeated string appends for efficiency in IE
-
}
-
-
/* – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – */
-
/* Base64 class: Base 64 encoding / decoding (c) Chris Veness 2002-2009 */
-
/* note: depends on Utf8 class */
-
/* – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – */
-
-
var Base64 = {}; // Base64 namespace
-
-
Base64.code = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
-
-
/**
-
* Encode string into Base64, as defined by RFC 4648 [http://tools./html/rfc4648]
-
* (instance method extending String object). As per RFC 4648, no newlines are added.
-
*
-
* @param {String} str The string to be encoded as base-64
-
* @param {Boolean} [utf8encode=false] Flag to indicate whether str is Unicode string to be encoded
-
* to UTF8 before conversion to base64; otherwise string is assumed to be 8-bit characters
-
* @returns {String} Base64-encoded string
-
*/
-
Base64.encode = function(str, utf8encode) { // http://tools./html/rfc4648
-
utf8encode = (typeof utf8encode == ‘undefined’) ? false : utf8encode;
-
var o1, o2, o3, bits, h1, h2, h3, h4, e=[], pad = ”, c, plain, coded;
-
var b64 = Base64.code;
-
-
plain = utf8encode ? str.encodeUTF8() : str;
-
-
c = plain.length % 3; // pad string to length of multiple of 3
-
if (c > 0) { while (c++ < 3) { pad += ‘=’; plain += ‘\0′; } }
-
// note: doing padding here saves us doing special-case packing for trailing 1 or 2 chars
-
-
for (c=0; c o1 = plain.charCodeAt(c);
-
o2 = plain.charCodeAt(c+1);
-
o3 = plain.charCodeAt(c+2);
-
-
bits = o1<<16 | o2<<8 | o3;
-
-
h1 = bits>>18 & 0x3f;
-
h2 = bits>>12 & 0x3f;
-
h3 = bits>>6 & 0x3f;
-
h4 = bits & 0x3f;
-
-
// use hextets to index into code string
-
e[c/3] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
-
}
-
coded = e.join(”); // join() is far faster than repeated string concatenation in IE
-
-
// replace ‘A’s from padded nulls with ‘=’s
-
coded = coded.slice(0, coded.length-pad.length) + pad;
-
-
return coded;
-
}
-
-
/**
-
* Decode string from Base64, as defined by RFC 4648 [http://tools./html/rfc4648]
-
* (instance method extending String object). As per RFC 4648, newlines are not catered for.
-
*
-
* @param {String} str The string to be decoded from base-64
-
* @param {Boolean} [utf8decode=false] Flag to indicate whether str is Unicode string to be decoded
-
* from UTF8 after conversion from base64
-
* @returns {String} decoded string
-
*/
-
Base64.decode = function(str, utf8decode) {
-
utf8decode = (typeof utf8decode == ‘undefined’) ? false : utf8decode;
-
var o1, o2, o3, h1, h2, h3, h4, bits, d=[], plain, coded;
-
var b64 = Base64.code;
-
-
coded = utf8decode ? str.decodeUTF8() : str;
-
-
for (var c=0; c h1 = b64.indexOf(coded.charAt(c));
-
h2 = b64.indexOf(coded.charAt(c+1));
-
h3 = b64.indexOf(coded.charAt(c+2));
-
h4 = b64.indexOf(coded.charAt(c+3));
-
-
bits = h1<<18 | h2<<12 | h3<<6 | h4;
-
-
o1 = bits>>>16 & 0xff;
-
o2 = bits>>>8 & 0xff;
-
o3 = bits & 0xff;
-
-
d[c/4] = String.fromCharCode(o1, o2, o3);
-
// check for padding
-
if (h4 == 0×40) d[c/4] = String.fromCharCode(o1, o2);
-
if (h3 == 0×40) d[c/4] = String.fromCharCode(o1);
-
}
-
plain = d.join(”); // join() is far faster than repeated string concatenation in IE
-
-
return utf8decode ? plain.decodeUTF8() : plain;
-
}
-
-
/* – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – */
-
/* Utf8 class: encode / decode between multi-byte Unicode characters and UTF-8 multiple */
-
/* single-byte character encoding (c) Chris Veness 2002-2009 */
-
/* – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – */
-
-
var Utf8 = {}; // Utf8 namespace
-
-
/**
-
* Encode multi-byte Unicode string into utf-8 multiple single-byte characters
-
* (BMP / basic multilingual plane only)
-
*
-
* Chars in range U+0080 – U+07FF are encoded in 2 chars, U+0800 – U+FFFF in 3 chars
-
*
-
* @param {String} strUni Unicode string to be encoded as UTF-8
-
* @returns {String} encoded string
-
*/
-
Utf8.encode = function(strUni) {
-
// use regular expressions & String.replace callback function for better efficiency
-
// than procedural approaches
-
var strUtf = strUni.replace(
-
/[\u0080-\u07ff]/g, // U+0080 – U+07FF => 2 bytes 110yyyyy, 10zzzzzz
-
function(c) {
-
var cc = c.charCodeAt(0);
-
return String.fromCharCode(0xc0 | cc>>6, 0×80 | cc&0x3f); }
-
);
-
strUtf = strUtf.replace(
-
/[\u0800-\uffff]/g, // U+0800 – U+FFFF => 3 bytes 1110xxxx, 10yyyyyy, 10zzzzzz
-
function(c) {
-
var cc = c.charCodeAt(0);
-
return String.fromCharCode(0xe0 | cc>>12, 0×80 | cc>>6&0x3F, 0×80 | cc&0x3f); }
-
);
-
return strUtf;
-
}
-
-
/**
-
* Decode utf-8 encoded string back into multi-byte Unicode characters
-
*
-
* @param {String} strUtf UTF-8 string to be decoded back to Unicode
-
* @returns {String} decoded string
-
*/
-
Utf8.decode = function(strUtf) {
-
var strUni = strUtf.replace(
-
/[\u00c0-\u00df][\u0080-\u00bf]/g, // 2-byte chars
-
function(c) { // (note parentheses for precence)
-
var cc = (c.charCodeAt(0)&0x1f)<<6 | c.charCodeAt(1)&0x3f;
-
return String.fromCharCode(cc); }
-
);
-
strUni = strUni.replace(
-
/[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g, // 3-byte chars
-
function(c) { // (note parentheses for precence)
-
var cc = ((c.charCodeAt(0)&0x0f)<<12) | ((c.charCodeAt(1)&0x3f)<<6) | ( c.charCodeAt(2)&0x3f);
-
return String.fromCharCode(cc); }
-
);
-
return strUni;
-
}
-
-
/* – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – */
-
-
普通的tea算法的
-
// use (16 chars of) ‘password’ to encrypt ‘plaintext’
-
-
function encrypt(plaintext, password) {
-
var v = new Array(2), k = new Array(4), s = "", i;
-
-
plaintext = escape(plaintext); // use escape() so only have single-byte chars to encode
-
-
// build key directly from 1st 16 chars of password
-
for (var i=0; i<4; i++) k[i] = Str4ToLong(password.slice(i*4,(i+1)*4));
-
-
for (i=0; i
-
v[0] = Str4ToLong(plaintext.slice(i,i+4)); // … note this is ‘electronic codebook’ mode
-
v[1] = Str4ToLong(plaintext.slice(i+4,i+8));
-
code(v, k);
-
s += LongToStr4(v[0]) + LongToStr4(v[1]);
-
}
-
-
return escCtrlCh(s);
-
// note: if plaintext or password are passed as string objects, rather than strings, this
-
// function will throw an ‘Object doesn’t support this property or method’ error
-
}
-
-
// use (16 chars of) ‘password’ to decrypt ‘ciphertext’ with xTEA
-
-
function decrypt(ciphertext, password) {
-
var v = new Array(2), k = new Array(4), s = "", i;
-
-
for (var i=0; i<4; i++) k[i] = Str4ToLong(password.slice(i*4,(i+1)*4));
-
-
ciphertext = unescCtrlCh(ciphertext);
-
for (i=0; i
-
v[0] = Str4ToLong(ciphertext.slice(i,i+4));
-
v[1] = Str4ToLong(ciphertext.slice(i+4,i+8));
-
decode(v, k);
-
s += LongToStr4(v[0]) + LongToStr4(v[1]);
-
}
-
-
// strip trailing null chars resulting from filling 4-char blocks:
-
s = s.replace(/\0+$/, ”);
-
-
return unescape(s);
-
}
-
-
function code(v, k) {
-
// 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
-
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];
-
// 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)
-
}
-
v[0] = y; v[1] = z;
-
}
-
-
function decode(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;
-
}
-
-
// supporting functions
-
-
function Str4ToLong(s) { // convert 4 chars of s to a numeric long
-
var v = 0;
-
for (var i=0; i<4; i++) v |= s.charCodeAt(i) << i*8; 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;
-
}
-
-
function escCtrlCh(str) { // escape control chars which might cause problems with encrypted texts
-
return str.replace(/[\0\t\n\v\f\r\xa0'"!]/g, function(c) { return ‘!’ + c.charCodeAt(0) + ‘!’; });
-
}
-
-
function unescCtrlCh(str) { // unescape potentially problematic nulls and control characters
-
return str.replace(/!\d\d?\d?!/g, function(c) { return String.fromCharCode(c.slice(1,-1)); });
-
}