问题
This is confusing me.
When I try and use the following inputs to encrypt a string with Blowfish: key = "some key" input = "input string"
I get the following results:
ruby: ["79af8c8ee9220bde"]
php: 79af8c8ee9220bdec2d1c9cfca7b13c6
I am going to be receiving strings from a php application so I need to get these two to sync up but I don't understand why the php string would be longer. What am I missing?
php code:
php > require_once 'Crypt/Blowfish.php';
php > $input = "input string";
php > $key = "some key";
php > $crypt = new Crypt_Blowfish($key);
php > echo bin2hex($crypt->encrypt($input));
79af8c8ee9220bdec2d1c9cfca7b13c6
ruby code:
irb(main):001:0> require 'rubygems'
=> true
irb(main):002:0> require 'crypt/blowfish'
=> true
irb(main):003:0> input = "input string"
=> "input string"
irb(main):004:0> key = "some key"
=> "some key"
irb(main):005:0> blowfish = Crypt::Blowfish.new(key)
=> #<Crypt::Blowfish:0xb74b10c4 @sBoxes=[[3156471959, 1769696695, 1443271708, 181204541,
...... 1894848609], @key="some key">
irb(main):006:0> blowfish.encrypt_block(input)
=> "y\257\214\216\351\"\v\336"
irb(main):007:0> blowfish.encrypt_block(input).unpack("H*")
=> ["79af8c8ee9220bde"]
回答1:
Assuming that Crypt_Blowfish
either uses mcrypt or acts just like it, you're encountering a padding issue. In particular, the string is being right-padded with null bytes until it's as long as a multiple of the block size. From the PHP interactive shell:
php > $bf = mcrypt_module_open('blowfish', '', 'ecb', '');
php > $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($bf), MCRYPT_DEV_RANDOM);
php > $key = 'some key';
php > mcrypt_generic_init($bf, $key, $iv);
php > echo mcrypt_enc_get_block_size($td);
8
php > echo bin2hex(mcrypt_generic($bf, 'input string'));
79af8c8ee9220bdec2d1c9cfca7b13c6
php > echo bin2hex(mcrypt_generic($td, "input string\0\0\0\0"));
79af8c8ee9220bdec2d1c9cfca7b13c6
There doesn't seem to be an obvious way to change the padding mode in mcrypt
, and I don't know who wrote the library you're using. Check for a padding mode in the module's documentation.
With any luck, you can just set Ruby's padding mode instead, or simply null-pad the string on Ruby's side.
回答2:
Hold on, your Ruby output is 8 bytes? Your input is 12 - it's the Ruby code that's in error here.
I haven't used Crypt::Blowfish (and the documentation is scarce) but you may need to pad your input to a multiple of 64 bits, anyway.
回答3:
Since Blowfish is a 64-bit block cipher you'll have to pad the data and the Ruby implementation doesn't do that for you automatically.
s = "input string"
len = s.length
mod = 8-len%8
padded = s.ljust(len+mod, "\0")
I just have to show my first attempt...
encrypted = blowfish.encrypt_block(input.
each_char.
each_slice(8).
map {|slice|
slice.count==8 ? slice.join : slice.join.ljust(8,"\0")}.join
I used \0 since that it seems that that is what PHP uses.
回答4:
I don't know what Crypt/Blowfish.php is or what it's ->encrypt() method does but it's likely the difference in string is php using a salt when calling crypt().
回答5:
It looks like the php custom Blowfish script is encrypting incorrectly.
In PHP4 and PHP5, you can use the built in crypt
function to encrypt with Blowfish.
PHP crypt().
CRYPT_BLOWFISH - Blowfish hashing with a salt as follows: "$2a$", a two digit cost parameter, "$", and 22 base 64 digits from the alphabet "./0-9A-Za-z". Using characters outside of this range in the salt will cause crypt() to return a zero-length string. The two digit cost parameter is the base-2 logarithm of the iteration count for the underlying Blowfish-based hashing algorithmeter and must be in range 04-31, values outside this range will cause crypt() to fail.
So you can call $hash = crypt($yourString, '$2a$07$'.$aSalt)
to encrypt using Blowfish.
If you don't have access to the PHP code, ignore this answer entirely.
回答6:
Try blowfish.encrypt_string
instead of encrypt_block
来源:https://stackoverflow.com/questions/5465148/encrypting-a-string-with-blowfish-in-ruby-returns-a-shorter-string-than-the-same