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.
on 2007-11-09 22:24
on 2007-11-09 22:35
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 Moschovitis <george.moschovitis@gmail.com>
on 2007-11-10 08:25
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 2007-11-10 11:37
On Nov 10, 2:24 am, "George Moschovitis" <george.moschovi...@gmail.com> 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.
on 2007-11-10 11:43
On Nov 10, 5:37 am, Trans <transf...@gmail.com> 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 2007-11-10 12:43
On Nov 10, 5:46 am, "George Moschovitis" <george.moschovi...@gmail.com> 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. http://kylekochis.com/2007/5/5/making-hmac-hashes-in-ruby T.
on 2007-11-10 12:50
> > OpenSSL::HMAC > i think this is used in rails. Why is this better suited? Is this two-way? -g.
on 2007-11-10 13:52
On Nov 10, 6:45 am, "George Moschovitis" <george.moschovi...@gmail.com> 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. http://en.wikipedia.org/wiki/HMAC Plus it's built into ruby. T.
on 2007-11-10 23:54
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
on 2007-11-11 02:25
On Nov 10, 5:23 pm, Timothy <interfe...@gmail.com> 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 ;) T.
on 2007-11-11 12:10
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 2007-11-11 17:22
On Nov 11, 6:09 am, "George Moschovitis" <george.moschovi...@gmail.com> 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.
on 2007-11-11 19:00
From: George Moschovitis > > 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 2007-11-11 19:07
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 2007-11-11 21:00
On Nov 11, 1:07 pm, "George Moschovitis" <george.moschovi...@gmail.com> 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.
on 2007-11-12 23:22
Hi George, From: George Moschovitis > > 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 2007-11-13 00:22
On Nov 12, 5:16 pm, "Bill Kelly" <bi...@cts.com> 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.
on 2007-11-13 00:53
From: "Trans" <transfire@gmail.com> > tracking that down, or did you just "see it" when looking over the > code? Thanks :) I didn't end up using your test case, because my test suite for my online store controller already tended to encounter the cookie problem every so often. (I had switched to the MemorySessionStore awhile back as a workaround.) So I went low-tech and put in some print statements and kept re-running my test suite until the error occurred. 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.) Regards, Bill
on 2007-11-13 07:54
> > 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.
on 2007-11-13 07:55
data = Base64.encode64(Marshal.dump(session)).chop
data = CGI.escape("#{data}--#{generate_digest(data)}")
as you can see the diggest is generated *before* escaping, ie it is
unescapped just like when it read back.
am I missing something?
-g.
on 2007-11-13 08:23
From: George Moschovitis > > data = Base64.encode64(Marshal.dump(session)).chop > data = CGI.escape("#{data}--#{generate_digest(data)}") > > as you can see the diggest is generated *before* escaping, ie it > is unescapped just like when it read back. > am I missing something? I think the encode is fine. But: def decode(data) data, digest = CGI.unescape(data).split("--") raise AlteredCookie.new unless digest == generate_digest(data) return Marshal.load(Base64.decode64(data)) end For whatever reason, 'data' passed to decode is already unescaped. So calling unescape again seems to convert '+' into ' ' (space). E.g. >> x = CGI.escape("hey+there") => "hey%2Bthere" >> CGI.unescape(x) => "hey+there" >> CGI.unescape(CGI.unescape(x)) => "hey there" Regards, Bill
on 2007-11-13 09:18
> > >> x = CGI.escape("hey+there") > => "hey%2Bthere" > >> CGI.unescape(x) > => "hey+there" > >> CGI.unescape(CGI.unescape(x)) > => "hey there" > AHA!!!!! -g.
on 2007-11-13 11:30
On Sunday 11 November 2007 14:24:54 Trans wrote: > couldn't care less if anyone finds out my shoe size ;) > > T. > > _______________________________________________ > Nitro-general mailing list > Nitro-general@rubyforge.org > http://rubyforge.org/mailman/listinfo/nitro-general HMAC would be suitable for authentication of a message but how does adding it to cookies improve over using a single, random session id cookie and storing all sensitive data in a session store? Why would you want to authenticate messages to yourself when you could just keep them in your sight? I'm aware that for some small things it could be advantageous to avoid a roundtrip to a database due to frequent use but it's these same, frequently used pieces of data that will be expensive to verify repeatedly. It is common to see user preferences in cookies because the user cannot do any harm by changing them. Such applications should assume that the user might do so. Anything more sensitive should be kept serverside. Timothy
on 2007-11-13 13:38
On Nov 13, 5:29 am, Timothy <interfe...@gmail.com> wrote:
> Anything more sensitive should be kept serverside.
I agree. I don't think it wise to use a cookie for anything that needs
to be secure, other then a session key.
T.
on 2007-11-13 13:47
I think the cookie session store is a great idea because it keeps the (small) state to the client. So i can redirect the client to different servers in my cluster w/o worrying about synchronizing state. btw, bills fix seems to have solved the AlteredCookie bug! :) :) -g.
on 2007-11-14 16:01
On Nov 13, 7:46 am, "George Moschovitis" <george.moschovi...@gmail.com> wrote: > I think the cookie session store is a great idea because it keeps the > (small) state to the client. So i can redirect the client to different > servers in my cluster w/o worrying about synchronizing state. Sure, i think it's great too. But not for secure data. > btw, bills fix seems to have solved the AlteredCookie bug! :) :) Yea! Shall we add the bug he found as a testcase? We can use the one I put together as a basis if need be. T.