Class: Crypt::Blowfish

Inherits:
Object
  • Object
show all
Includes:
BlowfishTables, CBC
Defined in:
lib/crypt/blowfish.rb

Overview

Ported by Richard Kernahan from the reference C code

Constant Summary collapse

ULONG =
0x100000000

Constants included from BlowfishTables

Crypt::BlowfishTables::INITIALPARRAY, Crypt::BlowfishTables::INITIALSBOXES

Instance Method Summary collapse

Methods included from CBC

#carefully_open_file, #decrypt_file, #decrypt_stream, #decrypt_string, #encrypt_file, #encrypt_stream, #encrypt_string, #generate_initialization_vector

Constructor Details

#initialize(key) ⇒ Blowfish

Returns a new instance of Blowfish.



16
17
18
19
20
21
22
# File 'lib/crypt/blowfish.rb', line 16

def initialize(key)
  @key = key
  raise "Bad key length: the key must be 1-56 bytes." unless (key.length.between?(1,56))
  @pArray = []
  @sBoxes = []
  setup_blowfish()
end

Instance Method Details

#block_sizeObject



24
25
26
# File 'lib/crypt/blowfish.rb', line 24

def block_size()
  8
end

#decrypt_block(block) ⇒ Object



102
103
104
105
106
107
108
# File 'lib/crypt/blowfish.rb', line 102

def decrypt_block(block)
  raise "block must be #{block_size()} bytes long" if (block.length() != block_size())
  xl, xr = block.unpack('NN')
  xl, xr = decrypt_pair(xl, xr)
  decrypted = [xl, xr].pack('NN')
  return(decrypted)
end

#decrypt_pair(xl, xr) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
# File 'lib/crypt/blowfish.rb', line 79

def decrypt_pair(xl, xr)
  17.downto(2) { |i|
      xl = (xl ^ @pArray[i]) % ULONG
      xr = (xr ^ f(xl)) % ULONG
      xl, xr = [xl, xr].reverse
  }
  xl, xr = [xl, xr].reverse
  xr = (xr ^ @pArray[1]) % ULONG
  xl = (xl ^ @pArray[0]) % ULONG
  return([xl, xr])
end

#encrypt_block(block) ⇒ Object



92
93
94
95
96
97
98
99
# File 'lib/crypt/blowfish.rb', line 92

def encrypt_block(block)
  block = block.force_encoding("ASCII-8BIT") # to treat unicode characters as two bytes
  raise "block must be #{block_size()} bytes long" if (block.length() != block_size())
  xl, xr = block.unpack('NN')
  xl, xr = encrypt_pair(xl, xr)
  encrypted = [xl, xr].pack('NN')
  return(encrypted)
end

#encrypt_pair(xl, xr) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
# File 'lib/crypt/blowfish.rb', line 66

def encrypt_pair(xl, xr)
  0.upto(15) { |i|
      xl = (xl ^ @pArray[i]) % ULONG
      xr = (xr ^ f(xl)) % ULONG
      xl, xr = [xl, xr].reverse
  }
  xl, xr = [xl, xr].reverse
  xr = (xr ^ @pArray[16]) % ULONG
  xl = (xl ^ @pArray[17]) % ULONG
  return([xl, xr])
end

#f(x) ⇒ Object



28
29
30
31
32
33
34
# File 'lib/crypt/blowfish.rb', line 28

def f(x)
  a, b, c, d = [x].pack('N').unpack('CCCC')
  y = (@sBoxes[0][a] + @sBoxes[1][b]) % ULONG
  y = (y ^ @sBoxes[2][c]) % ULONG
  y = (y + @sBoxes[3][d]) % ULONG
  return(y)
end

#setup_blowfishObject



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/crypt/blowfish.rb', line 37

def setup_blowfish()
  @sBoxes = Array.new(4) { |i| INITIALSBOXES[i].clone }
  @pArray = INITIALPARRAY.clone
  keypos = 0
  0.upto(17) { |i|
    data = 0
    4.times {
      k = @key[keypos].ord()    # ruby 2.0
      data = ((data << 8) | k) % ULONG
      keypos = (keypos.next) % @key.length
    }
    @pArray[i] = (@pArray[i] ^ data) % ULONG
  }
  l = 0
  r = 0
  0.step(17, 2) { |i|
    l, r = encrypt_pair(l, r)
    @pArray[i]   = l
    @pArray[i+1] = r
  }
  0.upto(3) { |i|
    0.step(255, 2) { |j|
      l, r = encrypt_pair(l, r)
      @sBoxes[i][j]   = l
      @sBoxes[i][j+1] = r
    }
  }
end