Blowfish in Tcl

snichols 07/06/05. I'm having trouble getting the sample Tcl code below to work under Windows. Does this code exist as packaged download already in a file somewhere? Because I get this error when running in Windows, "can't read "xl": no such variable". Thanks I look forward to trying this.

PT 7-Jul-2005: This blowfish code was imported into tcllib for version 1.7 and is in the current ActiveTcl distributions.

snichols 7-Jul-05: Thanks I'll give it a try. I already tried the blowfish package in the Kitten startkit and did not have any luck with it under Windows. Kitten seems to be very similar to tcllib, but allows for non pure Tcl based packages to be included in the starkit. Actually, its not in the version 1.7 tcllib, but luckily the latest tcllib snapshot in CVS has a copy. Thanks again.

FPX: For a pet project of mine (more on that later), I needed an implementation of the blowfish algorithm. After fiddling around with Trf's Trfcrypt and failing, I decided to come up with a pure-Tcl version. For my needs, speed was not an issue anyway.

Blowfish is a cryptographic algorithm for encryption and decryption using a common key (also known as password or passphrase). The key is usually a human-readable string, but can in practice be binary data. The key can be of arbitrary length, but should be long and random enough to avoid dictionary attacks.

This implementation supports the encryption and decryption of individual 64 bit blocks as well as the stream-oriented Cipher Block Chaining mode.

In Electronic Codebook (ECB) mode, the Blowfish algorithm is initialized with a key. It can then be used to encrypt a 64 bit (8 byte) clear text block into a 64 bit cipher text block (using the encryptBlock method) or vice versa (using the decryptBlock method). Block mode should only be used for very short messages (on the magnitude of a few blocks). Because block mode always encrypts the same clear text block to the same cipher text block, long encrypted messages might be subject to frequency attacks (see Solving cryptograms).

In Cipher Block Chaining (CBC) mode, the Blowfish algorithm is initialized with a key and a "salt" (also known as Initialization Vector). It can then be used to encrypt messages of arbitrary length. The salt, which mutates between blocks, avoids the potential for frequency attacks.

To encrypt a stream in CBC mode, the encrypt method can be called multiple times. Each time but the last, the clear text message passed to encrypt must be a multiple of 8 bytes in length. The returned cipher text is of equal length. Cipher text returned from multiple invocations to encrypt can be concatenated. On the last invocation, the clear text message is padded to be a multiple of 8 bytes; the encrypted cipher text will have the padded length and must not be truncated.

To decrypt a stream in CBC mode, the algorithm must be initialized with the same key and salt that were used for encryption. The decrypt method can then be called multiple times; each time, the cipher text must be a multiple of 8 bytes in length. The returned clear text is of equal length. Because the cipher text for a full message is always a multiple of 8 bytes, there are no padding issues.

Because of the padding that may occur upon encryption, some protocols embed the length of the message into the stream, so that the decrypted message can be truncated to the original length.

In CBC mode, the "salt" is 8 bytes of binary data. It must be shared between encryption and decryption. However, knowing the salt by itself is useless, and does not help in attacking the cipher as long as the key remains protected. Therefore, the salt need not be secret. When encrypting a message, the software usually generates a random salt, and prepends it, in plaintext, to the encrypted payload.

Now for the implementation. It uses incr Tcl for convenience. It requires Tcl 8.4 for its 64 bit support. (That may be laziness on my part. The code uses 64 bits solely to have 32 bit unsigned integers. It may be possible to work around that.)

The blowfish::cbc class inherits from the base above. It implements the Cipher Block Chaining (CBC) mode.

The constructor takes two parameters, the password and a salt (also known as the Initialization Vector). The salt must be exactly 8 bytes long; it is usually chosen by the encrypting software at random. The encrypted message is of the same length as the cleartext message, but padded to the next multiple of 8 bytes.

To decrypt a message, a blowfish::cbc object must be initialized with the same password and the same salt that were used for encryption. A decrypted message has the same (padded) length as the encrypted message. Protocols usually embed information about the message length, so that the decrypted message can be properly truncated to the length of the original cleartext message.

A blowfish::cbc object can be used to encrypt/decrypt a stream (i.e., a sequence of messages), by calling the encrypt or decrypt method repeatedly, passing subsequent blocks of the stream.

When encrypting a stream, all blocks but the last must be a multiple of 8 bytes in length.

When decrypting a stream, all blocks, including the last, must be a multiple of 8 bytes in length. Again, truncation may be necessary if the original cleartext stream was not a multiple of 8 bytes in length.

Note that the salt changes over time (it is updated after 8 bytes each). To encrypt a new message with the same salt, or to switch between encryption and decryption, re-configure the salt variable, e.g.,