Created
May 17, 2011 22:15
-
-
Save mad/977537 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/ruby -wKU | |
class SimpleCipher | |
attr_accessor :P, :S, :IP | |
CYCLE_NUM = 4 | |
BLOCK_SIZE = 32 | |
SUB_BLOCK_SIZE = 4 | |
SUB_BLOCK_NUM = BLOCK_SIZE/SUB_BLOCK_SIZE | |
S = [8, 1, 15, 4, 12, 11, 0, 9, 2, 14, 6, 3, 13, 5, 7, 10] | |
IS = [6, 1, 8, 11, 3, 13, 10, 14, 0, 7, 15, 5, 4, 12, 9, 2] | |
def initialize(key) | |
# XXX: normalize key | |
@key = key.to_i | |
permutation() | |
end | |
def permutation | |
@P = Array.new(32) | |
@IP = Array.new(32) | |
# i*(2k + 1) + 3 mod 32 | |
# k is student number in list | |
k = 1 | |
0.upto(31) do |i| | |
# Default permutation from book | |
# @P[i - 1] = 13*i%32 | |
@P[i] = (i*(2*k + 1) + 3) % 32 | |
# And make inverse substitution. WHAT? | |
@IP[@P[i]] = i | |
end | |
# Need for default permutation | |
# @P[31] = 32 | |
end | |
def add_padding(block) | |
# Add leading padding if number of bits < BLOCK_SIZE | |
if block.size > BLOCK_SIZE | |
raise "Your block greater than #{BLOCK_SIZE} bits" | |
elsif block.size < BLOCK_SIZE | |
block.insert(0, "0" * (BLOCK_SIZE - block.size)) | |
end | |
return block | |
end | |
def encrypt(block) | |
# Do main work | |
CYCLE_NUM.times do |cycle| | |
puts "Cycle #{cycle + 1}: #{block}" | |
block = block.to_i | |
# 1. XOR | |
block = block ^ @key | |
# XXX: make more simple and add test for it | |
# Convert to binary string | |
block = block.to_s(2) | |
block = add_padding(block) | |
# Convert binary string to array with sublocks for applying | |
# substitution | |
block = block.unpack(("a" + SUB_BLOCK_SIZE.to_s) * (SUB_BLOCK_NUM)) | |
# 2. Apply substitution for all subblocks | |
SUB_BLOCK_NUM.times do |b| | |
block[b] = "%04b" % S[block[b].to_i(2)] | |
end | |
# Preparing for permutation. Concatinate sublocks and convert it | |
# to bits array. | |
block = block.collect {|b| b.unpack("a" * SUB_BLOCK_SIZE) }.flatten | |
# 3. Apply permutation | |
tmp = Array.new(32) | |
BLOCK_SIZE.times do |b| | |
tmp[@P[b]] = block[b] | |
end | |
block = tmp | |
# Convert back to bits string | |
block = block.pack("a" * BLOCK_SIZE).to_i(2) | |
end | |
# 4. XOR with key | |
block = block ^ @key | |
# puts add_padding(block.to_s(2)).unpack(("a" + SUB_BLOCK_SIZE.to_s) * (SUB_BLOCK_NUM)).inspect | |
return block | |
end | |
# All encrypt steps but inverse | |
def decrypt(block) | |
# 4. XOR with key | |
block = block ^ @key | |
# Do main work | |
CYCLE_NUM.times do |cycle| | |
puts "Cycle #{cycle + 1}: #{block}" | |
block = block.to_i | |
# XXX: make more simple and add test for it | |
# Convert to binary string | |
block = block.to_s(2) | |
block = add_padding(block) | |
# Preparing for permutation. Concatinate sublocks and convert it | |
# to bits array. | |
block = block.unpack("a" * BLOCK_SIZE) | |
# 3. Apply permutation | |
tmp = Array.new(32) | |
BLOCK_SIZE.times do |b| | |
tmp[@IP[b]] = block[b] | |
end | |
block = tmp | |
# Convert bits arrayt to sublocks array | |
block = block.pack("a" * BLOCK_SIZE) | |
block = block.unpack(("a" + SUB_BLOCK_SIZE.to_s) * (SUB_BLOCK_NUM)) | |
# 2. Apply substitution for all subblocks | |
SUB_BLOCK_NUM.times do |b| | |
block[b] = "%04b" % IS[block[b].to_i(2)] | |
end | |
# Convert back to bits string | |
block = block.pack(("a" + SUB_BLOCK_SIZE.to_s) * (SUB_BLOCK_NUM)).to_i(2) | |
# 1. XOR | |
block = block ^ @key | |
end | |
return block | |
end | |
end | |
sc = SimpleCipher.new("9") | |
p0=0 | |
c1=0 | |
p1=0 | |
c2=0 | |
(2**32).times do |i| | |
p0=i | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment