2015-01-07 49 views
1

我想將消息轉換爲ASCII十六進制值字符串,然後再返回。但是,我的^ ^位XOR運算符遇到了很多麻煩。我花了最近4個小時在XOR和位操作上搜索stackoverflow的類似問題,但沒有看到我已經解決這個問題的建議。Ruby XOR位明智的操作密碼練習

我有一個RakeTest文件,該文件下面由測試:

def test_xor 
    key = 'hi' 
    msg = 'Hello There, how are you?' 
    key_trunc = key 
    key_trunc << key while key.length < msg.length 
    key_trunc = Decrypt.truncate_key key_trunc, msg.length 

    ct = Decrypt.xor msg, key_trunc 
    assert_equal('200c040507493c010d1b0d454801071e48081a0c4810071c57', ct) 
end 

我用手摸索出(和驗證與在線十六進制轉換器),正確的ASCII十六進制的結果應該是什麼以上。這裏是我的解密模塊:

module Decrypt 

    # Returns an array of ASCII Hex values 
    def self.to_hex_array(str_hex) 
    raise ArgumentError 'Argument is not a string.' unless str_hex.is_a? String 

    result = str_hex.unpack('C*').map { |e| e.to_s 16 } 

    result 
    end 

    def self.to_str_from_hex_array(hex_str) 
    return [hex_str].pack 'H*' 
    end 

    def self.xor(msg, key) 

    msg = self.to_hex_array msg 
    key = self.to_hex_array key 
    xor = [] 

    (0...msg.length).each do |i| 
     xor.push msg[i]^key[i] 
    end 

    return xor.join 
    end 

    def self.truncate_key(str, len) 
    str = str.to_s[0...len] if str.length > len 

    return str 

    end 

end 

我已確認在to_hex_arrayto_str_from_hex_array工作正常兩個獨立的耙測試功能。當我運行上述耙測試時,我得到一個'NoMethodError: undefined method '^' for "48":String。 48是開頭的十六進制值,顯然Strings不能進行位操作,但我嘗試了每種可以找到的方法來轉換這些值,以使'^'能夠正確運行。

我能得到的最接近(沒有錯誤拋出)是將循環內的操作更改爲msg[i].hex^key[i].hex,但輸出ASCII dec值。可以幫助我嗎?


編輯:多虧了下面的建議,我能夠成功運行以下測試:

def test_xor 
    key = 'hi' 
    msg = 'Hello There, how are you?' 
    key_trunc = key 
    key_trunc << key while key.length < msg.length 
    key_trunc = Decrypt.truncate key_trunc, msg.length 

    ct = Decrypt.xor msg, key_trunc 
    assert_equal(['200c040507493c010d1b0d454801071e48081a0c4810071c57'], ct) 
end 

def test_decrypt 
    msg = 'attack at dawn' 
    key = '6c73d5240a948c86981bc294814d' 
    key = [key].pack('H*') 

    new_key = Decrypt.xor msg, key 
    assert_equal(['0d07a14569fface7ec3ba6f5f623'], new_key) 
    ct = Decrypt.xor 'attack at dusk', new_key.pack('H*') 
    assert_equal(['6c73d5240a948c86981bc2808548'], ct) 
end 

對於那些有興趣,這裏是成功的解密模塊:

module Decrypt 

    # Returns an array of ASCII Hex values 
    def self.to_dec_array(str_hex) 
    raise ArgumentError, 'Argument is not a string!' unless str_hex.is_a? String 

    dec_array = str_hex.unpack('C*') 

    dec_array 
    end 

    def self.to_str_from_dec_array(dec_array) 
    raise ArgumentError, 'Argument is not an array!' unless dec_array.is_a? Array 

    return dec_array.pack 'C*' 
    end 

    def self.print_dec_array(dec_array) 
    return [dec] 
    end 

    def self.xor(msg, key) 

    msg = self.to_dec_array msg 
    key = self.to_dec_array key 
    xor = [] 

    (0...msg.length).each do |i| 
     xor.push msg[i]^key[i] 
    end 

    xor = xor.pack('C*').unpack('H*') 

    xor 
    end 

    def self.truncate(str, len) 
    str = str.to_s[0...len] if str.length > len 

    return str 

    end 

end 
+0

我我看了看'ord',看起來好像它可能是我需要用來實現它的工作,但是在閱讀了它並試圖實現它之後,我無法得到它的工作。 – eugene1832

回答

2

在你的to_hex_array方法中,你不應該將字節轉換爲字符串(你的電話to_s 16) - 這是w HY你最終要XOR字符串,而不是整數

這並不意味着你xor方法將需要額外的步驟,以整數數組爲字符串轉的結果 - 像

array_of_integers.map {|int| int.to_s(16)}.join 
+0

謝謝!我可以通過將'to_hex_array'中的'result'更改爲'result = str_hex.unpack('C *')',然後在'xor'中將最後的'xor'變爲'xor = xor'。打包('C *')。解包('H *')',這工作。但是,我希望'to_hex_array'返回一個數組,其中每個索引位置都保存一個十六進制值,而不是一個十進制值,該C *返回(但是以單個索引數組的形式返回,而H *返回一個數組一個值,整個十六進制字符串)。那有意義嗎? – eugene1832

+0

整數數組既不是十進制也不是十六進制 - 這就是ruby選擇如何將其打印到屏幕上的方式 –

+0

我的意思是''unpack('C *')'返回給我一個看起來像'['75' ,'36','72','101']和'unpack('H *')'返回給我一個看起來像'['6e32010a']'的數組。我希望將十六進制表示作爲數組中的單個索引返回給我,以使以前的數組變成'['6e','32','01','0a']'。但是操縱十六進制數組來分割它的索引會將這些值轉換爲字符串,並且我返回到原來的問題:XOR – eugene1832