The Cipher::DES class allows for encryption and decryption of plain text using the “Data Encryption Standard”. This version is the modified version which is part of the VNC authentication scheme.
Usage is pretty straight forward:
des = Cipher::DES.new 'mysecretkey', :encrypt str = des.update 'plain text' str << des.update 'more plain text' str << final
Or just use the shortcut class methods:
str = Cipher::DES.encrypt 'mysecretkey', 'plain text'
This code was ported from the file “d3des.c”, for portability reasons. It is not expected to be quick, but is only being used currently for the VNC authentication handshake. If you wanted to cipher a lot of text, you should probably compile the original C as an extension.
I’ve included the following copyright info from the C source verbatim:
This is D3DES (V5.09) by Richard Outerbridge with the double and triple-length support removed for use in VNC. Also the bytebit[] array has been reversed so that the most significant bit in each byte of the key is ignored, not the least significant. These changes are: Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. D3DES (V5.09) A portable, public domain, version of the Data Encryption Standard. Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge. Thanks to: Dan Hoey for his excellent Initial and Inverse permutation code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau, for humouring me on. Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge. (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
Use the key schedule specified in the Standard (ANSI X3.92-1981).
A shortcut method to create a cipher object using key, and
fully decrypt data
# File lib/cipher/des.rb, line 114 def self.decrypt key, data des = new key, :decrypt des.update(data) << des.final end
A shortcut method to create a cipher object using key, and
fully encrypt data
# File lib/cipher/des.rb, line 108 def self.encrypt key, data des = new key, :encrypt des.update(data) << des.final end
Create a des cipher object. key should be cipher key to use,
and mode should be either :encrypt or
:decrypt.
It will expand key to be 8 bytes by padding with null bytes.
If it is longer than 8 bytes, the additional data is discarded.
# File lib/cipher/des.rb, line 64 def initialize key, mode unless [:encrypt, :decrypt].include? mode raise ArgumentError, 'invalid mode argument - %s' % mode end @mode = mode # ensure key is 8 bytes. pad with nulls as needed key = key[0, BLOCK_SIZE] key << 0.chr * (BLOCK_SIZE - key.length) @key = key # now expand the key schedule @keys = self.class.send :prepare_key_stage2, self.class.send(:prepare_key_stage1, key, mode) # this internal buffer is used because we must process data in chunks of 8 bytes @buf = '' end
This flushes the internal buffer by padding it out with null bytes, and doing a final DES round. Note that this means the ciphered text is always padded out to a multiple of 8 bytes.
# File lib/cipher/des.rb, line 99 def final if @buf.empty? '' else update 0.chr * (BLOCK_SIZE - @buf.length) end end
This updates the cipher with data, returning any available
ciphered output. The data is processed in blocks of 8 bytes,
so any residual is added to an internal buffer.
# File lib/cipher/des.rb, line 84 def update data result = '' data = @buf + data unless @buf.empty? num_blocks, residual = data.length.divmod BLOCK_SIZE num_blocks.times do |i| block = data[i * BLOCK_SIZE, BLOCK_SIZE].unpack('N2') result << self.class.send(:desfunc, block, @keys).pack('N2') end @buf = residual == 0 ? '' : data[-residual..-1] result end