Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- =begin
- Copyright 2018 strict-flower
- Permission is hereby granted, free of charge, to any person obtaining a
- copy of this software and associated documentation files (the "Software"),
- to deal in the Software without restriction, including without limitation
- the rights to use, copy, modify, merge, publish, distribute, sublicense,
- and/or sell copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- IN THE SOFTWARE.
- =end
- require_relative './aes_table' # https://pastebin.com/UWLstSg8
- require 'matrix'
- # Galois field implementation (simple ver)
- class Fixnum
- alias_method :integer_add, :+
- alias_method :integer_sub, :-
- alias_method :integer_mul, :*
- alias_method :integer_div, :/
- def +(other)
- self ^ other.to_i
- end
- def -(other)
- self + other
- end
- def -@
- self
- end
- def /(other)
- raise 1 # assertion
- end
- def *(other)
- if self == 0
- 0
- elsif self == 1
- other
- else
- other = other.to_i
- if other == 0
- 0
- elsif other == 1
- self
- else
- if $mult_table.keys.include?(other)
- $mult_table[other][self]
- elsif $mult_table.keys.include?(self)
- $mult_table[self][other]
- else
- raise "Invalid Argument"
- end
- end
- end
- end
- end
- class AESMatrix < Matrix
- def self.to_mat(data)
- data = data.to_a
- raise unless data.length == 16
- AESMatrix.columns(data.each_slice(4).to_a)
- end
- def to_a
- t.rows.flatten
- end
- end
- def SubBytes(t)
- t.map{|x| $sbox[x]}
- end
- def SubBytesInv(t)
- t.map{|x| $sboxinv[x]}
- end
- $P = AESMatrix.to_mat([2, 1, 1, 3, 3, 2, 1, 1, 1, 3, 2, 1, 1, 1, 3, 2])
- $PInv = AESMatrix.to_mat([14, 9, 13, 11, 11, 14, 9, 13, 13, 11, 14, 9, 9, 13, 11, 14])
- def MixColumns(t)
- t * $P
- end
- def MixColumnsInv(t)
- t * $PInv
- end
- def ShiftRows(t)
- m = t[0, 0..3]
- m << t[1, 1..3]
- m << t[1, 0]
- m << t[2, 2..3]
- m << t[2, 0..1]
- m << t[3, 3..3]
- m << t[3, 0..2]
- m.flatten!
- AESMatrix.rows(m.each_slice(4).to_a)
- end
- def ShiftRowsInv(t)
- m = t[0, 0..3]
- m << t[1, 3]
- m << t[1, 0..2]
- m << t[2, 2..3]
- m << t[2, 0..1]
- m << t[3, 1..3]
- m << t[3, 0]
- m.flatten!
- AESMatrix.rows(m.each_slice(4).to_a)
- end
- def AddRoundKey(t, key)
- t + key
- end
- alias AddRoundKeyInv AddRoundKey
- def RoundFunc(r, state, key)
- state = SubBytes(state)
- state = ShiftRows(state)
- if r != $r - 1
- state = MixColumns(state)
- end
- AddRoundKey(state, key)
- end
- def RoundFuncInv(r, state, key)
- AddRoundKeyInv(state, key)
- if r != $r - 1
- state = MixColumnsInv(state)
- end
- state = SubBytesInv(state)
- ShiftRowsInv(state)
- end
- def encrypt(m, key)
- state = AESMatrix.to_mat(m)
- key = AESMatrix.to_mat(key)
- state = AddRoundKey(state, key)
- $r.times { |r|
- state = RoundFunc(r, state, key)
- puts r
- }
- state.to_a
- end
- def decrypt(c, key)
- state = AESMatrix.to_mat(c)
- key = AESMatrix.to_mat(key)
- $r.times { |_r|
- r = $r.integer_sub(_r).integer_sub(1)
- state = RoundFuncInv(r, state, key)
- }
- AddRoundKeyInv(state, key).to_a
- end
- $r = 10
- m = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
- k = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
- p encrypt(m, k)
- p decrypt(encrypt(m, k), k)
- raise unless 1 + 1 == 0
- raise unless $PInv * $P == AESMatrix.I(4)
- raise unless $P * $PInv == AESMatrix.I(4)
- raise unless $P + $P == AESMatrix.zero(4)
Advertisement
Add Comment
Please, Sign In to add comment