Authen-NZRealMe
view release on metacpan or search on metacpan
is true. In the new platform, iCMS is not used.
- iCMS functionality is deprecated, it will be removed in the next release.
It will be decommissioned by RealMe after 18th March 2021.
- Parameter acs_index set to 'default' will use the ACS with isDefault="true"
1.20 2020-02-25 13:07:33+13:00 Pacific/Auckland
- implement HTTP-POST binding through new resolve_posted_assertion()
method in ServiceProvider.pm
- as RealMe's HTTP-POST assertions are all encrypted, support has been
added for XML encryption; and the new 'CryptX' dependency is added for
the required AES128-CBC cipher
- revised SP metadata generation and editing to support multiple ACS
entries with support for HTTP-POST vs HTTP-Artifact bindings
- allow initial request to specify the index of the ACS to which the
response should be sent
- removed support for "force_auth" parameter to new_request
- fix missing namespace when generating SP metadata file
- add some asserts to sanity check user input
1.19 2019-02-20 19:11:05+13:00 Pacific/Auckland
- further improvements around the use of find_verified_element()
lib/Authen/NZRealMe/CommonURIs.pm view on Meta::CPAN
URI indicating that the encrypted data represents an element. Source: [XENC].
=item xenc_rsa15 => http://www.w3.org/2001/04/xmlenc#rsa-1_5
URI for XML Encryption block encryption algorithm "RSAES-PKCS1-v1_5". Source:
[XENC].
=item xenc_aes128cbc => http://www.w3.org/2001/04/xmlenc#aes128-cbc
URI for XML Encryption block encryption algorithm "AES128-CBC". Source: [XENC].
=item xenc_aes256cbc => http://www.w3.org/2001/04/xmlenc#aes256-cbc
URI for XML Encryption block encryption algorithm "AES256-CBC". Source: [XENC].
=item xenc_rsa_oaep_mgf1p => http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p
URI for XML Encryption key transport encryption algorithm "RSA OAEP MGF1P".
Source: [XENC].
=item rsa_1_5 => http://www.w3.org/2001/04/xmlenc#rsa-1_5
URI for XML Encryption key transport encryption algorithm "RSA Version 1.5".
Source: [XENC].
lib/Authen/NZRealMe/XMLEnc.pm view on Meta::CPAN
use Carp qw(croak);
use MIME::Base64 qw(encode_base64 decode_base64);
use Authen::NZRealMe::CommonURIs qw(URI NS_PAIR);
require XML::LibXML;
require XML::LibXML::XPathContext;
require Crypt::OpenSSL::RSA;
require Crypt::OpenSSL::X509;
require Crypt::Mode::CBC;
require Crypt::Cipher::AES;
use Crypt::PRNG qw(random_bytes);
my $ns_xenc = [ NS_PAIR('xenc') ];
my $ns_ds = [ NS_PAIR('ds') ];
my(%enc_alg_by_name, %enc_alg_by_uri);
__PACKAGE__->register_encryption_algorithm($_, URI($_)) foreach (qw(
lib/Authen/NZRealMe/XMLEnc.pm view on Meta::CPAN
sub _decrypt_aes128cbc {
my($self, $aes128_key, $ciphertext) = @_;
my $cipher = 'AES';
my $padding = 0; # no padding - we handle that below
my $blocksize = Crypt::Cipher::blocksize($cipher);
my $iv = substr($ciphertext, 0, $blocksize, '');
my $cbc = Crypt::Mode::CBC->new($cipher, $padding);
my $plaintext = $cbc->decrypt($ciphertext, $aes128_key, $iv);
return $self->_strip_padding($plaintext, $blocksize);
}
sub _encrypt_aes128cbc {
my($self, $key_info, $plaintext) = @_;
my $cipher = 'AES';
my $padding = 0; # no padding - we handle that below
my $blocksize = Crypt::Cipher::blocksize($cipher);
my $aes128_key = $key_info->{key} or die "No key in key_info";
my $iv = $key_info->{iv} or die "No iv in key_info";
$plaintext = $self->_add_padding($plaintext, $blocksize);
my $cbc = Crypt::Mode::CBC->new($cipher, $padding);
my $ciphertext = $cbc->encrypt($plaintext, $aes128_key, $iv);
return $ciphertext;
}
sub _key_gen_aes128cbc {
my($self) = @_;
my $aes128_key = random_bytes(Crypt::Cipher::keysize('AES'));
my $iv = random_bytes(Crypt::Cipher::blocksize('AES'));
lib/Authen/NZRealMe/XMLEnc.pm view on Meta::CPAN
}
sub _decrypt_aes256cbc {
my($self, $aes256_key, $ciphertext) = @_;
my $cipher = 'AES';
my $padding = 0; # no padding - we handle that below
my $blocksize = Crypt::Cipher::blocksize($cipher);
my $iv = substr($ciphertext, 0, $blocksize, '');
my $cbc = Crypt::Mode::CBC->new($cipher, $padding);
my $plaintext = $cbc->decrypt($ciphertext, $aes256_key, $iv);
return $self->_strip_padding($plaintext, $blocksize);
}
sub _encrypt_aes256cbc {
my($self, $key_info, $plaintext) = @_;
my $cipher = 'AES';
my $padding = 0; # no padding - we handle that below
my $blocksize = Crypt::Cipher::blocksize($cipher);
my $aes256_key = $key_info->{key} or die "No key in key_info";
my $iv = $key_info->{iv} or die "No iv in key_info";
$plaintext = $self->_add_padding($plaintext, $blocksize);
my $cbc = Crypt::Mode::CBC->new($cipher, $padding);
my $ciphertext = $cbc->encrypt($plaintext, $aes256_key, $iv);
return $ciphertext;
}
sub _key_gen_aes256cbc {
my($self) = @_;
my $aes256_key = random_bytes(Crypt::Cipher::keysize('AES'));
my $iv = random_bytes(Crypt::Cipher::blocksize('AES'));
lib/Authen/NZRealMe/XMLEnc.pm view on Meta::CPAN
using the C<pub_key_text> method.
=head1 SUPPORTED ALGORITHMS
=head2 rsa15 - RSAES-PKCS1-v1_5
Used only to encrypt/decrypt the random key which in turn is used by the block
cipher to encrypt the XML element data. This is used by the old RealMe service to
encrypt the random key.
=head2 aes128cbc - AES128-CBC
This is the oold supported block cipher used for the encryption/decryption of
XML elements. Whilst it is recognised that use of this cipher is not
recommended due to concerns about its security, it is the cipher used by the
RealMe service to encrypt SAML assertions.
=head2 rsa_oaep_mgf1p - RSA-OAEP-MGF1P
Used only to encrypt/decrypt the random key which in turn is used by the block
cipher to encrypt the XML element data. This is used by the new RealMe service to
encrypt the random key.
=head2 aes256cbc - AES256-CBC
This is the supported block cipher used for the encryption/decryption
of XML elements. This is the cipher used by the new RealMe service to
encrypt SAML assertions.
=head1 SEE ALSO
See L<Authen::NZRealMe> for documentation index.
t/test-data/login-assertion-post-1.b64 view on Meta::CPAN
bGRoeGFkcXJyVVE1dXI1CiAgICBJNXZLeVdPUWxwM0g4R2NqVDhIdlRhM1lNc3luTEtPWFJoaVdM
RzFDUEdoL2J3c1k5N0MxWEtDY25YcXdNemd1S2gzWTdmcEZVVmw1CiAgICBjREQvaUNzOU5FV0dJ
V3REbU9sZkhPemtjQnA1MHhUUW1zeW5RcjRuN0tOOUN0dzM1WW1vY1gwejhoZ2t2cW1nV2s5QnNz
OHoxWVQ5CiAgICBXZCtvTmh2UWVZSnM4QVJuNFBSb3ZZazBkZndZTTl4NW9vVVJPRkJqSkxvOHQ5
bFBQNit4bWMwRU14aE1WRC9LZjlFTUpNWkg4a2tWCiAgICBOTU9WeUFsT1VWN2ZEektRdEpEcDY4
WFlKR2FJRXNlbTVlMkNtc3Q0aFkwQW5OVThKMDdPKytsOGpKeXYrblIxY1hpbGMxZS9VcXZVCiAg
ICAvL3MzWnd3QlRqaURoWkNXdnJiczdLTC9KU1hoTGY2dGpuL0Rrd1MxM1B1UHpOSEN1U1FlVEtF
c2VsVGtrbUN1dE9VZnFOTTdMNUxZCiAgICBidkVyOW52UnB5WVNxNHpQYjFjeEU1eTRiUmh0UW42
K1dHOGFER1NHL1pPWkZQcEdSRzdFaVYvK1Erbk1zSUFseGs4QWVoaVhMTzYzCiAgICBjQWtlT1dS
dHJ2dkVJdk1XUkxXL2RianA3Y3ViTFVwdHlMQkVNenllLzNCWFVJNUoxY3VPMVZrNE9kQk93QzNC
WlJGQlFVaWZlL2IrCiAgICBCd1d3cFpuaktXbGpxTnM1RTdsZGVmNzU5Y1BvaHM3ZEpRY0VWcU9S
blRadjRYOFNxbE5EZzYyeWd0NzRUdVE1bEF1UnVjZ3lFYktsCiAgICBFWkhyWVY3VG9HSE5QMHRC
NlFEd2grRitPbk55N3hBRjJ2OW9Wc2hiN3RhdnFOV0NyNHgrTklWYU1CMlJIZU01UXRhREE2QVZm
YTloCiAgICBBTUxtMWJySDBNTVZHemgxcUJuNzBiNUFUckY5Q0JBSlR2UW9HNXptekhXUTNlOGsx
NVV5MVZNTTRQcGRjRVBMVmJWbDBDM1lQaGVkCiAgICA1RjVZdzNZalptUDl4UksweHhhcGtBcFBV
M2pSZ1FkZFlacDZ1eVZzVU1sVVRIN3R4dHdzdkZ5OGpOV0VoMFJuUGY1ZkdXdE9kWHhrCiAgICBB
SFNpK21Eb2JLM1JWcUplS0lzOXRldHdOaWtIYUV5TkxIck8vZk9YNE1BaktCYXYwc2Fsb1pyRDFx
T1BadE9NS1h1b0FTM05Rd0xwCiAgICAvVTV5c0lhSENBTm5uUlVmZFc3K29ZdlN5aGVwNklGeFBs
UFprdWUrd1dqZXY0SnZkMG9jUHMvaHVOc0RLRDI1MzhHM3dCTkpFdWdlCiAgICBaQlYzbktnSE5q
clZjbzA4WlJDb25yQ3B1VWYzYTlTTlRvR0dXUFZJZVJ6YXdQQVJNZDJMSGRiWm5lYnMxM3p2RWp5
eWJOUHpmR0VQCiAgICBWYVAvSHMxWW0xNEcyUDFPSi93cysyNXJCbmVBelRpM1hQN1d5ZXl2aG9Z
t/test-data/login-assertion-post-1.b64 view on Meta::CPAN
dVg0d01NTlNWVXRsTnc5VXVwRG5SNExNLzJBdWsvaVc0TC91CiAgICA3TXhFaW5UaXJodFowbnBU
L3RNYUphZFluN2RodEdYd3JBaHZPQktYUitTRGdOMVc0d2FpZ09YVkhDb0tuN3IvcHRBQ0lrZml0
akhyCiAgICB1TGlySTZWRjQvMjJoMFFuMFF3OGpEamRkdlB0a2JtUlBoNGpXTnZaUkZja3BsZ1lH
NTFHWmF5c1hrQWUzdXRrdERkeGJ2Nk5vV3BJCiAgICBBRVZYcDQxVUxPN0lCazNwVXRxd0ZKR3pD
Rmx0eFA2NGNGODNsS3BEektaWlRrb3R2MUVQakVpSTFVcnRJektxVGtUaEsxd3ZVMVIrCiAgICA0
b3lBTWtvMWtxcXBoVmdtR2h4RzcvYXErWGgraE14UnhpNFI3MEt5cURXMVBoQUtaYnVhRlZTSlVt
SzA4VkZFWVo3anhDeXVzandKCiAgICBkdThIUjI2S3lvcnlVNHRRalVpM0lXT2IvUWJjM3ZZVWR4
SCtScWxtN1hhaGFycU5oVUxzMXNRdEtudzdrWnlpa0MxUm5KMEx4aW04CiAgICAyaGNKbHR0OUE2
QVlhb1RpTFQrUXdndnNrcFk0azBsaEkzTXhTcm52ZTZDaXM1aFgxMEdyV09TUGtlQWxYK0k5OW54
Uyt4T3hGb2lSCiAgICA0WThFWHRLK3FyQWwwR1RxUkEzdzJZOVIvQ1E4QnNYMmVoL1dmb1AyM2V3
bTdtb0Zjb3gzejRyRFFqenhUV1dZd0UvdFB5Vmt3VFl2CiAgICBCTURIK3pmZk9IM0xjMzZJMjhW
SldVL1RLOEl1RnFKRkV3dFVKVDhBVk8yc3JZcWY0NXozanlpREpzcHFjdXUxb21uYkxQVWJKbEdh
CiAgICBxSU1GbG1pb0ZINStsREd0WEk0TFROUUd1NUNKVEhydUMyQzNYTjRvWGRWbzF2NjBuTFFq
emJaV1BSVlR6L01PQUd1WFU0RXBwT1BnCiAgICBzZG9XQWROZE9XM01BNXI4REtyNWFCVDhCUlQ4
MFhmcHRrM1FlOCt4N0JQRUZnRzFLVGNveFlLNFcwSm1EOWxnU1JDcXdZTjBLL0FVCiAgICAvYk1Q
dXMyWlVVNGZmbk41bVg0R090bk5WYW5UcC9peVh6TUlxZWc4MGhrZ2w5ZWlsYzI3QldVVml2U3VG
VW5ORVg0NC9vcFVXdnRJCiAgICBMU3NzODJ1Rm83NzFLYTlTb0VSR2lURmtzNDV3OXREcHRhMzRH
cjlpTVlmTElzRVBYaDVhS2U5UGJTeHRHNE0vcmh0RytneW5ELzV4CiAgICBidVhmQmQ0OGxaRkJ3
NkllS3FmS3V6ZHJlQ0VERXo5TUlpMGlLS1dobVNiZWFJTW9SWTVhNWlXdUtlek0vd2Jhcm83ck5L
S0FEdndGCiAgICAzb0RZNGFabHU5TnlzM1dIMjB1VW9pc1F2YjJZaHRISEhnazZqdFA3dzArbUJQ
aXYxd1JKKzZneDR2YzNSM1I0ZWdDeWNRRkRteS9lCiAgICA3VWY4alh2b0FEcDd6d25vUzNkN0lO
t/test-data/login-assertion-post-2.b64 view on Meta::CPAN
VHFxcEpYeTJidS8veHlQSVFkczNQR0IrCiAgICB2SWxqTXl5ZG9YQXZoOCt3ZkwzZXRUalUrZm9R
bnY3WjFwQlZZalA2S2NJZzVIVHFJS25jRk5vMmZERXQ4RGVxYzJ2Y3NWdHZjSnFWCiAgICA4aDFW
cFFsdEg4T0U4eitXcEdGcHBvTTlnQlBGUTBFZEhPU0JQenpOOENQZythdTd6N0NaUkk1MDljV0tZ
RGkvemVRMTZJOEY1TkIyCiAgICBEcTQyeWhCTkNUQWJHZ3poaEE4ZFV1R29hVWNLeUxGNzd2UzBD
VElndCtjYVdPUFNxMEdSZ1FlU0JEN1VvczNkS2ZlMitWa1FsZ3ppCiAgICBSOGw0TXprS2EwUkhT
ckMrdU9jcnl2Z3dRcHNlV2p0YUd2Q1lrUFU4bnZOVXZFUEZnVEdrZEZMdklMVmpjV0JOamxaRWpJ
SzFpb0E5CiAgICBxL1lIa05jc0FpdjJ6MjNnRXBlTnRubzcwT0J5R3kvU0s3bktPcDVpY3lpODgz
cHNYdmNML2tmQi8zRmk3RW5GMVVTU0dxaGc1bUtvCiAgICAwS3ZtK1BRVHZmVTF3SXM2RjJ3Zmwz
c2FVemRSOE5aM0xIN29lSW5leUNSWkhrOEdiMWF4RGdFS3dRWkJQNVp4a3hPS3Z5WVdrZjJSCiAg
ICBzR0FPQzltZU9GazNuODlWY25CbXNSN2RkUzlTNnhFNFpoU3U1cjlkSDRFTUdmTUhqS3dhbkpz
YnRFNzF4RDlNMm8wMmRucVRDQXl2CiAgICBCWHpTVHVjOGhGMGRmdHREYU1jR1FLVDZqTlRnZkk0
NzNuVnFsazhDWnA1ZHJuU09YNVpEZGZyYlhIWlpDd296MDFYK2IzN0Rha1d2CiAgICBoKzI1blpx
MVVkK004SXlPWjlwRzRPNlBRZWFGTjNDK0J5V2k4RHdSUThvV25nOXpHWEZWV2xTRUlLWkFMVk5o
a2RISkRSdVhOMlVsCiAgICBqQW5NVVd3QU1EWEM2cUVYcmNMYXp6WnIvRjZkaVlNVXZjQS9Eb21L
Y0NzTHp0NDkvckcyRHE3VzZsQ1gzYStMNGxrcUYzM2Z1bjBpCiAgICA3SWFnMm5seXZXN21lTnVm
OGRqTUk1dmhic1VCRzlTNnN6Y3dmbkxMS3BLUDZzRHZOVjY0SmhMQlJQUmhXU3ArbWNjOEdtZDJs
VEd1CiAgICBEeU55ajdabGJQc0VUWjdXSnd4ZHVuVzZMNFgyc0tydTVGSk1ON2pJV1UyL2JtcVNs
ZFFMb0ZMY1Y0WGd2NmRDWndNV1Z0MXQ3TGdYCiAgICBYSko0REVEdDlmM2xqcXFnQzlaVFFtVXFp
TmU1b1NlY3lucnR3UWxjeW5nUit1aXllelU3eVZTN0xYREh5Sk4xOUhtU0tvTmg5OSs5CiAgICBi
bm9sY3BYaVFidThzeUdWTVIzaHo1T09GWUhRWlNqSm1UckQyRG12K3U2NWVQeE9ldXMzekQweUpT
dGhabTJXdjhCVGVuZDJWdUM5CiAgICBkZWZrTnRBU2drVUluVWpzRmdoMVk2bEh5TW1CbXJ2Q1Y4
MHR3aXkyMi9ZYjh5NjNGVUxVSlFiYzNJU2hheHR3Yk1BaURvUGl4UWJHCiAgICB6b2JxQVBBbDcy
LzhLZW5zWEZNUFJXSnoyaFc1OTlYVWNTMDdEN05KTDdqNTNtSGp6U2MwZkVsdU5ZczZHaWpPNzk0
aE0zK0RDamwzCiAgICBCdjJIT05sSnhIMnBVQVRaOHpiQ3ZMbjlzeXFDZHhzUlNlbjR2ZHJHS2h1
RHhvMHJVOTk5ZTBHZTFjekFNOTJ6M1BKSWVRazlqb1dQCiAgICBqRVFKMmZzZmg0WFVVdkxIc1hP
WFFYRjVHZUpNeWVaRjNKQU1YWkZUNXI3SUxLSjhNQlhvTmZrNGt6WGgrSXk0ems0a1djTXhoNGc3
CiAgICBkZHN2bmNDZGRnWE5xWFltZENDcVV0R2Z0bEVmT2J2VWxwUjJ5VDdEamJ4VnNoZ0UyV1Fo
Qk1UdjlrQXUwWllyZ3NhU2hhNUJDbWdLCiAgICB1anpRaHI2WFVSTjEzS2NZWFM5YnFZRkxKUFFr
YVdUOTF2a2pYejlLS0Y3a2piS3RZTFA5by9teVBZK1R6MUJnVXhtbi80M2drMlplCiAgICB6ekpU
cUVzSEFOTXNKOVlqVUtKeEFnOE0KICAgIDwveGVuYzpDaXBoZXJWYWx1ZT4KICA8L3hlbmM6Q2lw
aGVyRGF0YT4KPC94ZW5jOkVuY3J5cHRlZERhdGE+PC9zYW1sOkVuY3J5cHRlZEFzc2VydGlvbj4K
PC9zYW1scDpSZXNwb25zZT4K
t/test-data/login-assertion-post-3.b64 view on Meta::CPAN
WmQ4dlAzYldRSGFpQkNMTk5hCiAgICBkS3g1T2czaUtlaE40UGFjUllQOEhYWFRFSEp2KzRXWmNM
NjdZNWFNVlBXUzhERFEvY0licndxN1pzTHBCam9nQzg2dkU4QzNMNGhrCiAgICArczlaRGNoa0NN
dmlaSnlzNnVVeFdzSEpxQTBXSEhBRGxoL3o3WHlVQ01PYk1QWlRvSTNHMlBVVE0yaVZDeGNIcjc1
cm5hSHZSSkZnCiAgICA1QjRYKzVSTzI5MTFzWXVmTW9YZExVdlFMRks4Um5CcTFJY2QzU3NLL1ho
THp5YnpjY0tUU3F6Ly9tY1NSQWx2S010b24wYjNrMFBQCiAgICAwL21zVDFKaEcwRjFCeWRXM3lo
Z21XeThPUlNURGhIYWczNC9ITFhxaFdVTk8yWW54S1dEWFZKellzN2x1ZHA2dlgvNTl5Q0hKeUE2
CiAgICA1K1lWRS9McUh1NzJZQXFlQmVLZlZITDJQQzNrbFd1bis2RkFsN0JRMEFZQlV2dEhWS0Fq
cHZPcWdnRWwvb1JJMTFBbCtqSTdqQk8zCiAgICBZb2NkeGw1TUlCRWJseHdDMnZPSEdHZlI2a1hK
YlR1a1lvMnQ1MU5iellzcmt4R3J6V0tneHVuckFFbzZxUVZhcVlaeFlDRWd1UkVvCiAgICB1VkhX
T1NKMGg0bUVXU2RSa2hjZmZJK1J6QmRoaTcwdzFuaEkvVnRvSnF2OFVuSmw0d0grN1dicG9RUnRW
SjZRTG1UYTlwUGJueVpOCiAgICBCaWhXalZOR2JTR3FvZUlTMkQzNDRsUVYrbXdGUm5DTERWVnRN
aTRqNW9Udm5jam5kWVVXaXgwTm1qbGJRWnVYTFZPck1RMk5jVWtaCiAgICB1dS9RazdZc0VnU0NX
bXp5QXdQMXdiSjhyTWVMdEg2VzFqVmh4c2V6MHFiQUdrTHBCRlYrNGtGczc0cTZ5djhzU2EzZUEw
NWJjZlZnCiAgICBHbFVZUTZsbU1TUkh6MDRsbE1pOVBOZUllb1hsSGdpSGQxem1qcVNPNC9PODlk
UkR6MkliMkpIbk1WbEFBQ1VPdHdEUGo5MWY2cFJRCiAgICBWTGR5WEowRW9TN1ptVy9HWU05eHpn
ME01d3hJQmNIdXdHOWpUVWZlYVJzUzVVUE9ReDB1R3BQWWVHU3RFRTJFV2FoL0wzWE1NUUZJCiAg
ICBoMHlyK094Z1QvdVUyeUVzQUhYcnNMNGZEdjFLNFlPWWlFZ2FlMm9oY2J1WnN1QzI5bllGWXR5
UmYwcGpaYU9aTVZDRTBoWk9UZXF3CiAgICAzVEFlaU1vcFdoQ1E0TlVxNmlablZoWVAwR0pTY21O
WkVKNjg2emd4ZUh5VzY3TlRTM0JBNG9oaUk4TlBMOC8vbnRMY3ozT255d1prCiAgICBJK0k2Y1JE
STB4YVBid0FXdlZiT1R1b0ZYWkxnZXN3NTJwenlSUHpXZnRaY0NrSEgyNTlRbjQ1Uk1UUjFDUlpa
SkdZS3FibnpCVVIxCiAgICBuVHkyZkozdVpmSXlnQmswQ0xGVm0zRjlmSWFlVHplZzcxUXdCOVdB
ekRWaHZ0Y21vNGNQeUFsRkdpOStFaHEyczFyYzZHbFpDd3FICiAgICA2NnVhMUVOS3ZuZUIxRUVh
cFp3cmtsdkhjdng1TDUwM0pDUVQxcExpTjg3VW0xdEF6QVVlbVFrbVoyY3RzRnFrV1QxcDhPNk1Z
L1cyCiAgICBnaFVyellnYjZiQjFPSU9jOEttcHBtcURaUFkrTHpTUTVDQ0ZBWjBFSDZkNytDTmxK
MU1CalFZRmtiSGxqZ3BQalp4amtKeHc3SFdxCiAgICB1QWxZZDdKSkJ4Y0hROU81VnNXR0Vrd3ph
RXJYc0JpWUZyWFh2NVZBK2VzWnJ3YlN4OEgvVzAzdzJFQXhiNVcvYWFJbTNiYmpTOUdrCiAgICBU
OVY5OHE3aWhRbFlOcUxVRGlCSkRzdWtWd21hTEU0RExlWlp6bFloZTRIbCtmRzUzem1kdUtjZ2Rz
NUxGMXBpNkZMbmpKZmNJYVpUCiAgICBVMkF4aEZZRXBhTjI3YzFDUnBkV0pqQXM2Z2Fvd2RvMi9T
QkYvMXFIQmcxejF4SlJFcGZINVNMNWdWSEs2T0RmZy9kTWJQOU14YlN3CiAgICBCcDhIMTFlSjBV
bGF5LytBVDZBNW5hdnFqVVFFQUlEWlNjRFVUcUY2enR0SVBjOEV1c3g1WGJrVkFxOWVLak5mSjNk
NG9UZXJsTWxCCiAgICBha2VmeEhydk5DZFJrMmRVSjRSZTZuQ2xrUVRydEVEdEJJMkxNSnUwZHFh
TytKcFlEWk05bzNkNnpVR3o0MWxLN2JSdHdTQjUrYW1XCiAgICBkV0xOUHI4Z3NSV2RUZVl5NnZC
bHUxTVZ1SFZUSUJCeEFLTS9GeXpmRnV0SUZzWFllR1dkaDJGcVpLcjhYL0VnOXA5NzNqM3lmQTlJ
CiAgICA4dWFPSU1IWWVFNW8wS1pIdUs1TXhXR2h1RElPbTBTcmhNbm9nQ2ZRcmVJUEV5Kyt5ZFZu
dDNiTFBuRVRWRTdaTFpZam5nbC9vQlVxCiAgICBmalIyUkFvT0tLVGF0NDl5N1NnV1A0a3JRT3Bj
U1RxbzhxVThYK3BHVStXeUdpQkZnb1AwOUZlTEJaUC9GYkgxNWFQLzNjbTYwYnRLCiAgICA5YTB5
RTcva2NMNG9EVEh5Q2FWK216dDVDVVVWNGZpTjg2UXVmZi9mVndUVjNBdmtRL05UQlZueVh4bGw4
MmZ1SlR2dm91cU1sd3JECiAgICAwYWFZd0hGaUY0eUo3T045QVVjbU1lNEhna01uLzVuZm9CRXJW
N1dsTE41cEIvRG0wdmVOeTR2d291SFNIdmxtbnhLdEJ3eUtub29JCiAgICB6T2FEMTdUQnZ6WUli
( run in 1.649 second using v1.01-cache-2.11-cpan-df04353d9ac )