2 * Aes encryption for PmWiki recipe AesCrypt
5 * http://submodal.googlecode.com
6 * http://www.pmwiki.org/wiki/Cookbook/DesCrypt
7 * http://www.pmwiki.org/wiki/Cookbook/AesCrypt
8 * http://the-stickman.com/web-development/javascript/finding-selection-cursor-position-in-a-textarea-in-internet-explorer/
16 * Mode of work. Either ['enc', start, end] or ['dec',block_id];
23 AesCrypt.title = null;
26 * is popup element created?
28 AesCrypt.popupDiv = false;
31 * create hidden modal box for encryption
33 AesCrypt.createPopup = function ()
35 if (!AesCrypt.popupDiv) {
36 var popup = '<div id=\'aescrypt_o\' class=\'aescrypt_overlay\'>'
38 + '<img onclick=\'AesCrypt.hideDialog()\' width=\'24\' height=\'24\' title=\'close dialog\' alt=\'close dialog\' id=\'aescrypt_i\' src=\''+AesCrypt.PubDirUrl+'/close.png\' />'
39 + '<p id=\'aescrypt_l\'>Enter password:</p>'
40 + '<form id=\'aescrypt_f\' onsubmit=\'AesCrypt.overlaySubmit();return false;\'>'
41 + '<span><input type=\'password\' name=\'aescrypt_p\' id=\'aescrypt_p\' onkeypress=\'AesCrypt.hidePass()\' /> '
42 + '<img onmousedown=\'AesCrypt.showPass()\' style=\'vertical-align:bottom\' onmouseup=\'AesCrypt.hidePass()\' onmouseout=\'AesCrypt.hidePass()\' onmouseover=\'AesCrypt.hidePass()\' width=\'24\' height=\'24\' alt=\'Show password\' title=\'Show password\' id=\'aescrypt_sp\' src=\''+AesCrypt.PubDirUrl+'/showpass.png\' />'
44 + '<label title=\'All encrypted texts on this page will be decrypted.\' id=\'aescrypt_all\'><input type=\"checkbox\" name=\"aescrypt_allb\" id=\"aescrypt_allb\" checked=\"checked\" value=\"true\" /> decrypt all</label>'
46 + '<input type=\'submit\' />'
47 + '</form>' + '</div>' + '</div>';
49 var theBody = document.getElementsByTagName('body')[0];
50 var popmask = document.createElement('div');
51 popmask.id = 'aescrypt_m';
52 var popcont = document.createElement('div');
53 popcont.id = 'aescrypt_x';
54 popcont.innerHTML = popup;
56 theBody.appendChild(popmask);
57 theBody.appendChild(popcont);
59 AesCrypt.popupDiv = true;
64 * Retrieve password and clear password box.
66 AesCrypt.getPassword = function ()
68 var pwel = document.getElementById('aescrypt_p');
76 * Display modal dialog.
78 AesCrypt.showDialog = function(label, decmode)
80 document.getElementById('aescrypt_o').style.visibility = 'visible';
81 document.getElementById('aescrypt_m').style.visibility = 'visible';
82 document.getElementById('aescrypt_all').style.visibility = (decmode ? 'visible' : 'hidden');
83 document.getElementById('aescrypt_l').childNodes[0].nodeValue = label;
84 AesCrypt.title = label;
86 var pw = document.getElementById('aescrypt_p');
90 AesCrypt.addEvent(window, 'keyup', AesCrypt.onEscPress);
96 AesCrypt.hideDialog = function()
98 document.getElementById('aescrypt_o').style.visibility = 'hidden';
99 document.getElementById('aescrypt_m').style.visibility = 'hidden';
100 document.getElementById('aescrypt_all').style.visibility = 'inherit';
101 document.getElementById('aescrypt_l').childNodes[0].nodeValue = 'Enter password:';
103 AesCrypt.removeEvent(window, 'keyup', AesCrypt.onEscPress, false);
107 AesCrypt.addEvent = function (obj, evType, fn)
109 if (obj.addEventListener){
110 obj.addEventListener(evType, fn, false);
113 else if (obj.attachEvent) {
114 var r = obj.attachEvent('on'+evType, fn);
121 AesCrypt.removeEvent = function(obj, evType, fn, useCapture)
123 if (obj.removeEventListener){
124 obj.removeEventListener(evType, fn, useCapture);
126 } else if (obj.detachEvent){
127 var r = obj.detachEvent('on'+evType, fn);
130 alert('Handler could not be removed');
134 AesCrypt.onEscPress = function(e)
138 if (e.keyCode == 27) {
139 AesCrypt.hideDialog();
146 * display modal box for encryption
148 AesCrypt.encPopup = function()
150 AesCrypt.mode = AesCrypt.saveSelection();
152 //alert("selection: " + AesCrypt.mode);
154 if (!AesCrypt.mode) {
155 alert('Please select text to encrypt');
159 AesCrypt.createPopup();
161 document.getElementById('aescrypt_p').value = '';
163 AesCrypt.showDialog("Encrypt selected text", false);
168 * display modal box for decryption
170 AesCrypt.decPopup = function(id)
172 AesCrypt.mode = ['dec',id];
174 AesCrypt.createPopup();
176 document.getElementById('aescrypt_p').value = '';
178 var c = document.getElementById('aescrypt_c_'+id).childNodes[0].nodeValue;
180 c = c.substr(0,29) + "\u2026";
182 AesCrypt.showDialog("Decrypt " + c, true);
185 AesCrypt.showPass = function()
187 var pwel = document.getElementById('aescrypt_p');
190 document.getElementById('aescrypt_l').childNodes[0].nodeValue = "Password is: "+pw;
194 AesCrypt.hidePass = function()
196 if (AesCrypt.title) {
197 document.getElementById('aescrypt_l').childNodes[0].nodeValue = AesCrypt.title;
202 AesCrypt.overlaySubmit = function()
204 var pw = AesCrypt.getPassword();
206 AesCrypt.hideDialog();
209 alert("No password given!");
213 if (!AesCrypt.mode) {
214 alert('Nothing to do.');
216 else if (AesCrypt.mode[0] == 'enc') {
217 AesCrypt.encSubmit(pw);
219 else if (AesCrypt.mode[0] == 'dec') {
220 AesCrypt.decSubmit(pw);
223 alert('Unknown action: '+AesCrypt.mode[0]);
225 AesCrypt.mode = null;
229 * Function invoked on submit of password modal dialog.
230 * Performs decryption.
232 AesCrypt.decSubmit = function(password)
235 var allEl = document.getElementById('aescrypt_allb');
237 var i = AesCrypt.mode[1];
241 to = 10000; // just some big number
245 var contentel = document.getElementById('aescrypt_c_'+i);
249 if (contentel.style.display == 'none') {
250 var cipher = contentel.childNodes[0].nodeValue;
251 var plain = AesCtr.decrypt(cipher,password,256);
252 if (plain.charAt(plain.length-1) != ' ') {
253 alert ("Invalid password for cipher #"+i);
256 var plainTrim = plain.replace(/\s\s*$/, '');
257 contentel.childNodes[0].nodeValue = plainTrim;
258 contentel.style.display='block';
259 var linkel = document.getElementById('aescrypt_a_'+i);
261 alert("Cipher block not found: id="+i);
263 linkel.style.visibility='hidden';
264 linkel.style.display='none';
273 * Hide modal box and encrypt selection
275 AesCrypt.encSubmit = function(password)
277 var tpart = AesCrypt.getSelection();
279 var padding = AesCrypt.AesCryptPadding;
280 var tarr = AesCrypt.AesCryptCipherToken;
281 var markup_end = AesCrypt.AesCryptEndToken;
283 while ((tpart.length % padding) > 0) {
284 tpart = tpart.concat(' ');
286 tpart = tpart.concat(' ');
288 tarr +=AesCtr.encrypt(tpart, password, 256);
292 AesCrypt.replaceSelection(tarr);
296 * Get selection to be encrypted (selection mode)
298 AesCrypt.saveSelection = function()
300 var textarea = document.getElementById('text');
302 if (document.selection) { // IE variant
305 var range = document.selection.createRange();
306 var stored_range = range.duplicate();
307 stored_range.moveToElementText(textarea);
308 stored_range.setEndPoint( 'EndToEnd', range );
309 var start = stored_range.text.length - range.text.length;
310 var end = start + range.text.length;
312 var sel = textarea.value.substring(start, end);
313 var st = textarea.value.substring(0,start);
314 var et = textarea.value.substring(end);
315 return ['enc', st, sel, et];
318 var start = textarea.selectionStart;
319 var end = textarea.selectionEnd;
321 var sel = textarea.value.substring(start, end);
322 var st = textarea.value.substring(0,start);
323 var et = textarea.value.substring(end);
324 return ['enc', st, sel, et];
332 AesCrypt.getSelection = function()
334 return AesCrypt.mode[2];
337 AesCrypt.replaceSelection = function(replacement)
339 var textarea = document.getElementById('text');
340 var start = AesCrypt.mode[1];
341 var end = AesCrypt.mode[3];
342 textarea.value = start + replacement + end;