basically our site are using Perl, so we want to write the applications
system in Perl.
then the big problem is BasicSecurityToken which leads to a problem of
Crypto.php
our BasicBlobCrypter.pm is attached.

it's not the same as the one in PHP. and it doesn't work at all.
the shindig reports error like:
[Sun Aug 23 23:25:35 2009] [error] [client 222.216.168.150] PHP Fatal
error:  Uncaught exception 'GadgetException' with message
'INVALID_GADGET_TOKEN' in
/var/www/html/shindig/src/common/sample/BasicSecurityTokenDecoder.php:

so my problem is that anyone can give me any idea to write correct code in
Perl? I can't find something the same like 'mcrypt_create_iv',
'mcrypt_generic_init' in Perl.

any hint is really appreciated.

Thanks.

-- 
Fayland Lam // http://www.fayland.org/
Foorum based on Catalyst // http://www.foorumbbs.com/
package OpenSocialX::BasicBlobCrypter;

use Moose;
use URI::Escape;
use MIME::Base64;
use Crypt::CBC;
use Digest::SHA;

# Labels for key derivation
my $CIPHER_KEY_LABEL = 0;
my $HMAC_KEY_LABEL = 1;

# Key used for time stamp (in seconds) of data
my $TIMESTAMP_KEY = 't';

# minimum length of master key
my $MASTER_KEY_MIN_LEN = 16;

# allow three minutes for clock skew
my $CLOCK_SKEW_ALLOWANCE = 180;

my $UTF8 = "UTF-8";

has 'cipherKey' => ( isa => 'Str', is => 'rw' );
has 'hmacKey' => ( isa => 'Str', is => 'rw' );

sub wrap {
    my ( $self, $in ) = @_;

    my $encoded = _serializeAndTimestamp($in);
    my $cipher = Crypt::CBC->new(
        -key    => $self->cipherKey,
        -cipher => "Crypt::Rijndael",
        -keysize => 128/8,
    );
    my $cipherText = $cipher->encrypt($encoded);
    my $hmac = Digest::SHA::hmac_sha1($self->hmacKey, $cipherText);
    my $b64 = encode_base64($cipherText . $hmac);
    return $b64;
}

sub _serializeAndTimestamp {
    my ( $in ) = @_;
    
    my $encoded;
    foreach my $key (keys %$in) {
        $encoded .= uri_escape($key) . "=" . uri_escape($in->{$key}) . "&";
    }
    $encoded .= $TIMESTAMP_KEY . "=" . time();
    return $encoded;
}

sub unwrap {
    my ( $self, $in, $max_age ) = @_;

    my $bin = decode_base64($in);
    my $cipherText = substr($bin, 0, length($bin) - 20);
    my $hmac = substr($bin, length($cipherText));
    
    # verify
    my $v_hmac = Digest::SHA::hmac_sha1($self->hmacKey, $cipherText);
    if ( $v_hmac ne $hmac ) {
        die 'HMAC verification failure';
    }
    my $cipher = Crypt::CBC->new(
        -key    => $self->cipherKey,
        -cipher => "Crypt::Rijndael",
        -keysize => 128/8,
    );
    my $plain = $cipher->decrypt($cipherText);
    my $out = $self->deserialize($plain);
    
    $self->checkTimestamp($out, $max_age);
    
    return $out;
}

sub deserialize {
    my ( $self, $plain ) = @_;

    my $h;
    my @items = split(/[\&\=]/, $plain);
    my $i;
    for ($i = 0; $i < scalar(@items);) {
      my $key = uri_unescape($items[$i ++]);
      my $value = uri_unescape($items[$i ++]);
      $h->{$key} = $value;
    }
    return $h;
}

sub checkTimestamp {
    my ( $self, $out, $max_age ) = @_;

    my $minTime = $out->{$TIMESTAMP_KEY} - $CLOCK_SKEW_ALLOWANCE;
    my $maxTime = $out->{$TIMESTAMP_KEY} + $max_age + $CLOCK_SKEW_ALLOWANCE;
    my $now = time();
    if (! ($minTime < $now && $now < $maxTime)) {
      die "Security token expired";
    }
}

1;

Reply via email to