首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >河豚加密: Java与Ruby

河豚加密: Java与Ruby
EN

Stack Overflow用户
提问于 2014-04-02 04:42:00
回答 2查看 1.2K关注 0票数 0

我正在尝试从木偶(Ruby)生成一些加密的JBoss数据源密码。JBoss使用这个库(见第149行)加密/解密密码(使用在Java代码中编译的预定义密钥的Blowfish )。

现在,研究一下我发现,默认情况下,javax.crypto对河豚使用以下参数: blowfish /ECB/PKCS5Padd。

默认情况下,Ruby的OpenSSL库根本不做任何填充(如果键不是8的倍数,它就会拒绝)。我尝试手动完成填充操作,下面是我的完整代码:

代码语言:javascript
复制
#!/usr/bin/ruby

require 'openssl'

key = 'jaas is the way'

ciph = OpenSSL::Cipher.new('bf-ecb').encrypt
ciph.key = key + (8 - key.length % 8).chr * (8 - key.length % 8)

b = ciph.update(ARGV[0]) + ciph.final()
puts b.unpack('H*')

我试图以类似的方式(Pythonvs.JavaBlowfish)实现PKCS5填充,方法是在这里添加chr(字节数直到长度为8的倍数),直到字符串的长度为8。对于这个特定的键,它应该添加一个chr(1),当尝试调试时,它似乎做得很好。

问题是,我的Ruby代码给出了与Java Picketbox库中的代码不同的结果。

编辑:以下是我在运行更多测试后得出的一些结论:

  • 如果要加密的密钥和纯文本都是16字节长,则结果很好。
  • 我们尝试使用16字节长的纯文本字符串进行加密,并使用15字节的密钥。然后,我们用从0到255之间的ASCII代码填充Ruby中的键( pre和post),所有字符都用ASCII代码填充,结果没有一个与我们在Java中得到的加密文本相匹配。这根本没有意义,因为如果Java只是简单地用任何东西填充键,它就会在原始键的开头或结尾添加一个字符。唯一的逻辑解释可能是如果Java确实通过其他方式操纵键字符串,而不是附加一个字符。
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-04-07 12:15:59

Worakarn Isaratham的回答是100%正确的,但是,我想使用标准的OpenSSL库为这个问题提供一个实现:

代码语言:javascript
复制
#!/usr/bin/ruby

require 'openssl'

def JBossPasswordEncrypt(s)
    ciph = OpenSSL::Cipher.new('bf-ecb').encrypt

    # https://source.jboss.org/browse/PicketBox/trunk/security-jboss-sx/jbosssx/src/main/java/org/picketbox/datasource/security/SecureIdentityLoginModule.java?r=332 Line 153
    ciph.key_len = 15
    ciph.key = 'jaas is the way'

    # PKCS5 Padding
    s = s + (8 - s.length % 8).chr * (8 - s.length % 8)

    # Split the secret in chunks of 8 and encrypt it
    e = s.scan(/.{8}/).map { |block| ciph.update(block).unpack('H*') }

    # Convert the bytes array into a signed number
    en = e.join.to_i(16)
    en = en - (2 ** (en.size * 8)) if en >= (2 ** (en.size * 8 - 1))

    # Return the result in hex (as string)
    return en.to_s(16)
end

puts JBossPasswordEncrypt(ARGV[0])

非常感谢您对大家的帮助!

编辑:我添加了一个有符号数字的转换,就像Java一样。不太好但很管用。

编辑:我把它写成一种更容易理解语法和注释的方法。

票数 1
EN

Stack Overflow用户

发布于 2014-04-06 18:30:15

看起来,根本没有填充键;一旦到达键的末尾,它就会从第一个字节开始。(尝试使用"abc,然后是abcabc“键,看看会发生什么。)

我建议查看这个Crypt19创业板--它们的Blowfish实现接受的键不是8的倍数,但它们只提供CBC模式,所以您需要自己实现欧洲央行。应该很容易-只是:

  • 按下信息(就像你按下键的方式)
  • 将消息拆分为8字节块,
  • 为每个块调用encrypt_block

编辑:好的,这是密码。这将产生与Java版本相同的输出,至少对于这个"Hello,world!“输入。

代码语言:javascript
复制
require 'crypt/blowfish' 

secret = "Hello, world!"
blowfish = Crypt::Blowfish.new("jaas is the way")
padded_secret = secret + (8 - secret.length % 8).chr * (8 - secret.length % 8)
encrypted = padded_secret.scan(/.{8}/).map{|block| blowfish.encrypt_block(block).unpack('H*')}.join
puts encrypted #print "17a0aef80205dd34d08dbf27a0101c9c"
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22801741

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档