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;