新手问题 用 RC4 加密出现乱码,但可被解密。

killernova · 2015年08月18日 · 最后由 killernova 回复于 2015年08月19日 · 7031 次阅读

代码如下:

class RubyRc4


  def initialize(str)
    @q1, @q2 = 0, 0
    @key = []
    str.each_byte {|elem| @key << elem} while @key.size < 256
    @key.slice!(256..@key.size-1) if @key.size >= 256
    @s = (0..255).to_a
    j = 0 
    0.upto(255) do |i| 
      j = (j + @s[i] + @key[i] )%256
      @s[i], @s[j] = @s[j], @s[i]
    end    
  end

  def encrypt!(text)
    process text
  end  

  def encrypt(text)
    process text.dup
  end 

  private

  def process(text)
    0.upto(text.length-1) do |i|
      text.setbyte(i, text.getbyte(i) ^ round)
    end
    text
  end

  def round
    @q1 = (@q1 + 1)%256
    @q2 = (@q2 + @s[@q1])%256
    @s[@q1], @s[@q2] = @s[@q2], @s[@q1]
    @s[(@s[@q1]+@s[@q2])%256]  
  end
end

str = '3f873a36c658'
key = '134df334ijnfd'
encryptor = RubyRc4.new(key)
decryptor = RubyRc4.new(key)
a = encryptor.encrypt(str)
b = decryptor.encrypt(a)

puts "a = #{a}"
puts "b = #{b}"

运行该文件后,加密后的密文 (a) 出现了乱码,但是解密后却能得到明文。

  code  ruby rc4.rb
a = ;
      )?}��
b = 3f873a36c658

根据不同的明文与 key,会出现不同的乱码,尤其是某些时候,会出现"a="也变成乱码,比如:

  code  ruby rc4.rb
f���564
b = 3f873a36c658

也试过 base64 解码什么的,没用。本人小白一个,求大家帮忙看看吧。。。

说了一大堆,问题在哪?要我们看什么?

问题就是如何解决乱码啊…

不是乱码,程序没问题,想好看点就 base64 呗

def encrypt64 s
  Base64.encode64 encrypt s
end

def decrypt64 s
  encrypt Base64.decode64 s
end

应该只是在 terminal 上的显示而已吧

没有乱码,如果你想知道加密后的内容到底是什么的话:

puts "a = #{a}".inspect
puts "b = #{b}".inspect

大家说的对,谢谢各位。但我还有问题。 按照代码,任意一个字符的 ascii 值与某个 (0..255) 之间的数字进行异或运算,得到的值完全有可能不落在数字与字符所代表的 ascii 值的集合内,所以出现"5\xD564\xCC\rf\xC4\xEE\x9A\xDB\x03"这样的值是很正常的。 但是奇怪的是,客户给出的加密后的密文都是标准的字符串,比如:3f873a36c658,这是怎么做到的? 客户用的 php,按照他们的说法,步骤是这样的:

密码加密和解密步骤: 加密:密码明文,先经过 rc4 加密,再把加密后的密文转成十六进制 (小写),才可以与系统交互; 解密:就是把加密的步骤反过来;把得到的密码密文,先转成字符串,然后再经过 rc4 解密即可得到密码明文。

方法是这样的:

这个是加密:asc2hex(rc4(APIRC4KEY,明码)) 解密是这个:rc4(APIRC4KEY,hex2asc(加密的密码))

#6 楼 @killernova 这个不是 base64, 是 hex 表示,两个十六进制字符表示一个字节 (16*16=256)

"5\xD564\xCC\rf\xC4\xEE\x9A\xDB\x03".pack('h*')[0]

@luikore 对的,这个我知道。另外你写的那段代码我运行不了 NoMethodError: undefined method 'pack' for "5\xD564\xCC\rf\xC4\xEE\x9A\xDB\u0003":String

#8 楼 @killernova 写错了... 是 unpack

@luikore 还有个问题,我用的是"5\xD564\xCC\rf\xC4\xEE\x9A\xDB\u0003".unpack('H*)[0],得到了我所想要的,"35d53634cc0d66c4ee9adb03", 但是如果我想转回去,该用什么方法?

@luikore 不知为何,unpack 后的数据在 pack,得到的数据不一致。不过我写了个简单的转化方法:

def hex2asc(str)
  arr = []
  (0..str.length - 2).step(2) do |x|
    arr << str.slice(x, 2).hex.chr
  end
  arr.join
end
需要 登录 后方可回复, 如果你还没有账号请 注册新账号