Peter Billam

NAME

Tea_JS.pm - The Tiny Encryption Algorithm in Perl and JavaScript

SYNOPSIS

Usage:

 use Crypt::Tea_JS;
 $key = 'PUFgob$*LKDF D)(F IDD&P?/';
 $ascii_cyphertext = encrypt($plaintext, $key);
 ...
 $plaintext_again = decrypt($ascii_cyphertext, $key);
 ...
 $signature = asciidigest($text);

In CGI scripts:

 use Crypt::Tea_JS;
 print tea_in_javascript();
 # now the browser can encrypt and decrypt ! In JS:
 var ascii_ciphertext = encrypt (plaintext, key);
 var plaintext_again  = decrypt (ascii_ciphertext, key);
 var signature = asciidigest (text);

DESCRIPTION

This module implements TEA, the Tiny Encryption Algorithm, and some Modes of Use, in Perl and JavaScript.

The $key is a sufficiently longish string; at least 17 random 8-bit bytes for single encryption.

Crypt::Tea_JS can be used for secret-key encryption in general, or, in particular, to communicate securely between browser and web-host. In this case, the simplest arrangement is for the user to enter the key into a JavaScript variable, and for the host to retrieve that user's key from a database. Or, for extra security, the first message (or even each message) between browser and host could contain a random challenge-string, which each end would then turn into a signature, and use that signature as the encryption-key for the session (or the reply).

If a travelling employee can carry a session-startup file (e.g. login_on_the_road.html) on their laptop, then they are invulnerable to imposter-web-hosts trying to feed them trojan JavaScript.

Version 2.23

(c) Peter J Billam 1998

SUBROUTINES

encrypt( $plaintext, $key );

Encrypts with CBC (Cipher Block Chaining)

decrypt( $cyphertext, $key );

Decrypts with CBC (Cipher Block Chaining)

asciidigest( $a_string );

Returns an asciified binary signature of the argument.

tea_in_javascript();

Returns a compatible implementation of TEA in JavaScript, for use in CGI scripts to communicate with browsers.

EXPORT_OK SUBROUTINES

The following routines are not exported by default, but are exported under the ALL tag, so if you need them you should:

 import Crypt::Tea_JS qw(:ALL);
binary2ascii( $a_binary_string );

Provides an ascii text encoding of the binary argument. If Tea_JS.pm is not being invoked from a GCI script, the ascii is split into lines of 72 characters.

ascii2binary( $an_ascii_string );

Provides the binary original of an ascii text encoding.

JAVASCRIPT

At the browser end, the following functions offer the same functionality as their perl equivalents above:

encrypt ( str, keystr )
decrypt ( ascii, keystr )
asciidigest ( str );

Of course the same Key must be used by the Perl on the server and by the JavaScript in the browser, and of course you don't want to transmit the Key in cleartext between them. Let's assume you've already asked the user to fill in a form asking for their Username, and that this username can be transmitted back and forth in cleartext as an ordinary form variable.

On the server, typically you will retrieve the Key from a database of some sort, for example:

 dbmopen %keys, "/home/wherever/passwords", 0666;
 $key = $keys{$username};  dbmclose %keys;
 $cyphertext = encrypt("<P>Hello World !</P>\n", $key);

At the browser end, just ask the user for their password when they load an encrypted page, e.g.

 print tea_in_javascript(), <<EOT;
 <SCRIPT LANGUAGE="JavaScript">
 var key = prompt("Password ?","");
 document.write(decrypt($cyphertext, key));
 </SCRIPT>
 EOT

To submit an encrypted FORM, the traditional way is to construct two FORMs; an overt one which the user fills in but which never actually gets submitted, and a covert one which will hold the cyphertext. See the cgi script examples/old_tea_demo.cgi in the distribution directory.

More often you want the browser to remember its Key from page to page, to form a session. If you store the Key in a Cookie, it is vulnerable to any imposter server who imitates your IP address, and also to anyone who sits down at the user's computer. Better is to store the Key in a JavaScript variable, and communicate with the server in Ajax style, with XMLHttpRequest or ActiveXObject, and responseText or responseXML. See the cgi script examples/tea_demo.cgi in the distribution directory.

In the distribution directory there is also Tea_JS.js, which is simply the output of tea_in_javascript(). This could be useful if your initial login page is an HTML page rather than a CGI script.

ROADMAP

Crypt::Tea conflicted with a similarly-named Crypt::TEA by Abhijit Menon-Sen. Unfortunately, Microsoft operating systems confused the two names and are unable to install both. Version 2.10 of Crypt::Tea is mature, and apart perhaps from minor bug fixes will probably remain the final version. Further development will take place under the name Crypt::Tea_JS. The calling interface is identical.

I've taken advantage of the new name to make two important changes. Firstly, Crypt::Tea_JS uses the New Improved version of the Tea algorithm, which provides even stronger encryption, though it does surrender backward-compatibility for files encrypted by the old Crypt::Tea. Secondly, some of the core routines are now implemented in C, for improved performance (at the server end, if you're using it in a CGI context).

AUTHOR

Peter J Billam ( http://www.pjb.com.au/comp/contact.html ).

CREDITS

Based on TEA, as described in http://www.cl.cam.ac.uk/ftp/papers/djw-rmn/djw-rmn-tea.html , and on some help from Applied Cryptography by Bruce Schneier as regards the modes of use. Thanks also to Neil Watkiss for the MakeMaker packaging, to Scott Harrison for suggesting workarounds for MacOS 10.2 browsers, to Morgan Burke for pointing out the problem with URL query strings, and to Slaven Razic for portability advice in spite of "use bytes".

SEE ALSO

examples/tea_demo.cgi, perldoc Encode, http://www.pjb.com.au/comp, tea(1), perl(1).