On Mar 24, 2009, at 2:35 AM, Felipe Coury wrote:
> Just as a FYI, it works!!!
>
> I forgot about the remains... Take a look at the final incarnation:
>
> def mysql_key(key)
>  # The algorithm just creates a 16 byte buffer set to all zero,
>  final_key = "\0" * 16
>
>  # Number of string "blocks"
>  blocks, remain = key.length.divmod(16)
>
>  blocks.times do |i|
>    # For each block
>    key_block = key[i*16, 16]
>
>    # Runs bitwise XOR for each char on string
>    # and the same char on the block
>    16.times do |j|
>      final_key[j] ^= key_block[j]
>    end
>  end
>
>  if remain
>    remain.times do |i|
>      final_key[i] ^= key[(blocks * 16) + i]
>    end
>  end
>
>  final_key
> end
>
> And:
>
>>> mkey = mysql_key(key)
> => "dp&!{\021?pK?G!8[r."
>>> decrypt(mkey, User.find(1).password)
>  User Load (2.9ms)   SELECT * FROM `users` WHERE (`users`.`id` = 1)
> => "password"
>
> Just BEATIFUL!
>
> Thanks a lot everyone!
> --  
> Posted via http://www.ruby-forum.com/.
>


I'm glad you got it.  Your key-building function doesn't need to be  
quite so complex:

def mysql_key2(key)
   final_key = "\0" * 16
   key.length.times do |i|
     final_key[i%16] ^= key[i]
   end
   final_key
end

Hardly needs any comments now ;-)  Just a pointer to the MySQL doc  
perhaps.

irb> mkey2 = mysql_key2(key)
=> "dp&!{\021?pK?G!8[r."
irb> mkey == mkey2
=> true

-Rob

Rob Biedenharn		http://agileconsultingllc.com
Rob / AgileConsultingLLC.com