【问题标题】:Port ColdFusion Java hashing function to Ruby将 ColdFusion Java 散列函数移植到 Ruby
【发布时间】:2014-08-12 15:37:22
【问题描述】:

我正在尝试将 java 散列函数移植到 Ruby,但最终得到的散列值与预期不同。下面是相关的java函数(coldfusion):

 public string function hashAdministrator(required string pass) {
   MessageDigest = createObject('java','java.security.MessageDigest');
   for(i=1; i<=5; i++) {
     md = MessageDigest.getInstance('SHA-256');
     md.update(pass.getBytes('UTF-8'));
     pass = enc(md.digest());
   }
   return pass;
 }

 private string function enc(strArr) {
   //local.strArr = str.getBytes('UTF-8');
   local.hex = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];

   savecontent variable="local.out" {
     for (local.item in strArr) {
       writeOutput(hex[bitshrn(bitAnd(240,local.item),4)+1]);
       writeOutput(hex[bitAnd(15,local.item)+1]);
     }
   };
   return local.out;
 }

下面是我的红宝石代码:

 # encoding: utf-8

 require 'digest/sha2'

 class RailoPassword

   attr_accessor :pass

   def admin_password
     password = ''
     5.times do
       md = Digest::SHA2.new
       md.update(self.pass)
       password = self.enc(md.digest.bytes.to_a)
     end
     password
   end


   def enc(strarr)
     hex = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']

     a = ''
     strarr.each do |item|
       a << hex[((0xF0 & item) >> 4)]
       a << hex[(0x0F & item)]
     end
     a
   end
 end

ruby 中的实际实现:

 a = RailoPassword.new
 a.pass = 'test1234'
 puts 'expected: 0be431aeebf55fdc30296e1224fb80b0edbebcddaedb65fcbad1315e906dde65'
 puts "actual:   #{a.admin_password}"

预期哈希:0be431aeebf55fdc30296e1224fb80b0edbebcddaedb65fcbad1315e906dde65

返回的哈希:937e8d5fbb48bd4949536cd65b8d35c426b80d2f830c5c308e2cdec422ae2244

返回的哈希与我刚刚从 Digest::SHA2: 获得十六进制摘要相同:

 1.9.3-p547 :335 > Digest::SHA2.hexdigest('test1234')
  => "937e8d5fbb48bd4949536cd65b8d35c426b80d2f830c5c308e2cdec422ae2244"

任何帮助将不胜感激。

【问题讨论】:

  • 我不了解你,但如果我要继承这样的代码,甚至是我自己(我已经做了很长时间了)我会考虑重写。我认为writeOutput(hex[bitshrn(bitAnd(240,local.item),4)+1]); 不够清晰,尤其是bitAnd 部分(Java 中的常量HIGHEST_FOUR_BITS0b1111_0000 怎么样?)

标签: java ruby encryption coldfusion sha256


【解决方案1】:

这个:

def admin_password
    password = ''
    5.times do
        md = Digest::SHA2.new
        md.update(self.pass)
        password = self.enc(md.digest.bytes.to_a)
    end
    password
end

与您的 CFML 逻辑不匹配。应该是这样的(我是 Ruby 新手,如果这不是完美的 Ruby,请见谅):

def admin_password
    # password = '' # get rid of this
    5.times do
        md = Digest::SHA2.new
        md.update(self.pass)
        self.pass = self.enc(md.digest.bytes.to_a) # update the correct variable here
    end
    self.pass # and return the correct variable here
end

完成后,两个代码块返回相同的值,0be431aeebf55fdc30296e1224fb80b0edbebcddaedb65fcbad1315e906dde65

而且,坦率地说,如果您也按照@owlstead 的建议进行了一些调试,那么您就会立即明白这一点。所以这里也有一个教训:如果你寻求帮助,请注意所提供的帮助。

【讨论】:

  • 谢谢,我看错了。没有考虑到它在迭代中编码self.pass。非常感谢和吸取有关调试的教训。 @owlstead,很抱歉当您最初回复时没有进一步阅读。
【解决方案2】:

你不应该这样做:

password = self.pass

然后

md.update(password)

?

【讨论】:

  • 他们不是在 Ruby 中包含调试器吗? SO 不是社区调试器。
  • 调试不会告诉我为什么哈希与返回的 java 函数不同。并且没有密码不应该 = self.pass
  • 是的,无论如何,但在 Java 中,每次循环迭代都会更新 pass,而在 Ruby 中则不会。
  • 在循环工作的同时输出中间值进行调试肯定告诉你哪里出了问题,以及相应的查找位置。