I am creating a website which will cater for several clients, each of whom will have several users.

To keep life simple I will create a database for each client and all the relevant stuff will go in there. There will also be a master database that stores only the information that is needed to get the user to the right database at login.

The users will be given sessions (stored in cookies) which say not only who they are but also which database they should connect to. Once the database has been determined the session_id and session_secret will be used to check that the user is allowed.

The attached code is my attempt to prevent tampering of that cookie. It is cut back so that only the relevant bits are presented. I am fairly sure that it is secure but I cannot be sure.

Please could you look at this code and see if there are any holes. Thank you.

#!/usr/bin/perl use strict; use warnings; use String::CRC::Cksum qw(cksum); use Crypt::CBC; # Utility function. sub display { my ( $first, $second ) = @_; print ' 'x( 16 - length $first ), "$first: '$second'\n"; } my $database_id = 1234; my $session_id = 5678; my $session_secret = join '', 'a'..'z'; # Create the input. my $in = join ':', $database_id, $session_id, $session_secret; display "Input", $in; my $cipher_text = my_encrypt( $in ); display "Encrypted token", $cipher_text; # $cipher_text =~ s/a/b/g; # <= uncomment to muck up the encryption. # display "Altered token", $cipher_text; my $out = my_decrypt( $cipher_text ); display "Output", $out; display 'Result', $in eq $out ? "Good" : "Bad"; ############################################## sub my_encrypt { my $input = shift || die; # Calculate the checksum and then prepend it to the token. my $cksum = cksum( $input ); my $token = join ':', $cksum, $input; display "Token", $token; # Encrypt the token to hex. my $cipher = get_cipher(); my $hex_token = $cipher->encrypt_hex( $token ); return $hex_token; } sub my_decrypt { my $input = shift || die; my $cipher = get_cipher(); my $cksum_token = $cipher->decrypt_hex( $input ); display "Decrypted token", $cksum_token; unless ( $cksum_token ) { warn "Error decrypting"; return 0; } # Extract the checksum and then check it. my ( $cksum, $token ) = split /:/, $cksum_token, 2; # If the checksum is correct. return $token if defined $cksum && $token && $cksum =~ m/^\d+$/ && cksum( $token ) == $cksum; # If it is not correct then complain. warn "Checksum is wrong."; return 0; } sub get_cipher { my $system_secret = 'top secret'; return Crypt::CBC->new ( {'key' => $system_secret, 'cipher' => 'Blowfish' } ) || die; }
I know that there are modules such as Apache::Cookie::Encrypted but I want to be able to put the encrypted token elsewhere and so want a more flexible home grown solution.

--tidiness is the memory loss of environmental mnemonics


In reply to Is this a secure way to prevent cookie tampering by EvdB

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.