Symetrical encryption algo's?

Hi list.

I need to encode some data with a userID and then also be able to
decode it with the same key.

This is basically a quick approach to obfuscate URLs. Its for an
environment where we know the users ID with some degree of certainty.

Are there any libraries/simple algorithms to do this in ruby? it might
be as simple as bitshiting a string around...

any other suggested alternatives to this approach?

tx

/dc

···

-------------------------------------------
      David "DC" Collier
mailto:dc@pikkle.com
      +81 (0)80 6521 9559
      skype: callto://d3ntaku
-------------------------------------------
      Pikkle 株式会社
      http://www.pikkle.com
-------------------------------------------

dc wrote:

Hi list.

Hi.

I need to encode some data with a userID and then also be able to
decode it with the same key.

This is basically a quick approach to obfuscate URLs. Its for an
environment where we know the users ID with some degree of certainty.

Are there any libraries/simple algorithms to do this in ruby? it might
be as simple as bitshiting a string around...

Is "bitshiting" what happens when you eat one byte at a time? :slight_smile:

any other suggested alternatives to this approach?

Let your key be an integer. XOR each byte (or set of bytes) in the
string by the integer to encode. To decode, XOR them again. Let me
know if you'd like code. (Actually, I'd be interested to see other
people's implementations. :wink:

dc wrote:

I need to encode some data with a userID and then also be able to
decode it with the same key.
This is basically a quick approach to obfuscate URLs. Its for an
environment where we know the users ID with some degree of
certainty.

Simple obfuscation can be done by XORing a keyword. On a binary layer
this works as follows:

Calling Key K, Original messages O, transmitted Message T here's a
binary example:

K = 1010
V = 1001010111101001

1001010111101001
1010101010101010
0011111101000011

T = 0011111101000011

In this particular encoding is not secure because K is not random and
much shorter than V. In contrast to false rumors XOR coding is not
inherently insecure. Quite the opposite is true: When K is perfectly
random and at least as long as V the coding is the only one known to
mankind that can be mathematically proved to be unbreakable.
According to certain sources the XOR encoding with perfectly random K
is used for the launch command for nuclear SMBs (submarine based
missiles). That may be an uran legend. A fact is that many programs
that allow you to password-encode a file actually XOR the file's
content with the Password. Which means that a more random and longer
passwords results in a more secure encoding.

じゃまた、

Jupp

