Two way crypt function

I ve asked this before:

is there a two-way ‘crypt’ function in ruby?

ie:

a = encrypt(original, “mysecret”)
b = decrypt(a, “mysecret”)

===> b == original

thanks in advance for any help. I am looking for something fast (not
super
secure)

-g.

Here is blowfish

http://crypt.rubyforge.org/blowfish.html

and here is Rijndael

http://crypt.rubyforge.org/rijndael.html

On Nov 9, 2007 4:24 PM, George M.
[email protected]

previous reply –
http://article.gmane.org/gmane.comp.lang.ruby.nitro.general/8394/match=crypt

Thanks,

ezcrypto does the work!

I am thinking about encrypting the session data with a two-way method
and
skip the diggest test. Anyone sees any problems?

-g.

On Nov 10, 5:37 am, Trans [email protected] wrote:

I am thinking about encrypting the session data with a two-way method and
skip the diggest test. Anyone sees any problems?

How will that effect the cookie size? BTW, How were you doing the
digest to begin with? Were you using facets/crypt.rb? I would like to
add a two-way routine to that lib, to have available for simple cases.

Actually, I just added one, and called it BiCrypt.

T.

On Nov 10, 2:24 am, “George M.”
[email protected] wrote:

Thanks,

ezcrypto does the work!

Thing I don’t like about this lib – it is for Rails. They’ve embedded
EzCrypto and ActiveCrypto in the same package. I don’t think that’s
good for Nitro. Maybe we can ask them to split the package in two?

I am thinking about encrypting the session data with a two-way method and
skip the diggest test. Anyone sees any problems?

How will that effect the cookie size? BTW, How were you doing the
digest to begin with? Were you using facets/crypt.rb? I would like to
add a two-way routine to that lib, to have available for simple cases.

T.

Cool,

is this fast? This encryption/decrption will be done per request.

-g.

On Nov 10, 5:46 am, “George M.”
[email protected] wrote:

Cool,

is this fast? This encryption/decrption will be done per request.

Eeeewwww. I mean, I’m sure it’s fairly quick. It’s not that
complicated, but it is Ruby. If you are going to be doing this per
request, you should consider something C-based.

Actually, a little more research reveals what’s is probably the right
answer:

OpenSSL::HMAC

See. kylekochis.com

T.

On Nov 10, 6:45 am, “George M.”
[email protected] wrote:

OpenSSL::HMAC

i think this is used in rails. Why is this better suited? Is this two-way?

B/c it was designed to do pretty much exactly you are wanting to do.

HMAC - Wikipedia

Plus it’s built into ruby.

T.

OpenSSL::HMAC

i think this is used in rails. Why is this better suited? Is this
two-way?

-g.

HMAC is not appropriate for this! HMAC is for authentication over a
network,
not for encryption. HMAC is not reversible. If you want to be able to
store
data in cookies securely I would use a system like this:

In advance you need to select a constant global key for the application.

For each session:

  1. Create a random session key, encrypt it with the global key. Store
    this in
    a cookie with a constant name (e.g. NITRO_SESS_KEY).

  2. For each cookie you want to store, encrypt it to the session key and
    put it
    in a cookie. You could use one cookie for all the data or break it up in
    to
    related groups.

  3. To recover a cookie, decrypt the session key using the global key.
    You can
    then use the session key to decrypt the cookie contents. Sanity checks
    or an
    included digest should be used to detect invalid data.

Notes:

  1. The separate session key is used to minimise the risk of somebody
    finding
    the global key. If a person can compromise the session key then they can
    read
    and alter the session data from that session. If they can get the global
    key
    then they can read and alter the data from any session.

  2. If the content of session data is predictable (size would be a good
    predictor of this) it should probably have some random data prepended to
    make
    it harder to use known plaintext attacks.

  3. It is worth only decrypting the session when it is accessed to avoid
    unnecessary CPU load.

For encryption in Ruby you want to use the OpenSSL library. The ruby
bindings
are part of the standard library.

Cheers,

Tim

My problem is that sometimes, for some stupid reason, the digest
integrity
check fails for non altered cookies.
Ie you get AlteredCookie exceptions for now reason.
I really can’t find the problem.

So I was thinking, I could just encrypt/decrypt the cookie with a fast 2
way
encryption method and
solve this once and for all.

-g.

On Nov 10, 5:23 pm, Timothy [email protected] wrote:

HMAC is not appropriate for this! HMAC is for authentication over a network,
not for encryption.

Currently authentication is all George is doing and that’s what I was
suggesting it for. Also, HMAC is a part of OpenSSL.

I think if you go so far as to enrypt cookies, you should consider
carefully if you should be using cookies to begin with. Also don’t
bother encrypting any cookie that doesn’t really need to be. I
couldn’t care less if anyone finds out my shoe size :wink:

T.

From: George M.

My problem is that sometimes, for some stupid reason, the digest
integrity check fails for non altered cookies.
Ie you get AlteredCookie exceptions for now reason.
I really can’t find the problem.

Would it be feasible to add some temporary debugging, to store
the exact binary data of the original cookie alongside the
digest? So that, later, when the integrity check fails, you
can compare the exact bytes of the old cookie against the new
cookie?

(Or if I’ve misunderstood the problem, I’m sorry.)

But it seems like there are three possibilities:

  • the cookie bytes really did change somehow
  • the stored digest bytes got mutated somehow
  • the digest code is broken and has randomness

It seems like it should be possible (by storing the original
cookie bytes for debug purposes) to have all the data needed
to narrow down the possibilities?

Regards,

Bill

On Nov 11, 6:09 am, “George M.”
[email protected] wrote:

My problem is that sometimes, for some stupid reason, the digest integrity
check fails for non altered cookies.
Ie you get AlteredCookie exceptions for now reason.
I really can’t find the problem.

