Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Encryption Question

by Purdy (Hermit)
on Nov 01, 2001 at 23:30 UTC ( [id://122640]=perlquestion: print w/replies, xml ) Need Help??

Purdy has asked for the wisdom of the Perl Monks concerning the following question:

I have a small userid (6 digits) that I want to use as a url for renewing a subscription, such as:

http://www.mysite.com/renew.cgi?id=213455

But I don't want to have the id in plain view like that (been told that's bad {why?}). I've been playing around with CBC & Blowfish, but the resulting encryption is too long (it will make the line wrap, which will break the link in some mail clients I plan on e-mailing the link to.

So my question is, is there an available encryption scheme that will encrypt that (and decrypt the encrypted string) where I can specify the length of the encrypted string, or where the length of the encrypted string is not-so-long. (crypt() isn't too long, but I need to decrypt, so that's out)

Thanks!

Jason

Replies are listed 'Best First'.
Re: Encryption Question
by broquaint (Abbot) on Nov 02, 2001 at 00:05 UTC
    Well if you want the crypted string to be the same length as the input string then I'd recommend Crypt::RC4. It encrypts and decrypts with the same function (I forget the technical term for it ...) so is nice and easy to use. However you'll probably want to make the encrypted string web friendly e.g
    use Crypt::RC4; sub nice_encrypt { my($val, $key) = @_; return join '', map { sprintf('%02x', ord()) } split //, RC4($key, $val); } sub nice_decrypt { my($val, $key) = @_; return RC4($key, join '', map { chr(hex($_)) } $val =~ /../g); } my $encstr = nice_encrypt("foobar", 123); my $decstr = nice_decrypt($encstr, 123); print "$encstr\n$decstr\n"; __END__ output - 359fd0e08406 foobar
    The above code doubles the size of the crypted string, but I'm sure you get the gist of it.
    HTH

    broquaint

      It encrypts and decrypts with the same function (I forget the technical term for it ...)

      Symmetrical cipher. Also (though this doesn't matter in this particular case), RC4 is a stream cipher, which means it encrypts a character at a time. This is as opposed to a block cipher, which encrypts a small block of characters (usually 8 characters, in my experience) at once.
      ___________________
      Kurt
Re: Encryption Question
by blackmateria (Chaplain) on Nov 02, 2001 at 00:27 UTC
    IMO, if you're just sending links to current subscribers you don't need to actually encrypt the link, you just need to add a MAC. The problem with sending plain subscriber ID's in links is that anyone with a subscriber ID, who gets a link from you, can trivially figure out anyone else's link (and maybe forge renewals in their name, etc., depending on the rest of your site design). So just use Digest::MD5 to compute the hash of the subscription ID and a secret (e.g. "open sesame"):
    use Digest::MD5 ; my $id = '213455' ; # WARNING: this is the third password any cracker would guess, don't r +eally use it. my $secret = 'open sesame' ; my $mac = Digest::MD5::md5_hex ("${id}${secret}") ;

    Then just tack the MAC onto the end of the subscription ID: my $url = "http://www.mysite.com/renew.cgi?id=${id}${mac}" ;

    Actually, you could even add the MAC as another CGI parameter, it wouldn't make any difference. The link is shorter this way though (my example gives a URL of http://www.mysite.com/renew.cgi?id=213455da74bbd77b3890eadce45ef45add94c8 -- I don't know if that's short enough or not. If you need it to be shorter, you could use md5_base64 instead of md5_hex, but be careful because standard base64 includes some characters (like "+") that aren't compatible with URL's.) Then just check the MAC when the client surfs in. Presto, nobody can fake a link anymore unless they can read the victim's email. Of course, this is all totally off-base if you're posting these links on a public web page or something. The basic principle would remain the same even in that case: never trust data coming from the client. HTH!

    Disclaimer: IANACE (I am not a crypto expert)

    Update: Well, I was surprised to learn that "${id}${secret}" does not mean the same thing as "$id$secret," although both would work correctly in my example above. Apparently the ${} form is actually a symref, which should not be used unless you already know why they are bad. :) I had no idea there was a difference between the two forms (actually it was a complete accident that I used the ${} form in my example, normally I stay away from it.) Thanks to crazyinsomniac for picking this one up.

Re: Encryption Question
by JungleBoy (Scribe) on Nov 02, 2001 at 00:19 UTC
    For a simple 6 digit number such as this, perhaps you should consider doing a simple XOR encryption. It's quick, easy to implement, and won't stretch out the string.

    I can see two approaches to implementing this. One, create a universal 6 digit key, that all users would be encrypted against. Two, create a key for each user.

    Obviously the first method is easier to manage, but is also 'less secure'. If a user knows what their ID is, they can easily figure out the key, and from that can get anyone else's user ID. Of course this requires the user knowing that the encryption is XOR and that all IDs are encrpyted with the same key. So the big question becomes, how secure do you need this? Is it likely that a valid user will try to figure out someone's ID? How valuable is the information that is encrypted?

    Happy Hacking!

    Rob.

Re: Encryption Question
by Purdy (Hermit) on Nov 02, 2001 at 00:42 UTC
    Wow, these are all really GREAT answers! Thank you!! I LOVE learning this kind of stuff and it's overwhelming sometimes seeing all the different stuff that's out there to learn (like the MD5_hex & MD5_base64, etc).

    That said, I went with the Crypt::RC4 solution. Our magazine is free to US subscribers (it's a trade magazine for restaurant folks, so you guys wouldn't be interested, I bet ;)), so there's no credit card #'s and the folks that do use this online that receive the e-mail (or actually have e-mail to begin with!) won't monkey around with the URL to figure out others (especially when they see that awesome encryption of their userid: 62c88fb1d64d).

    Thanks again for all your responses!

    Jason

      Incidentally, the second edition of O'Reilly's CGI Programming book explains these issues very nicely. You can even read that chapter on-line here.
        Thanks! I'll check that out. I just bought the mod_perl book from O'Reilly and I'm looking forward to writing my first project in that! :)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://122640]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (3)
As of 2024-04-19 19:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found