Алгоритм шифрования из PHP в Ruby (вариант Виньера) - PullRequest
2 голосов
/ 13 января 2010

Я немного застрял с этим. Я должен взаимодействовать с API-интерфейсом, который использует версию алгоритма шифрования, которую они, похоже, извлекли из Typo3, написанной Ари Куорикоски.

Мне нужно создать библиотеку ruby ​​для взаимодействия с их API, поэтому придется перенести их алгоритм на ruby, и я немного не в себе, когда дело доходит до шифрования.

Это код:

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)); 
}

Часть, которая поставила меня в тупик, такова: я должен написать ее для ruby ​​1.8.6, так как это сервер, на котором он будет работать. И нет XOR для строк. Не то чтобы я это понял, если бы был.

Любая помощь, указатели, идеи будут высоко ценится.

Добавление:

Я понимаю, я не ставил никакой код, единственная трудность на самом деле - проблема с xor, но вот мой код:

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

Ответы [ 2 ]

2 голосов
/ 13 января 2010

С Эрик Веенстра :

class String
  def xor(other)
    if other.empty?
      self
    else
      a1        = self.unpack("c*")
      a2        = other.unpack("c*")
      a2 *= 2   while a2.length < a1.length
      a1.zip(a2).collect{|c1,c2| c1^c2}.pack("c*")
    end
  end
end

Тогда ваш код становится

tmp << str.slice(i,1).xor(encrypt_key.slice(i,1))

Альтернативная реализация String#xor, предложенная jolierouge и David Garamond :

class String
  def xor(other)
    raise ArgumentError, "Can't bitwise-XOR a String with a non-String" unless other.kind_of? String
    raise ArgumentError, "Can't bitwise-XOR strings of different length" unless self.length == other.length
    (0..self.length-1).collect { |i| self[i] ^ other[i] }.pack("C*")
  end
end
0 голосов
/ 28 июля 2015

Примечание редактора: окончательный рабочий код был перенесен из вопроса в его собственный ответ.

Окончательный рабочий источник, основанный на полезном ответе Джеймса, основные реквизиты! И Дэвиду Гарамонду.

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
...