What lib are you using to check the cookies?

T.

I have added all the debugging aids. This bug is random and I still
cannot
understand why it happens.
the offending code is:

lib/raw/context/session/cookie.rb

-g.

On Nov 11, 1:07 pm, “George M.”
[email protected] wrote:

I have added all the debugging aids. This bug is random and I still cannot
understand why it happens.
the offending code is:

lib/raw/context/session/cookie.rb

Add this to the end of that file:

if FILE == $0

BEGIN {
require “facets”
require “facets/random”
require “cgi”

require "raw/context/session"
require "raw/controller/cookie"

}

require “test/unit”

class TestCookie < Test::Unit::TestCase

class MockContext
  def initialize
    @cookies = {}
    @data = {}
  end
  def cookies
    @data
  end
  def add_cookie(cookie)
    @cookies[cookie.name] = cookie
    @data[cookie.name] = cookie.value
  end
end

def setup
  @cookie_store = Raw::CookieSessionStore.new
end

def test_simple
  context = MockContext.new
  input = "RABBIT DATA"
  @cookie_store.put(input, context)
  output = @cookie_store.get(context)
  assert_equal(input, output)
end

context = MockContext.new
maxsize = 1000

1000.times do |i|
  input = String.random((rand * maxsize).to_i, /[\w\W]/)

  define_method("test_#{i}") do
    @cookie_store.put(input, context)
    output =  @cookie_store.get(context)
    assert_equal(input, output)
  end
end

end

end

I ran it a few times now and it’s working fine. So that should narrow
the possibilities.

My guess as the moment is Bill’s #1. The cookies must be changing
somehow when it moves through the browser.

Perhaps you are not the only one using the cookie name?

Also, going the encryption route won’t buy you anything if you still
plan to have the JSON formatted data available to the browser.

T.

Hi George,

From: George M.

I have added all the debugging aids. This bug is random and I still
cannot understand why it happens.
the offending code is:

lib/raw/context/session/cookie.rb

It appears that while the encoded cookie data going out has been
URL encoded with %0A %2B etc…

WARN: --old–> “BAhJQzoRUmF3OjpTZXNzaW9uewciDm9yZGVyX29pZGlaIgpG
TEFTSElDOhlS%0AYXc6OkZsYXNoaW5nOjpGbGFzaHsABjoLQGRpcnR5ewAGOg1AZ
XhwaXJlc3U6%0ACVRpbWUNlukagFY%2BaVE%3D%0A–fae0818a4fea3a7a9285c46f101297ea6eb11d08781a45be7c25d46ef75a2ceb
8c25feb5f1a0e5744594f6ade3f0835956e5b1bca9ae5750fe99f859d47c86b2”

WARN: %%%%%%%% digest: Session.secret=“public”
WARN: -input-> “BAhJQzoRUmF3OjpTZXNzaW9uewciDm9yZGVyX29pZGlaIgpG
TEFTSElDOhlS\nYXc6OkZsYXNoaW5nOjpGbGFzaHsABjoLQGRpcnR5ewAGOg1AZX
hwaXJlc3U6\nCVRpbWUNlukagFY+aVE=\n”
WARN: -hash–>
fae0818a4fea3a7a9285c46f101297ea6eb11d08781a45be7c25d46ef75a2ceb
8c25feb5f1a0e5744594f6ade3f0835956e5b1bca9ae5750fe99f859d47c86b2

…The encoded data coming back in has already had the %xx URL
encoding decoded into literal characters:

WARN: --new–> “BAhJQzoRUmF3OjpTZXNzaW9uewciDm9yZGVyX29pZGlaIgpG
TEFTSElDOhlS\nYXc6OkZsYXNoaW5nOjpGbGFzaHsABjoLQGRpcnR5ewAGOg1AZX
hwaXJlc3U6\nCVRpbWUNlukagFY+aVE=\n–
fae0818a4fea3a7a9285c46f101297ea6eb11d08781a45be7c25d46ef75a2ceb
8c25feb5f1a0e5744594f6ade3f0835956e5b1bca9ae5750fe99f859d47c86b2”

…And as such, when CGI.decode is called on these already-literal
characters, a literal ‘+’ will be converted to a space ’ ’ by
CGI.unescape.

WARN: %%%%%%%% digest: Session.secret=“public”
WARN: -input-> “BAhJQzoRUmF3OjpTZXNzaW9uewciDm9yZGVyX29pZGlaIgpG
TEFTSElDOhlS\nYXc6OkZsYXNoaW5nOjpGbGFzaHsABjoLQGRpcnR5ewAGOg1AZX
hwaXJlc3U6\nCVRpbWUNlukagFY aVE=\n”
WARN: -hash–>
859210ca5f0bfbaf57e94fbadc8c4eb9ac4c0deb6caf6ec02b664d675ea9150f
840c4dfaa41f646b51a836cd4c391bbe05a44c9dc7f495a6d9e001370181b958

Thus the digest was originally generated on data above that
ended in “…kagFY+aVE=\n”. But when the digest is later called
to converm the data, it is called on data that looks like:
“…kagFY aVE=\n”.

(Where the + has been replaced with a space.)

Hope this helps,

Bill

On Nov 12, 5:16 pm, “Bill K.” [email protected] wrote:

(Where the + has been replaced with a space.)

Hope this helps,

Good job Bill!

So how did you figure it? Did my test case come in handy at all in
tracking that down, or did you just “see it” when looking over the
code?

T.

But I haven’t studied the rest of the code enough to understand
why the data in context.cookies[Session.cookie_name] is already
CGI.unescape’d (maybe it’s supposed to be.)

It is supposed to be. But I cannot understand why the diggest is
generated
on CGI.encodeded input in the first place.

I will have a better look, thanks!

-g.