class Crypt::Blowfish

blowfish.rb Richard Kernahan

Blowfish algorithm by Bruce Schneider
Ported by Richard Kernahan from the reference C code

Constants

ULONG

Public Class Methods

new(key) click to toggle source
# 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

Public Instance Methods

block_size() click to toggle source
# File lib/crypt/blowfish.rb, line 24
def block_size()
  8
end
decrypt_block(block) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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_blowfish() click to toggle source
# 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