[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Logical XOR of strings

Michael W. Ryder

5/30/2006 12:34:00 AM

I have looked in the documentation and can't find a way to XOR two
strings. I want to use this to obfuscate an identifier in a database so
that it can't be read. In the language I have used for over 20 years I
just say A$=XOR(B$,C$) to get this result. In Ruby I expect it would be
something like a = string1.xor(string2). Obviously this does not work,
but is there another way short of converting everything to numbers,
using the ^ operator on them, and then converting the result back to a
string?
9 Answers

Dave Burt

5/30/2006 2:51:00 AM

0

Michael W. Ryder wrote:
> I have looked in the documentation and can't find a way to XOR two
> strings. I want to use this to obfuscate an identifier in a database so
> that it can't be read. In the language I have used for over 20 years I
> just say A$=XOR(B$,C$) to get this result. In Ruby I expect it would be
> something like a = string1.xor(string2). Obviously this does not work,
> but is there another way short of converting everything to numbers,
> using the ^ operator on them, and then converting the result back to a
> string?

No, but it's not hard to implement:

class String
def ^(other)
other = other.to_str rescue (raise TypeError, "can't convert to string")
ret = ""
size.times {|i| ret << (self[i] ^ other[i] rescue self[i]) }
ret
end
end

Cheers,
Dave

Robert Klemme

5/30/2006 7:17:00 AM

0

Dave Burt wrote:
> Michael W. Ryder wrote:
>> I have looked in the documentation and can't find a way to XOR two
>> strings. I want to use this to obfuscate an identifier in a database so
>> that it can't be read. In the language I have used for over 20 years I
>> just say A$=XOR(B$,C$) to get this result. In Ruby I expect it would be
>> something like a = string1.xor(string2). Obviously this does not work,
>> but is there another way short of converting everything to numbers,
>> using the ^ operator on them, and then converting the result back to a
>> string?
>
> No, but it's not hard to implement:
>
> class String
> def ^(other)
> other = other.to_str rescue (raise TypeError, "can't convert to string")
> ret = ""
> size.times {|i| ret << (self[i] ^ other[i] rescue self[i]) }
> ret
> end
> end

Here's my take:

class String
def ^(key)
key = key.to_str
result = ""
for i in 0...length
result << (self[i] ^ key[i % key.length])
end
result
end
end

Kind regards

robert

Michael W. Ryder

5/30/2006 7:24:00 PM

0

Robert Klemme wrote:
> Dave Burt wrote:
>> Michael W. Ryder wrote:
>>> I have looked in the documentation and can't find a way to XOR two
>>> strings. I want to use this to obfuscate an identifier in a database so
>>> that it can't be read. In the language I have used for over 20 years I
>>> just say A$=XOR(B$,C$) to get this result. In Ruby I expect it would be
>>> something like a = string1.xor(string2). Obviously this does not work,
>>> but is there another way short of converting everything to numbers,
>>> using the ^ operator on them, and then converting the result back to a
>>> string?
>>
>> No, but it's not hard to implement:
>>
>> class String
>> def ^(other)
>> other = other.to_str rescue (raise TypeError, "can't convert to
>> string")
>> ret = ""
>> size.times {|i| ret << (self[i] ^ other[i] rescue self[i]) }
>> ret
>> end
>> end
>
> Here's my take:
>
> class String
> def ^(key)
> key = key.to_str
> result = ""
> for i in 0...length
> result << (self[i] ^ key[i % key.length])
> end
> result
> end
> end
>
> Kind regards
>
> robert

Both of those worked great. Thank you. Now I just have to figure out
what they say. The only difference in Ruby from my past experience is
that the returned strings include octal characters for the non-printable
characters but I can live with that.

Robert Klemme

5/30/2006 8:25:00 PM

0

Michael W. Ryder wrote:

> Both of those worked great. Thank you. Now I just have to figure out
> what they say. The only difference in Ruby from my past experience is
> that the returned strings include octal characters for the non-printable
> characters but I can live with that.

I don't know what you mean by that. You requested XORing of strings -
and if you XOR two strings you likely end with non printable chars.
That's totally expected behavior. Can you elaborate?

Cheers

robert

Michael W. Ryder

5/30/2006 8:31:00 PM

0

Robert Klemme wrote:
> Michael W. Ryder wrote:
>
>> Both of those worked great. Thank you. Now I just have to figure out
>> what they say. The only difference in Ruby from my past experience is
>> that the returned strings include octal characters for the
>> non-printable characters but I can live with that.
>
> I don't know what you mean by that. You requested XORing of strings -
> and if you XOR two strings you likely end with non printable chars.
> That's totally expected behavior. Can you elaborate?
>

Instead of having an ascii character 21 (decimal) in the string the
string would display \025. I don't know if the stored string just
included the character 21 or the octal representation. Using nine
character strings would at a worst case show 36 characters for the
result. I am not sure how much it would use internally or how it would
load into a database such as MySQL. I am still trying to learn Ruby as
I want to use if for customer access to their accounts.

> Cheers
>
> robert

Robert Klemme

5/30/2006 8:44:00 PM

0

Michael W. Ryder wrote:
> Robert Klemme wrote:
>> Michael W. Ryder wrote:
>>
>>> Both of those worked great. Thank you. Now I just have to figure out
>>> what they say. The only difference in Ruby from my past experience
>>> is that the returned strings include octal characters for the
>>> non-printable characters but I can live with that.
>>
>> I don't know what you mean by that. You requested XORing of strings -
>> and if you XOR two strings you likely end with non printable chars.
>> That's totally expected behavior. Can you elaborate?
>>
>
> Instead of having an ascii character 21 (decimal) in the string the
> string would display \025. I don't know if the stored string just
> included the character 21 or the octal representation. Using nine
> character strings would at a worst case show 36 characters for the
> result.

You probably have a different understanding of what you want to do than
I. When I hear string XOR this means byte wise (or character wise) XOR
and this does not result in a longer string. Are you rather looking for
encoding the result base64 to ensure only printable characters? Do you
want to have hex representation of XOR results? How do you want to
combine characters from both strings? What exactly do you want the
method to perform?

Kind regards

robert

Dave Burt

5/30/2006 10:12:00 PM

0

Michael W. Ryder wrote:
> Both of those worked great. Thank you. Now I just have to figure out
> what they say. The only difference in Ruby from my past experience is
> that the returned strings include octal characters for the non-printable
> characters but I can live with that.

You're running into a feature here. If you're using IRB, or
string.inspect, or p(string), then what you're looking at is a
displayable version of the string.

The octal escapes are legal in a Ruby string literal, and represent a
single character in the string.

If you use puts(string) or print(string) or string.display, the
"interesting" characters (such as "\n" for newline, "\t" for tab, "\025"
for ASCII char 025) will be output.

"123".length #=> 3
"\n\t\025".length #=> 3
puts "\n\t\025"
=>
§

So, the data you want is in the strings; you have our bitwise (not
"logical" as in the message subject) xor.

HTH,
Dave

Michael W. Ryder

5/30/2006 10:56:00 PM

0

Dave Burt wrote:
> Michael W. Ryder wrote:
>> Both of those worked great. Thank you. Now I just have to figure out
>> what they say. The only difference in Ruby from my past experience is
>> that the returned strings include octal characters for the non-printable
>> characters but I can live with that.
>
> You're running into a feature here. If you're using IRB, or
> string.inspect, or p(string), then what you're looking at is a
> displayable version of the string.
>
> The octal escapes are legal in a Ruby string literal, and represent a
> single character in the string.
>
> If you use puts(string) or print(string) or string.display, the
> "interesting" characters (such as "\n" for newline, "\t" for tab, "\025"
> for ASCII char 025) will be output.
>
> "123".length #=> 3
> "\n\t\025".length #=> 3
> puts "\n\t\025"
> =>

This makes it a lot clearer. I am still trying to learn the language
and the differences between it and my primary language. The language I
normally use does not display the unprintable characters so the
displayed string is often shorter than the input string. I wasn't
expecting irb to display the unprintable characters.


> §
>
> So, the data you want is in the strings; you have our bitwise (not
> "logical" as in the message subject) xor.
>
> HTH,
> Dave

Martin DeMello

5/31/2006 7:21:00 AM

0

Robert Klemme <bob.news@gmx.net> wrote:
> Michael W. Ryder wrote:
> >
> > Instead of having an ascii character 21 (decimal) in the string the
> > string would display \025. I don't know if the stored string just
> > included the character 21 or the octal representation. Using nine
> > character strings would at a worst case show 36 characters for the
> > result.
>
> You probably have a different understanding of what you want to do than
> I. When I hear string XOR this means byte wise (or character wise) XOR
> and this does not result in a longer string. Are you rather looking for
> encoding the result base64 to ensure only printable characters? Do you
> want to have hex representation of XOR results? How do you want to
> combine characters from both strings? What exactly do you want the
> method to perform?

His concern is that ruby is actually storing "\021" internally as %w(\ 0
2 1).join. Don't worry - that's merely a display artefact:

irb(main):004:0> a = "\021"
=> "\021"
irb(main):005:0> p a
"\021" # <---- inspecting the string, so it shows a human-friendly
# representation of the character
irb(main):006:0> puts a
# <------ unprintable character here


martin