Logical XOR of strings

M

Michael W. Ryder

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?
 
D

Dave Burt

Michael said:
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 ^ other rescue self) }
ret
end
end

Cheers,
Dave
 
R

Robert Klemme

Dave said:
Michael said:
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 ^ other rescue self) }
ret
end
end


Here's my take:

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

Kind regards

robert
 
M

Michael W. Ryder

Robert said:
Dave said:
Michael said:
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 ^ other rescue self) }
ret
end
end


Here's my take:

class String
def ^(key)
key = key.to_str
result = ""
for i in 0...length
result << (self ^ 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.
 
R

Robert Klemme

Michael said:
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
 
M

Michael W. Ryder

Robert said:
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.
 
R

Robert Klemme

Michael said:
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
 
D

Dave Burt

Michael said:
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
 
M

Michael W. Ryder

Dave said:
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.
 
M

Martin DeMello

Robert Klemme said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top