Class: Cipher::DES
- Inherits:
-
Object
- Object
- Cipher::DES
- Defined in:
- lib/cipher/des.rb
Overview
Brief
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'
About
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.
Constant Summary collapse
- BLOCK_SIZE =
8- BYTEBIT =
[ 01, 02, 04, 010, 020, 040, 0100, 0200 ]
- BIGBYTE =
[ 0x800000, 0x400000, 0x200000, 0x100000, 0x080000, 0x040000, 0x020000, 0x010000, 0x008000, 0x004000, 0x002000, 0x001000, 0x000800, 0x000400, 0x000200, 0x000100, 0x000080, 0x000040, 0x000020, 0x000010, 0x000008, 0x000004, 0x000002, 0x000001 ]
- PC1 =
Use the key schedule specified in the Standard (ANSI X3.92-1981).
[ 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 ]
- TOTROT =
[ 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 ]
- PC2 =
[ 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 ]
Instance Attribute Summary collapse
-
#key ⇒ Object
readonly
Returns the value of attribute key.
-
#mode ⇒ Object
readonly
Returns the value of attribute mode.
Class Method Summary collapse
-
.decrypt(key, data) ⇒ Object
A shortcut method to create a cipher object using
key, and fully decryptdata. -
.encrypt(key, data) ⇒ Object
A shortcut method to create a cipher object using
key, and fully encryptdata.
Instance Method Summary collapse
-
#final ⇒ Object
This flushes the internal buffer by padding it out with null bytes, and doing a final DES round.
-
#initialize(key, mode) ⇒ DES
constructor
Create a des cipher object.
-
#update(data) ⇒ Object
This updates the cipher with
data, returning any available ciphered output.
Constructor Details
#initialize(key, mode) ⇒ DES
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.
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# 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 |
Instance Attribute Details
#key ⇒ Object (readonly)
Returns the value of attribute key.
57 58 59 |
# File 'lib/cipher/des.rb', line 57 def key @key end |
#mode ⇒ Object (readonly)
Returns the value of attribute mode.
57 58 59 |
# File 'lib/cipher/des.rb', line 57 def mode @mode end |
Class Method Details
.decrypt(key, data) ⇒ Object
A shortcut method to create a cipher object using key, and fully decrypt data
114 115 116 117 |
# File 'lib/cipher/des.rb', line 114 def self.decrypt key, data des = new key, :decrypt des.update(data) << des.final end |
.encrypt(key, data) ⇒ Object
A shortcut method to create a cipher object using key, and fully encrypt data
108 109 110 111 |
# File 'lib/cipher/des.rb', line 108 def self.encrypt key, data des = new key, :encrypt des.update(data) << des.final end |
Instance Method Details
#final ⇒ Object
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.
99 100 101 102 103 104 105 |
# File 'lib/cipher/des.rb', line 99 def final if @buf.empty? '' else update 0.chr * (BLOCK_SIZE - @buf.length) end end |
#update(data) ⇒ Object
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.
84 85 86 87 88 89 90 91 92 93 94 |
# 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 |