Hey all,
I am a bit stuck with this. I have to interface with an api that uses a version of an encryption algorithm that they seem to have ripped from Typo3 written by Ari Kuorikoski.
I need to create a ruby lib to interface with their api, so have to port their algorithm into ruby, and I am a bit out of my depth when it comes to encryption.
This is the code:
private function keyED($txt) {
$encrypt_key = md5($this->encrypt_key);
$ctr=0;
$tmp = "";
for ($i=0;$i<strlen($txt);$i++) {
if ($ctr==strlen($encrypt_key)) $ctr=0;
$tmp.= substr($txt,$i,1) ^ substr($encrypt_key,$ctr,1);
$ctr++;
}
return $tmp;
}
private function encrypt($txt){
srand((double)microtime()*1000000);
$encrypt_key = md5(rand(0,32000));
$ctr=0;
$tmp = "";
for ($i=0;$i<strlen($txt);$i++){
if ($ctr==strlen($encrypt_key)) $ctr=0;
$tmp.= substr($encrypt_key,$ctr,1) .
(substr($txt,$i,1) ^ substr($encrypt_key,$ctr,1));
$ctr++;
}
return base64_encode($this->keyED($tmp));
}
The part that has me stumped is this, I have to write it for ruby 1.8.6 as that's the server that it will be on. And there's no XOR for strings... Not that I would understand it if there was.
Any help, pointers, ideas would be much much appreciated.
Thanks, J
Addendum:
I realize, I didn't put any code up, the only difficulty is actually the xor problem, but here is my code so far:
def xor(s1,s2)
if s2.empty? then
return s1
else
a1 = s1.unpack("c*")
a2 = s2.unpack("c*")
a2 *= 2 while a2.length < a1.length
return a1.zip(a2).collect {|c1,c2| c1 ^ c2}.pack("c*")
end
end
def keyED(str)
encrypt_key = Digest::MD5.digest(@key)
ctr = 0
tmp = ''
for i in 0...str.length do
ctr = 0 if ctr == encrypt_key.length
tmp << xor(str.slice(i,1), encrypt_key.slice(ctr,1)).to_s
ctr = ctr + 1
end
return tmp
end
# === Ported Code
# This code was ported from Ari's Typo 3 Session Encryption
def encrypt(str)
encrypt_key = Digest::MD5.digest(rand(32000).to_s)
ctr = 0
tmp = ''
for i in 0...str.length do
ctr=0 if ctr==encrypt_key.length
tmp << encrypt_key.slice(ctr,1) << xor(str.slice(i,1), encrypt_key.slice(ctr,1))
ctr = ctr + 1
end
return Base64.encode64(keyED(tmp))
end
def decrypt(str)
txt = keyED(str)
tmp = ''
for i in 0...txt.length do
md = txt.slice(i,1)
i = i + 1
tmp << xor(txt.slice(i,1),md)
end
puts "Decrypte string:#{Base64.decode64(tmp)}EOSTRING"
end
Update:
Final working source, based on James helpful answer, major props! And to David Garamound.
def xor(s1,s2)
raise ArgumentError, "Can't bitwise-XOR a String with a non-String" unless s2.kind_of? String
raise ArgumentError, "Can't bitwise-XOR strings of different length" unless s1.length == s2.length
(0..s1.length-1).collect { |i| s1[i] ^ s2[i] }.pack("C*")
end
def keyED(txt,key)
ctr,tmp = 0,''
key = Digest::MD5.hexdigest(key)
for i in 0...txt.length do
ctr = 0 if ctr == key.length
str = xor(txt.slice(i,1),key.slice(ctr,1))
tmp << str
ctr = ctr + 1
end
return tmp
end
def encrypt(txt,key)
ctr,tmp = 0,''
ekey = Digest::MD5.hexdigest(rand(32000).to_s)
for i in 0...txt.length do
ctr = 0 if ctr == ekey.length
str = xor(txt.slice(i,1), ekey.slice(ctr,1))
tmp << ekey.slice(ctr,1) << str
ctr = ctr + 1
end
return Base64.encode64(keyED(tmp,key))
end