advertisement -- please support sponsors

dynamic content, security:
encrypting web pages

How can I encrypt my web pages using JavaScript?

dynamic content

One of the really nice feature about JavaScript is the way it can be used to write text directly into the document as it is being loaded. When a web page without JavaScript is loaded into a browser window, the text is displayed, line by line, as it is received from the server. If the document source has JavaScript embedded in the middle of it, however, the text following the script cannot be displayed until the script has finished executing.

For example, consider the following HTML/JavaScript source:

<big>This text will be visible in your browser <em>before</em> you are prompted for a number.</big> <p> <script> num = null; while (num == null) { num = prompt ("Enter a number:"); num = parseInt (num); if (isNaN (num)) num = null; } for (count = 1; count <= num; ++ count) document . write (count + " "); </script> <p> <big>This text will not be displayed until <em>after</em> the script completes.</big>
When this document is loaded, the text at the beginning of the document, up until the opening <script> tag, is displayed immediately. Then the script begins execution and prompts the user for a number. At this point, the document freezes until the user responds. After the user inputs a number num, the script writes the numbers 1 through num to the document. When the script finishes, the rest of the document is displayed.

This example demonstrates how a web page can ask for user input while it is being loaded and then display content that depends on the user's response. This pattern can be extended so that JavaScript embedded near the top of the web page prompts the user for a password. The user's response can then be used to decrypt the rest of the document.

encrypted source

The code you will see in this section might be completely mind-boggling to you, but don't let it discourage you. You will see a good example of an encrypted document that automatically decrypts itself when loaded into your browser -- provided, of course, that you supply the correct password.

Don't waste a lot of time trying to understand the decryption algorithm; that's not what's important here. What I do want you to notice, however, is the following:

  1. The document begins with an unencrypted header.
  2. A section of script follows, and it contains the following elements:
    1. a decryption function definition (just know that that's what it is; don't try to follow the code)
    2. a string of encrypted text (ciphertext)
    3. a few lines of code that prompt the user for a key
    4. a call to the decryption function using the ciphertext and key as parameters
    5. a write statement that outputs the string returned by the decryption function
  3. The document ends with an unencrypted footer.
Here is the source code. See if you can find all of these elements.
<hr>
begin classified document
<hr>

<script>

function decode (input, key)
{
	var alphabet =   "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	               + "abcdefghijklmnopqrstuvwxyz";

	key = key . toUpperCase ();
	var key_len = key . length;
	var i;
	var adjusted_key = "";
	for (i = 0; i < key_len; i ++)
	{
		var key_char = alphabet . indexOf (key . charAt (i));
		if (key_char < 0)
			continue;
		adjusted_key += alphabet . charAt (key_char);
	}
	key = adjusted_key;
	key_len = key . length;
	if (key_len == 0)
	{
		key = "a";
		key_len = 1;
	}
	var input_len = input . length;
	var output = "";
	var key_index = 0;
	var in_tag = false;
	for (i = 0; i < input_len; i ++)
	{
		var input_char = input . charAt (i);
		if (input_char == "<")
			in_tag = true;
		else if (input_char == ">")
			in_tag = false;
		if (in_tag)
		{
			output += input_char;
			continue;
		}
		var input_char_value = alphabet . indexOf (input_char);
		if (input_char_value < 0)
		{
			output += input_char;
			continue;
		}
		var lowercase = input_char_value >= 26 ? true : false;
		input_char_value -= alphabet . indexOf (key . charAt (key_index));
		input_char_value += 26;
		if (lowercase)
			input_char_value = input_char_value % 26 + 26;
		else
			input_char_value %= 26;
		output += alphabet . charAt (input_char_value);
		key_index = (key_index + 1) % key_len;
	}
	return output;
}

ciphertext =
  "<h1>Voe Wtkgg Scgo qm Mfdxg Przdif Neeplwf</h1>"
+ "<h2>tvstvlr 1</h2>"
+ "<ol>"
+ "<li>Zy mvr ssympuier Zcq tfwevld ksx vrrjwr cud ksx snihz."
+ "<li>Epk typ xoekv oeu dikshig wcjq, cud mzbr; ner vetrnvdl "
+ "knj ihsp ahv qtqr ft llg keva.  Tbq kvw Wrprze ht Tfr "
+ "esxld lahb gys xeel ow eas jrhwvu."
+ "<li>Hnu Rhr frwv, Pga typks ov zakja: aeo mvris oeu sixsm."
+ "</ol>";

key = null;
while (key == null)
	key = prompt ("Enter a decryption key to view this document.");
plaintext = decode (ciphertext, key);
document . write (plaintext);

</script>

<hr>
end classified document
<hr>
Now, unless you have experience with cryptoanalysis, odds are good that you will not be able to learn anything about the encrypted text unless you have the password. You can click HERE to see the document in action (in a separate window). However, you will not see the unencrypted text unless you enter the correct password. The "View Source" command won't help much, either, because the password is not contained in the source and the text is scrambled.
(Hint: The password is the author's first and last name. If you get it wrong, push reload and try again.)
The encryption technique used in this example is called a Vigenere cipher. Although this kind of cipher doesn't stand a chance against experienced cryptoanalysts, it is probably sufficient to keep most people out.

I chose the Vigenere cipher because it was easy to code and good enough to make my point: that JavaScript can be used to decode encrypted documents. This technique makes it possible to protect your web pages from unwelcome visitors.

Of course, you can encrypt your documents with nearly any encryption technique, as long as you are able to write the JavaScript code that decrypts is. To get you started, here is the basic scripting pattern that you should use in JavaScript-decoded web documents:

<script>
// Copy the ciphertext into a string variable:
text = "jdiownvuizsponmwe";

// Obtain a password from the user:
password = get_password ();

// Use the password to unscramble the text.
text = decode (text, password);

// Display the result in the document:
document . write (text);
</script>
When the user's password is correct, decoded text will be written to the browser window. Otherwise, the output will just look like garbage.

If you are going to encrypt more than one document, you should consider storing the decryption function in a separate JavaScript file. You can have it automatically loaded with each document by setting the src property of the <script> tag. See my answer to the question, "How can I use JavaScript functions defined in an external file?" for more information.

One final note: This article was meant to inform you of data security options available through JavaScript -- and to have fun showing off some of the cool things that JavaScript can do. The techniques described in this article, however, are meant for audiences who are not able to configure the authentication protocols built into their web servers. If you are "dead-serious" about protecting your documents, then JavaScript by itself is probably not powerful enough to provide the solution you require.

Charlton Rose
31 Jan. 1997