Search code examples
perlhashencryption-symmetric

Safe non-tamperable URL component in Perl using symmetric encryption?


OK, I'm probably just having a bad Monday, but I have the following need and I'm seeing lots of partial solutions but I'm sure I'm not the first person to need this, so I'm wondering if I'm missing the obvious.

$client has 50 to 500 bytes worth of binary data that must be inserted into the middle of a URL and roundtrip to their customer's browser. Since it's part of the URL, we're up against the 1K "theoretical" limit of a GET URL. Also, $client doesn't want their customer decoding the data, or tampering with it without detection. $client would also prefer not to store anything server-side, so this must be completely standalone. Must be Perl code, and fast, in both encoding and decoding.

I think the last step can be base64. But what are the steps for encryption and hashing that make the most sense?


Solution

  • I have some code in a Cat App that uses Crypt::Util to encode/decode a user's email address for an email verification link.

    I set up a Crypt::Util model using Catalyst::Model::Adaptor with a secret key. Then in my Controller I have the following logic on the sending side:

    my $cu = $c->model('CryptUtil');
    my $token = $cu->encode_string_uri_base64( $cu->encode_string( $user->email ) );
    my $url = $c->uri_for( $self->action_for('verify'), $token );
    

    I send this link to the $user->email and when it is clicked on I use the following.

    my $cu = $c->model('CryptUtil');
    if ( my $id = $cu->decode_string( $cu->decode_string_uri_base64($token) ) ) {
        # handle valid link
    } else { 
        # invalid link
    }
    

    This is basically what edanite just suggested in another answer. You'll just need to make sure whatever data you use to form the token with that the final $url doesn't exceed your arbitrary limit.