CBC
Crypt  :: pure-ruby cryptographic cyphers

The Crypt library is a pure-ruby implementation of a number of popular encryption algorithms. Block cyphers currently available include Blowfish, GOST, IDEA, and Rijndael (AES). Cypher Block Chaining (CBC) has been implemented. Twofish, Serpent, and CAST256 are planned for release soon.

Crypt is written entirely in ruby so deployment is simple - no platform concerns, no library dependencies, nothing to compile.

Cypher Block Chaining

Cypher Block Chaining is a mode of encryption for a stream of data. Each block of plain text is XORed with the previous block of encrypted text. This introduces entropy, making attacks much more difficult because the the attacker cannot rely on relationships between decrypted data that exist between words in a normal sentence.

Other modes include Cypher Feeback (CFB), Output Feedback (OFB), and Electronic Codebook (ECB). The first two are alternatives to CBC. ECB is essentially just encrypting blocks without using any of these methods to add entropy. These alternatives are not implemented and there are no plans to do so at this stage.

This implementation was inspired by the description from Wikipedia. It places the encrypted initialization vector in an extra block at the start of the message. At the end of the message, another extra block is added. This contains the remaining bytes of the message that did not fit evenly into a block. The number of meaningful bytes in this final block can be anywhere from zero up to one less than the block size. That means the last byte of the final block is never used by the message. We use it to store the number of meaningful bytes in the final block.

Once you have initialized any of the block cypher classes with a key, you can encrypt and decrypt files with a single line of ruby. The example below shows Blowfish, but the #encrypt_file method works the same for all of the block ciphers.

blowfish = Crypt::Blowfish.new("A sample key better than this one")
blowfish.encrypt_file('plain.txt', 'crypt.txt')
blowfish.decrypt_file('crypt.txt', 'plain.txt')

You can also read from a plain text stream, encrypt and write to an encrypted output stream, or treat a string as a stream:

f = File.new('plain.txt', 'r')
g = TCPSocket.new('encrypted.example.com', 2222)
blowfish.encrypt_stream(f, g)

plainText = "This is plain text."
encrypted = blowfish.encrypt_string(plainText)

When this module is mixed in with an block cypher encryption class, the class must provide three methods: #encrypt_block(block) and #decrypt_block(block) and #block_size().