Skip to content

Instantly share code, notes, and snippets.

@jslmnop
Created February 17, 2012 14:03
Show Gist options
  • Select an option

  • Save jslmnop/1853596 to your computer and use it in GitHub Desktop.

Select an option

Save jslmnop/1853596 to your computer and use it in GitHub Desktop.
simple pos encryption
module Crypt
module CBC
require 'stringio'
require 'crypt/stringxor'
ULONG = 0x100000000
# When this module is mixed in with an encryption class, the class
# must provide three methods: encrypt_block(block) and decrypt_block(block)
# and block_size()
def generate_initialization_vector(words)
srand(Time.now.to_i)
vector = ""
words.times {
vector << [rand(ULONG)].pack('N')
}
return(vector)
end
def encrypt_stream(plainStream, cryptStream)
# Cypher-block-chain mode
initVector = generate_initialization_vector(block_size() / 4)
chain = encrypt_block(initVector)
cryptStream.write(chain)
while ((block = plainStream.read(block_size())) && (block.length == block_size()))
block = block ^ chain
encrypted = encrypt_block(block)
cryptStream.write(encrypted)
chain = encrypted
end
# write the final block
# At most block_size()-1 bytes can be part of the message.
# That means the final byte can be used to store the number of meaningful
# bytes in the final block
block = '' if block.nil?
buffer = block.split('')
remainingMessageBytes = buffer.length
# we use 7-bit characters to avoid possible strange behavior on the Mac
remainingMessageBytes.upto(block_size()-2) { buffer << rand(128).chr }
buffer << remainingMessageBytes.chr
block = buffer.join('')
block = block ^ chain
encrypted = encrypt_block(block)
cryptStream.write(encrypted)
end
def decrypt_stream(cryptStream, plainStream)
# Cypher-block-chain mode
chain = cryptStream.read(block_size())
while (block = cryptStream.read(block_size()))
decrypted = decrypt_block(block)
plainText = decrypted ^ chain
plainStream.write(plainText) unless cryptStream.eof?
chain = block
end
# write the final block, omitting the padding
buffer = plainText.split('')
remainingMessageBytes = buffer.last.unpack('C').first
remainingMessageBytes.times { plainStream.write(buffer.shift) }
end
def carefully_open_file(filename, mode)
begin
aFile = File.new(filename, mode)
rescue
puts "Sorry. There was a problem opening the file <#{filename}>."
aFile.close() unless aFile.nil?
raise
end
return(aFile)
end
def encrypt_file(plainFilename, cryptFilename)
plainFile = carefully_open_file(plainFilename, 'rb')
cryptFile = carefully_open_file(cryptFilename, 'wb+')
encrypt_stream(plainFile, cryptFile)
plainFile.close unless plainFile.closed?
cryptFile.close unless cryptFile.closed?
end
def decrypt_file(cryptFilename, plainFilename)
cryptFile = carefully_open_file(cryptFilename, 'rb')
plainFile = carefully_open_file(plainFilename, 'wb+')
decrypt_stream(cryptFile, plainFile)
cryptFile.close unless cryptFile.closed?
plainFile.close unless plainFile.closed?
end
def encrypt_string(plainText)
plainStream = StringIO.new(plainText)
cryptStream = StringIO.new('')
encrypt_stream(plainStream, cryptStream)
cryptText = cryptStream.string
return(cryptText)
end
def decrypt_string(cryptText)
cryptStream = StringIO.new(cryptText)
plainStream = StringIO.new('')
decrypt_stream(cryptStream, plainStream)
plainText = plainStream.string
return(plainText)
end
end
end
class Idea
require 'crypt/cbc'
include Crypt::CBC
require 'digest/md5'
ULONG = 0x100000000
USHORT = 0x10000
encrypt = 0
decrypt = 1
def block_size
return(8)
end
def initialize(key128, mode)
# IDEA is subject to attack unless the key is sufficiently random, so we
# take an MD5 digest of a variable-length passphrase to ensure a solid key
if (key128.class == String)
digest = Digest::MD5.new(key128).digest
key128 = digest.unpack('n'*8)
end
raise "Key must be 128 bits (8 words)" unless (key128.class == Array) && (key128.length == 8)
raise "Mode must be encrypt or decrypt" unless ((mode == "encrypt") | (mode == "decrypt"))
if (mode == "encrypt")
@subkeys = generate_encryption_subkeys(key128)
else (mode == "decrypt")
@subkeys = generate_decryption_subkeys(key128)
end
end
def mul(a, b)
modulus = 0x10001
return((1 - b) % USHORT) if (a == 0)
return((1 - a) % USHORT) if (b == 0)
return((a * b) % modulus)
end
def mulInv(x)
modulus = 0x10001
x = x.to_i % USHORT
return(x) if (x <= 1)
t1 = USHORT / x
y = modulus % x
if (y == 1)
inv = (1 - t1) & 0xFFFF
return(inv)
end
t0 = 1
while (y != 1)
q = x / y
x = x % y
t0 = t0 + (q * t1)
return(t0) if (x == 1)
q = y / x
y = y % x
t1 = t1 + (q * t0)
end
inv = (1 - t1) & 0xFFFF
return(inv)
end
def generate_encryption_subkeys(key)
encrypt_keys = []
encrypt_keys[0..7] = key.dup
8.upto(51) { |i|
a = ((i + 1) % 8 > 0) ? (i-7) : (i-15)
b = ((i + 2) % 8 < 2) ? (i-14) : (i-6)
encrypt_keys[i] = ((encrypt_keys[a] << 9) | (encrypt_keys[b] >> 7)) % USHORT
}
return(encrypt_keys)
end
def generate_decryption_subkeys(key)
encrypt_keys = generate_encryption_subkeys(key)
decrypt_keys = []
decrypt_keys[48] = mulInv(encrypt_keys.shift)
decrypt_keys[49] = (-encrypt_keys.shift) % USHORT
decrypt_keys[50] = (-encrypt_keys.shift) % USHORT
decrypt_keys[51] = mulInv(encrypt_keys.shift)
42.step(0, -6) { |i|
decrypt_keys[i+4] = encrypt_keys.shift % USHORT
decrypt_keys[i+5] = encrypt_keys.shift % USHORT
decrypt_keys[i] = mulInv(encrypt_keys.shift)
if (i ==0)
decrypt_keys[1] = (-encrypt_keys.shift) % USHORT
decrypt_keys[2] = (-encrypt_keys.shift) % USHORT
else
decrypt_keys[i+2] = (-encrypt_keys.shift) % USHORT
decrypt_keys[i+1] = (-encrypt_keys.shift) % USHORT
end
decrypt_keys[i+3] = mulInv(encrypt_keys.shift)
}
return(decrypt_keys)
end
def crypt_pair(l, r)
word = [l, r].pack('NN').unpack('nnnn')
k = @subkeys[0..51]
8.downto(1) { |i|
word[0] = mul(word[0], k.shift)
word[1] = (word[1] + k.shift) % USHORT
word[2] = (word[2] + k.shift) % USHORT
word[3] = mul(word[3], k.shift)
t2 = word[0] ^ word[2]
t2 = mul(t2, k.shift)
t1 = (t2 + (word[1] ^ word[3])) % USHORT
t1 = mul(t1, k.shift)
t2 = (t1 + t2) % USHORT
word[0] ^= t1
word[3] ^= t2
t2 ^= word[1]
word[1] = word[2] ^ t1
word[2] = t2
}
result = []
result << mul(word[0], k.shift)
result << (word[2] + k.shift) % USHORT
result << (word[1] + k.shift) % USHORT
result << mul(word[3], k.shift)
twoLongs = result.pack('nnnn').unpack('NN')
return(twoLongs)
end
def encrypt_block(block)
xl, xr = block.unpack('NN')
xl, xr = crypt_pair(xl, xr)
encrypted = [xl, xr].pack('NN')
return(encrypted)
end
def decrypt_block(block)
xl, xr = block.unpack('NN')
xl, xr = crypt_pair(xl, xr)
decrypted = [xl, xr].pack('NN')
return(decrypted)
end
end
#dont make any money off this algo in any way or you'll get your white ass sued into darkness
module Crypt
module StringXor
def ^(aString)
a = self.unpack('C'*(self.length))
b = aString.unpack('C'*(aString.length))
if (b.length < a.length)
(a.length - b.length).times { b << 0 }
end
xor = ""
0.upto(a.length-1) { |pos|
x = a[pos] ^ b[pos]
xor << x.chr()
}
return(xor)
end
end
end
class String
include Crypt::StringXor
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment