You're padding the shortest string with low values. When using
XOR to encrypt a string (my goal...), uh, you're not encrypting
most of the data:

 "very long secret data".xor("secret")   # ==> "\005\000\021\vE\030ong 
secret data"

The secret key should be repeated several times, so every byte
in the data gets XOR'ed.

In a more general situation, your solution (padding low values)
should do. And String#xor should be general, so I'm wrong...

Does "s << a" generate a new string? If so, we have a lot of
intermediate long strings.

gegroet,
Erik V. - http://www.erikveen.dds.nl/

----------------------------------------------------------------

 class String
   def xor(other, encrypting=false)
     if other.empty?
       self
     else
       a1        = self.unpack("c*")
       a2        = other.unpack("c*")

       if encrypting
         a2 *= 2 while a2.length < a1.length
       else
         l       = [a1.length, a2.length].max

         a1.concat([0x00]*(l - a1.length))
         a2.concat([0x00]*(l - a2.length))
       end

       a1.zip(a2).collect{|c1,c2| c1^c2}.pack("c*")
     end
   end
 end

 p "very long secret data".xor("secret")                 # ==> 
"\005\000\021\vE\030ong secret data"

 p "long string".xor("short")                            # ==> "\037\a
\001\025Tstring"
 p "short".xor("long string")                            # ==> "\037\a
\001\025Tstring"

 message = "This is a secret message."
 secret  = "secret"

 p message.xor(secret, false)                            # ==> "'\r\n
\001E\035s a secret message."
 p message.xor(secret, true)                             # ==> "'\r\n
\001E\035\000E\002R\026\021\020\027\006\006E
\031\026\026\020\023\002\021]"

 p message.xor(secret, false).xor(secret, false)         # ==> "This 
is a secret message."
 p message.xor(secret, true).xor(secret, true)           # ==> "This 
is a secret message."

----------------------------------------------------------------