Parent

Class/Module Index [+]

Quicksearch

Origami::Encryption::AES

Pure Ruby implementation of the AES symmetric algorithm. Using mode CBC.

Constants

BLOCKSIZE
NCOLS
NROWS
RCON
ROUNDS
RSBOX

Inverse of the Rijndael S-box

SBOX

Rijndael S-box

Attributes

iv[W]

Public Class Methods

decrypt(key, data) click to toggle source
# File lib/origami/encryption.rb, line 715
def AES.decrypt(key, data)
  AES.new(key, nil).decrypt(data)
end
encrypt(key, iv, data) click to toggle source
# File lib/origami/encryption.rb, line 711
def AES.encrypt(key, iv, data)
  AES.new(key, iv).encrypt(data)
end
new(key, iv, use_padding = true) click to toggle source
# File lib/origami/encryption.rb, line 719
def initialize(key, iv, use_padding = true)
  unless key.size == 16 or key.size == 24 or key.size == 32
    raise EncryptionError, "Key must have a length of 128, 192 or 256 bits."
  end

  if not iv.nil? and iv.size != BLOCKSIZE
    raise EncryptionError, "Initialization vector must have a length of #{BLOCKSIZE} bytes."
  end

  @key = key
  @iv = iv
  @use_padding = use_padding
end

Public Instance Methods

decrypt(data) click to toggle source
# File lib/origami/encryption.rb, line 775
def decrypt(data)
  unless data.size % BLOCKSIZE == 0
    raise EncryptionError, 
      "Data must be 16-bytes padded (data size = #{data.size} bytes)"
  end

  @iv = data.slice!(0, BLOCKSIZE)

  if Origami::OPTIONS[:use_openssl]
    aes = OpenSSL::Cipher::Cipher.new("aes-#{@key.length << 3}-cbc").decrypt
    aes.iv = @iv
    aes.key = @key
    aes.padding = 0

    plain = (aes.update(data) + aes.final).unpack("C*")
  else
    plain = []
    plainblock = []
    prev_cipherblock = []
    nblocks = data.size / BLOCKSIZE

    first_round = true
    nblocks.times do |n|
      cipherblock = data[n * BLOCKSIZE, BLOCKSIZE].unpack("C*")

      plainblock = aesDecrypt(cipherblock)

      if first_round
        BLOCKSIZE.times do |i| plainblock[i] ^= @iv[i].ord end
      else
        BLOCKSIZE.times do |i| plainblock[i] ^= prev_cipherblock[i] end
      end

      first_round = false
      prev_cipherblock = cipherblock
      plain.concat(plainblock)
    end
  end

  if @use_padding
    padlen = plain[-1]
    unless (1..16) === padlen
      raise EncryptionError, "Incorrect padding length : #{padlen}"
    end

    padlen.times do 
      pad = plain.pop
      raise EncryptionError, 
        "Incorrect padding byte : 0x#{pad.to_s 16}" if pad != padlen
    end
  end

  plain.pack("C*")
end
encrypt(data) click to toggle source
# File lib/origami/encryption.rb, line 733
def encrypt(data)

  if @iv.nil?
    raise EncryptionError, "No initialization vector has been set."
  end
  
  if @use_padding
    padlen = BLOCKSIZE - (data.size % BLOCKSIZE)
    data << (padlen.chr * padlen)
  end

  if Origami::OPTIONS[:use_openssl]
    aes = OpenSSL::Cipher::Cipher.new("aes-#{@key.length << 3}-cbc").encrypt
    aes.iv = @iv
    aes.key = @key
    aes.padding = 0

    @iv + aes.update(data) + aes.final
  else
    cipher = []
    cipherblock = []
    nblocks = data.size / BLOCKSIZE

    first_round = true
    nblocks.times do |n|
      plainblock = data[n * BLOCKSIZE, BLOCKSIZE].unpack("C*")

      if first_round
        BLOCKSIZE.times do |i| plainblock[i] ^= @iv[i].ord end
      else
        BLOCKSIZE.times do |i| plainblock[i] ^= cipherblock[i] end
      end

      first_round = false
      cipherblock = aesEncrypt(plainblock)
      cipher.concat(cipherblock)
    end

    @iv + cipher.pack("C*")
  end
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.