I played around with the Tiny Encryption Algorithm[1] a year or so ago
and ended up with a quick ruby implementation of it that is a snippet on
rubyforge. (http://rubyforge.org/snippet/detail.php?type=snippet&id=101\)

enjoy,

-jeremy

[1] - Tiny Encryption Algorithm - Wikipedia

···

On Sun, Oct 29, 2006 at 04:51:59AM +0900, dc wrote:

Hi list.

I need to encode some data with a userID and then also be able to
decode it with the same key.

This is basically a quick approach to obfuscate URLs. Its for an
environment where we know the users ID with some degree of certainty.

Are there any libraries/simple algorithms to do this in ruby? it might
be as simple as bitshiting a string around...

any other suggested alternatives to this approach?

--

Jeremy Hinegardner jeremy@hinegardner.org

I have a feeling I'm missing something, but if all you want to do is
generate obfuscated URLs, why not just the the SHA1-hash of a string
consisting of the "real" url and the user's name? You can store the
generated urls in the server-side user-session so you don't have to do any
decrypting.

···

On 10/28/06, dc <lister@pikkle.com> wrote:

Hi list.

I need to encode some data with a userID and then also be able to
decode it with the same key.

This is basically a quick approach to obfuscate URLs. Its for an
environment where we know the users ID with some degree of certainty.

Are there any libraries/simple algorithms to do this in ruby? it might
be as simple as bitshiting a string around...

any other suggested alternatives to this approach?

tx

I'd say: if obfuscation is enough, do base64encode.reverse and if not,
use AES from OpenSSL

···

On 10/28/06, Josef 'Jupp' Schugt <jupp@gmx.de> wrote:

dc wrote:
> I need to encode some data with a userID and then also be able to
> decode it with the same key.
> This is basically a quick approach to obfuscate URLs. Its for an
> environment where we know the users ID with some degree of
> certainty.

Simple obfuscation can be done by XORing a keyword. On a binary layer
this works as follows:

Calling Key K, Original messages O, transmitted Message T here's a
binary example:

K = 1010
V = 1001010111101001

1001010111101001
1010101010101010
0011111101000011

T = 0011111101000011

In this particular encoding is not secure because K is not random and
much shorter than V. In contrast to false rumors XOR coding is not
inherently insecure. Quite the opposite is true: When K is perfectly
random and at least as long as V the coding is the only one known to
mankind that can be mathematically proved to be unbreakable.
According to certain sources the XOR encoding with perfectly random K
is used for the launch command for nuclear SMBs (submarine based
missiles). That may be an uran legend. A fact is that many programs
that allow you to password-encode a file actually XOR the file's
content with the Password. Which means that a more random and longer
passwords results in a more secure encoding.

じゃまた、

Jupp

hi -

> any other suggested alternatives to this approach?

Let your key be an integer. XOR each byte (or set of bytes) in the
string by the integer to encode. To decode, XOR them again. Let me
know if you'd like code. (Actually, I'd be interested to see other
people's implementations. :wink:

I googled a bit and found something in this direction, but cant get
the reverse of it
(at least not a working version!)
Would appreciate a working fragment...

        def encr str
            key = "ABC123abc123ABC456ABC123abc" # long enough?
            result = (0..str.length-1).collect { |i|
                $stderr.puts("#{i} #{str[i]}")
                str[i] ^ key[i]
            }
            result.pack("C*")
            return result
        end

does the key have to be an integer for XOR ( ^ operator ) to work?

tx!

/dc

Maybe the URL he's obfusicating doesn't go to a machine under his control?

I have a requirement for something like this right now.

A web site with private content links to an external provider. The users log into the private content with a standard userid/password authentication.

The external provider trusts my authentication, so they want liks to them to encode the userid using a symetric algorithm with a specific key. The users just see a url like:

http://foo.com/place?1b12d9542f%2F33b1a4

and feel all warm and fuzzy. The external provider can recover the userid from that, though, and can thus give the user their specific content.

I'm using the http://rubyforge.org/projects/crypt/ library for this.

Kirk Haines

···

On Sun, 29 Oct 2006, Francis Cianfrocca wrote:

I have a feeling I'm missing something, but if all you want to do is
generate obfuscated URLs, why not just the the SHA1-hash of a string
consisting of the "real" url and the user's name? You can store the
generated urls in the server-side user-session so you don't have to do any
decrypting.

hi -

I have a feeling I'm missing something, but if all you want to do is
generate obfuscated URLs, why not just the the SHA1-hash of a string
consisting of the "real" url and the user's name? You can store the
generated urls in the server-side user-session so you don't have to do any
decrypting.

is there a way to de-sha1 these hashed results to get the original data?
and to do the shash with a specific key?
all i could find was:

           res = Digest::SHA1.hexdigest(str)

whats the reverse of this,
and where is the key from?

we need to pass URLs back and forth from a ruby site to a PHP site. so
i was looking for a reasonably easy algorithm that would work for
both. I've had problems with blowfish on PHP giving different results
on different OSs. So i dont really want to risk something more obscure
given such different environments.

this is also for a mobile phone service where we reliably can get a
uniqueID per user.

we need to prevent people forwarding URLs which is why we need to key
off the uniqueID

but I need to be able to go both ways, given the key. eg:

ruby.site.com/uri=1b2347ghjhsdgf

I can then decode this + with the users ID/key + send them on their way,
and also pack up URLs to send ppl back to the php page.

other suggestions are to put all the URLs in a DB + then check against
the userID/urlID key etc but i want to avoid DB access.

tx!

Jan Svitok wrote:

I'd say: if obfuscation is enough, do base64encode.reverse and if
not, use AES from OpenSSL

I wanted to provide a one-size-fits-it-all algorithm that can more or
less easily be implemented without using any external library.

Jupp
- --
Switched character encoding to sth. more common :slight_smile:

SHA1 is, to my knowledge, not reversable.

J`ey
http://www.eachmapinject.com

···

On 10/29/06, dc <lister@pikkle.com> wrote:

           res = Digest::SHA1.hexdigest(str)

whats the reverse of this,
and where is the key from?

<snip>

is there a way to de-sha1 these hashed results to get the original data?
and to do the shash with a specific key?
all i could find was:

         res = Digest::SHA1.hexdigest(str)

whats the reverse of this,
and where is the key from?

No.

A hashing algorithm is a one way algorithm. You can't get your original data back from it.

we need to pass URLs back and forth from a ruby site to a PHP site. so
i was looking for a reasonably easy algorithm that would work for
both. I've had problems with blowfish on PHP giving different results
on different OSs. So i dont really want to risk something more obscure
given such different environments.

As I've mentioned, I'm doing this using a pure ruby crypto library found on Rubyforge: http://rubyforge.org/projects/crypt/

but I need to be able to go both ways, given the key. eg:

ruby.site.com/uri=1b2347ghjhsdgf

I can then decode this + with the users ID/key + send them on their way,
and also pack up URLs to send ppl back to the php page.

If Rijndael(AES), Gost, or IDEA can work reliably via PHP, then you do something like this:

irb(main):001:0> require 'rubygems'
=> true

irb(main):002:0> require 'crypt/rijndael'
=> true

irb(main):003:0> require 'base64'
=> true

irb(main):004:0> require 'cgi'
=> true

irb(main):005:0> uri = 'uri=1b2347ghjhsdgf'
=> "uri=1b2347ghjhsdgf
"
irb(main):006:0> crypto = Crypt::Rijndael.new('I am a key')
=> #<Crypt::Rijndael:0xb726dd9c @shiftIndex=0, @keyWords=8, @blockWords=4, ...[snip]...

irb(main):007:0> encrypted_uri = CGI.escape(Base64::encode64(crypto.encrypt_string(uri)))
=> "Ai32bnCHRKW1xVEfjtNt63dSQRzRq8SPCSiS6gs9b9fgteBEBSFB%2BLRYdUD2%0AijDQ%0A"

irb(main):008:0> url = "ruby.site.com/#{encrypted_uri}"
=> "ruby.site.com/Ai32bnCHRKW1xVEfjtNt63dSQRzRq8SPCSiS6gs9b9fgteBEBSFB%2BLRYdUD2%0AijDQ%0A"

Just reverse the steps to get the original data back:

irb(main):009:0> original = crypto.decrypt_string(Base64::decode64(CGI.unescape(encrypted_uri)))
=> "uri=1b2347ghjhsdgf"

Kirk Haines

···

On Sun, 29 Oct 2006, dc wrote:

I probably shouldn't get into this because it's offtopic, but why not just
use a plain-vanilla federated identity solution with the external provider?

···

On 10/29/06, khaines@enigo.com <khaines@enigo.com> wrote:

I have a requirement for something like this right now.

A web site with private content links to an external provider. The users
log into the private content with a standard userid/password
authentication.

The external provider trusts my authentication, so they want liks to them
to encode the userid using a symetric algorithm with a specific key. The
users just see a url like:

http://foo.com/place?1b12d9542f%2F33b1a4

and feel all warm and fuzzy. The external provider can recover the userid
from that, though, and can thus give the user their specific content.

dc wrote:

hi -

> any other suggested alternatives to this approach?

Let your key be an integer. XOR each byte (or set of bytes) in the
string by the integer to encode. To decode, XOR them again. Let me
know if you'd like code. (Actually, I'd be interested to see other
people's implementations. :wink:

I googled a bit and found something in this direction, but cant get
the reverse of it
(at least not a working version!)

The point of the technique is that if you get it working one way, it automatically works the other way, too. The same function encrypts and decrypts.

Would appreciate a working fragment...

       def encr str
           key = "ABC123abc123ABC456ABC123abc" # long enough?

Depends on how strong you need the encryption to be. :slight_smile:

           result = (0..str.length-1).collect { |i|
               $stderr.puts("#{i} #{str[i]}")
               str[i] ^ key[i]
           }
           result.pack("C*")
           return result
       end

does the key have to be an integer for XOR ( ^ operator ) to work?

No, but the XOR operation for whatever object type you use has to undo itself when applied an even number of times. A plain old bit-pattern works nicely, and bit-patterns are easy to visualize as integers.

Here's a quick example that uses an 8-bit key for simplicity. To use a larger key of N bits, you'll probably want to break it into (N / 8 + (N % 8 == 0 ? 0 : 1)) bytes, and rotate which byte you're XORing as you walk through the bytes of the string.

def encr(s, k)
     r = ''
     s.each_byte { |b| r += (b ^ k).chr }
     r
end

s = "hello"
k = 42

e = encr(s, k)
puts e # "BOFFE" on ASCII-like machines.
puts encr(e, k) # Re-creates the original string.

http://rubyforge.org/projects/crypt/

AES, Blowfish, IDEA, Gost all supported with pure ruby.

Kirk Haines

···

On Sun, 29 Oct 2006, Josef 'Jupp' Schugt wrote:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Jan Svitok wrote:
> I'd say: if obfuscation is enough, do base64encode.reverse and if
> not, use AES from OpenSSL

I wanted to provide a one-size-fits-it-all algorithm that can more or
less easily be implemented without using any external library.

Josef 'Jupp' Schugt wrote:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Jan Svitok wrote:
> I'd say: if obfuscation is enough, do base64encode.reverse and if
> not, use AES from OpenSSL

I wanted to provide a one-size-fits-it-all algorithm that can more or
less easily be implemented without using any external library.

OpenSSL extensions come with the Ruby standard library. Require
'openssl'.

···

Jupp
- --
Switched character encoding to sth. more common :slight_smile:
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (GNU/Linux)

iD8DBQFFQ81Hrhv7B2zGV08RApTmAJ9qMwAFjypLqS8BPo9wA00iy4c94wCgi2QI
1fT2I07IQHxxf4qhh+jb66Q=
=jMQ5
-----END PGP SIGNATURE-----

Because encrypting the id and putting it into the URL is trivial to implement, costs nothing, is sufficiently secure for this application, and provides the external folks with the information that they need.

Kirk Haines

···

On Mon, 30 Oct 2006, Francis Cianfrocca wrote:

I probably shouldn't get into this because it's offtopic, but why not just
use a plain-vanilla federated identity solution with the external provider?

Thanks for all the help.

it could probly be done in one line, but attaching one fairly verbose
solution below; i found i had to convert the various items to integers
for them to XOR back and forth properly....

def strxor instr, keystr
    outstr = CGI::unescape(instr)
    puts "xoring #{outstr}"
    outstr.length.times {|x|
        keychar = keystr[x % keystr.length].to_i
        inchar = instr.to_i
        outchar = inchar ^ keychar
        outstr = outchar
        # puts "#{inchar} ^ #{keychar} -> #{outchar}"
    }
    return outstr
end

# encr a safe str
def encr str, key
    str = strxor(str, key)
    return CGI::escape(str)
end

# decr an ugly URL
def decr str, key
    str = CGI::unescape(str)
    return( strxor(str, key))
end

key = "1x3*"
str = "some/1&url?id=10"
enc = encr(str, key)
dec = decr(enc, key)
puts "enc: #{enc}"
puts "dec: #{dec}"

# gives me>>>

xoring some/1&url?id=10
xoring B^OI_C
             CUE
enc: B%17%5EO%1EI%15_C%14%0CCUE%02%1A
dec: some/1&url?id=10

tx

/dc

···

On 30/10/06, khaines@enigo.com <khaines@enigo.com> wrote:

On Mon, 30 Oct 2006, Francis Cianfrocca wrote:

> I probably shouldn't get into this because it's offtopic, but why not just
> use a plain-vanilla federated identity solution with the external provider?

Because encrypting the id and putting it into the URL is trivial to
implement, costs nothing, is sufficiently secure for this application, and
provides the external folks with the information that they need.

Kirk Haines

--
-------------------------------------------
      David "DC" Collier
mailto:dc@pikkle.com
      +81 (0)80 6521 9559
      skype: callto://d3ntaku
-------------------------------------------
      Pikkle 株式会社
      http://www.pikkle.com
-------------------------------------------