Imported Upstream version 0.018
This commit is contained in:
commit
fd8ac42b2a
54
Changes
Normal file
54
Changes
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
Changes for Crypt-JWT distribution
|
||||||
|
|
||||||
|
0.018 2016/08/31
|
||||||
|
- doc fixes
|
||||||
|
- file perms fixes
|
||||||
|
|
||||||
|
0.017 2016/06/03
|
||||||
|
- doc fixes
|
||||||
|
|
||||||
|
0.016 2016/05/12
|
||||||
|
- require CryptX-0.034 (jws_no_key.t fails with older versions)
|
||||||
|
|
||||||
|
0.015 2016/05/12
|
||||||
|
- fix broken test jws_no_key.t
|
||||||
|
|
||||||
|
0.014 2016/05/04
|
||||||
|
- using Base64 en/decoding routines from CryptX also in tests
|
||||||
|
|
||||||
|
0.013 2016/05/03
|
||||||
|
- fix misused utf8:stuff
|
||||||
|
- fix 5.8.* compatibility
|
||||||
|
- using Base64 en/decoding routines from CryptX
|
||||||
|
|
||||||
|
0.012 2016/05/02
|
||||||
|
- JWS is now able to use the key from jwk header
|
||||||
|
- added support for Flattened JSON serialization (for both JWS and JWE)
|
||||||
|
|
||||||
|
0.011 2015/10/22
|
||||||
|
- switch to JSON::MaybeXS https://github.com/DCIT/perl-Crypt-JWT/pull/1
|
||||||
|
|
||||||
|
0.010 2015/07/07
|
||||||
|
- INCOMPATIBLE CHANGE: 'key' param of decode_jwt and encode_jwt:
|
||||||
|
PEM/DER/JWK-JSON key strings are not passed as scalars but
|
||||||
|
as a reference to scalar (see examples in documentation)
|
||||||
|
- decode_jwt: kid_keys now strictly checks kty (key type)
|
||||||
|
|
||||||
|
0.009 2015/07/04
|
||||||
|
- decode_jwt: verify_iat default changed to 0
|
||||||
|
- encode_jwt: auto_typ removed
|
||||||
|
- improved tests
|
||||||
|
|
||||||
|
0.008 2015/07/04
|
||||||
|
- decode_jwt: new parameter - ignore_claims
|
||||||
|
- fix related to nbf, iat, exp checks
|
||||||
|
|
||||||
|
0.007 2015/07/04
|
||||||
|
- decode_jwt: new parameter - kid_keys
|
||||||
|
|
||||||
|
0.006 2015/07/03
|
||||||
|
- after many changes first candidate for stable API
|
||||||
|
- incomplete tests
|
||||||
|
|
||||||
|
0.001 2015/06/30
|
||||||
|
- initial version
|
1
LICENSE
Normal file
1
LICENSE
Normal file
@ -0,0 +1 @@
|
|||||||
|
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
|
21
MANIFEST
Normal file
21
MANIFEST
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
Changes
|
||||||
|
lib/Crypt/JWT.pm
|
||||||
|
lib/Crypt/KeyWrap.pm
|
||||||
|
LICENSE
|
||||||
|
Makefile.PL
|
||||||
|
MANIFEST This list of files
|
||||||
|
README
|
||||||
|
t/compile.t
|
||||||
|
t/flattened.t
|
||||||
|
t/jws_no_key.t
|
||||||
|
t/jwt_decode_tv.t
|
||||||
|
t/jwt_encode_decode.t
|
||||||
|
t/jwt_params.t
|
||||||
|
t/kw_aes.t
|
||||||
|
t/kw_ecdh.t
|
||||||
|
t/kw_ecdhaes.t
|
||||||
|
t/kw_gcm.t
|
||||||
|
t/kw_pbes2.t
|
||||||
|
t/kw_rsa.t
|
||||||
|
META.yml Module YAML meta-data (added by MakeMaker)
|
||||||
|
META.json Module JSON meta-data (added by MakeMaker)
|
54
META.json
Normal file
54
META.json
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
{
|
||||||
|
"abstract" : "JSON Web Token",
|
||||||
|
"author" : [
|
||||||
|
"Karel Miko"
|
||||||
|
],
|
||||||
|
"dynamic_config" : 1,
|
||||||
|
"generated_by" : "ExtUtils::MakeMaker version 7.18, CPAN::Meta::Converter version 2.150005",
|
||||||
|
"license" : [
|
||||||
|
"perl_5"
|
||||||
|
],
|
||||||
|
"meta-spec" : {
|
||||||
|
"url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
|
||||||
|
"version" : "2"
|
||||||
|
},
|
||||||
|
"name" : "Crypt-JWT",
|
||||||
|
"no_index" : {
|
||||||
|
"directory" : [
|
||||||
|
"t",
|
||||||
|
"inc"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"prereqs" : {
|
||||||
|
"build" : {
|
||||||
|
"requires" : {
|
||||||
|
"ExtUtils::MakeMaker" : "0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"configure" : {
|
||||||
|
"requires" : {
|
||||||
|
"ExtUtils::MakeMaker" : "0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"runtime" : {
|
||||||
|
"requires" : {
|
||||||
|
"Compress::Raw::Zlib" : "0",
|
||||||
|
"CryptX" : "0.034",
|
||||||
|
"Exporter" : "5.57",
|
||||||
|
"JSON::MaybeXS" : "1.003005",
|
||||||
|
"perl" : "5.006"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"release_status" : "stable",
|
||||||
|
"resources" : {
|
||||||
|
"bugtracker" : {
|
||||||
|
"web" : "https://github.com/DCIT/perl-Crypt-JWT/issues"
|
||||||
|
},
|
||||||
|
"repository" : {
|
||||||
|
"url" : "https://github.com/DCIT/perl-Crypt-JWT"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"version" : "0.018",
|
||||||
|
"x_serialization_backend" : "JSON::PP version 2.27400"
|
||||||
|
}
|
30
META.yml
Normal file
30
META.yml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
abstract: 'JSON Web Token'
|
||||||
|
author:
|
||||||
|
- 'Karel Miko'
|
||||||
|
build_requires:
|
||||||
|
ExtUtils::MakeMaker: '0'
|
||||||
|
configure_requires:
|
||||||
|
ExtUtils::MakeMaker: '0'
|
||||||
|
dynamic_config: 1
|
||||||
|
generated_by: 'ExtUtils::MakeMaker version 7.18, CPAN::Meta::Converter version 2.150005'
|
||||||
|
license: perl
|
||||||
|
meta-spec:
|
||||||
|
url: http://module-build.sourceforge.net/META-spec-v1.4.html
|
||||||
|
version: '1.4'
|
||||||
|
name: Crypt-JWT
|
||||||
|
no_index:
|
||||||
|
directory:
|
||||||
|
- t
|
||||||
|
- inc
|
||||||
|
requires:
|
||||||
|
Compress::Raw::Zlib: '0'
|
||||||
|
CryptX: '0.034'
|
||||||
|
Exporter: '5.57'
|
||||||
|
JSON::MaybeXS: '1.003005'
|
||||||
|
perl: '5.006'
|
||||||
|
resources:
|
||||||
|
bugtracker: https://github.com/DCIT/perl-Crypt-JWT/issues
|
||||||
|
repository: https://github.com/DCIT/perl-Crypt-JWT
|
||||||
|
version: '0.018'
|
||||||
|
x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
|
31
Makefile.PL
Normal file
31
Makefile.PL
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
use 5.006;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use ExtUtils::MakeMaker;
|
||||||
|
|
||||||
|
WriteMakefile(
|
||||||
|
NAME => 'Crypt::JWT',
|
||||||
|
AUTHOR => 'Karel Miko',
|
||||||
|
VERSION_FROM => 'lib/Crypt/JWT.pm',
|
||||||
|
ABSTRACT => 'JSON Web Token',
|
||||||
|
LICENSE => 'perl',
|
||||||
|
PREREQ_PM => {
|
||||||
|
'JSON::MaybeXS' => '1.003005', # we need: (en|de)code_json
|
||||||
|
'Exporter' => '5.57', # we need: use Exporter 'import';
|
||||||
|
'Compress::Raw::Zlib' => 0,
|
||||||
|
'CryptX' => '0.034',
|
||||||
|
},
|
||||||
|
MIN_PERL_VERSION => '5.006',
|
||||||
|
META_MERGE => {
|
||||||
|
resources => {
|
||||||
|
repository => 'https://github.com/DCIT/perl-Crypt-JWT',
|
||||||
|
bugtracker => 'https://github.com/DCIT/perl-Crypt-JWT/issues',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dist => {
|
||||||
|
PREOP => 'pod2text lib/Crypt/JWT.pm > README',
|
||||||
|
TAR => 'ptar',
|
||||||
|
TARFLAGS => '-c -C -f'
|
||||||
|
#TARFLAGS => '--owner=0 --group=0 -cvf',
|
||||||
|
},
|
||||||
|
);
|
543
README
Normal file
543
README
Normal file
@ -0,0 +1,543 @@
|
|||||||
|
NAME
|
||||||
|
Crypt::JWT - JSON Web Token (JWT, JWS, JWE) as defined by RFC7519,
|
||||||
|
RFC7515, RFC7516
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
# encoding
|
||||||
|
use Crypt::JWT qw(encode_jwt);
|
||||||
|
my $jws_token = encode_jwt(payload=>$data, alg=>'HS256', key=>'secret');
|
||||||
|
my $jwe_token = encode_jwt(payload=>$data, alg=>'PBES2-HS256+A128KW', enc=>'A128GCM', key=>'secret');
|
||||||
|
|
||||||
|
# decoding
|
||||||
|
use Crypt::JWT qw(decode_jwt);
|
||||||
|
my $data1 = decode_jwt(token=>$jws_token, key=>'secret');
|
||||||
|
my $data2 = decode_jwt(token=>$jwe_token, key=>'secret');
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
Implements JSON Web Token (JWT) - <https://tools.ietf.org/html/rfc7519>.
|
||||||
|
The implementation covers not only JSON Web Signature (JWS) -
|
||||||
|
<https://tools.ietf.org/html/rfc7515>, but also JSON Web Encryption
|
||||||
|
(JWE) - <https://tools.ietf.org/html/rfc7516>.
|
||||||
|
|
||||||
|
The module implements all (100%) algorithms defined in
|
||||||
|
<https://tools.ietf.org/html/rfc7518> - JSON Web Algorithms (JWA).
|
||||||
|
|
||||||
|
This module supports Compact JWS/JWE and Flattened JWS/JWE JSON
|
||||||
|
serialization, general JSON serialization is not supported yet.
|
||||||
|
|
||||||
|
EXPORT
|
||||||
|
Nothing is exported by default.
|
||||||
|
|
||||||
|
You can export selected functions:
|
||||||
|
|
||||||
|
use Crypt::JWT qw(decode_jwt encode_jwt);
|
||||||
|
|
||||||
|
Or all of them at once:
|
||||||
|
|
||||||
|
use Crypt::JWT ':all';
|
||||||
|
|
||||||
|
FUNCTIONS
|
||||||
|
decode_jwt
|
||||||
|
my $data = decode_jwt(%named_args);
|
||||||
|
|
||||||
|
Named arguments:
|
||||||
|
|
||||||
|
token
|
||||||
|
Mandatory argument, a string with either JWS or JWE JSON Web Token.
|
||||||
|
|
||||||
|
### JWS token example (3 segments)
|
||||||
|
$t = "eyJhbGciOiJIUzI1NiJ9.dGVzdA.ujBihtLSr66CEWqN74SpLUkv28lra_CeHnxLmLNp4Jo";
|
||||||
|
my $data = decode_jwt(token=>$t, key=>$k);
|
||||||
|
|
||||||
|
### JWE token example (5 segments)
|
||||||
|
$t = "eyJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiQTEyOEtXIn0.UusxEbzhGkORxTRq0xkFKhvzPrXb9smw.VGfOuq0Fxt6TsdqLZUpnxw.JajIQQ.pkKZ7MHS0XjyGmRsqgom6w";
|
||||||
|
my $data = decode_jwt(token=>$t, key=>$k);
|
||||||
|
|
||||||
|
key A key used for token decryption (JWE) or token signature validation
|
||||||
|
(JWS). If not given, and the token header contains a "jwk" header
|
||||||
|
value, that value will be used. The value depends on the "alg" token
|
||||||
|
header value.
|
||||||
|
|
||||||
|
JWS alg header key value
|
||||||
|
------------------ ----------------------------------
|
||||||
|
none no key required
|
||||||
|
HS256 string (raw octects) of any length (or perl HASH ref with JWK, kty=>'oct')
|
||||||
|
HS384 dtto
|
||||||
|
HS512 dtto
|
||||||
|
RS256 public RSA key, perl HASH ref with JWK key structure,
|
||||||
|
a reference to SCALAR string with PEM or DER or JSON/JWK data,
|
||||||
|
object: Crypt::PK::RSA, Crypt::OpenSSL::RSA, Crypt::X509 or Crypt::OpenSSL::X509
|
||||||
|
RS384 public RSA key, see RS256
|
||||||
|
RS512 public RSA key, see RS256
|
||||||
|
PS256 public RSA key, see RS256
|
||||||
|
PS384 public RSA key, see RS256
|
||||||
|
PS512 public RSA key, see RS256
|
||||||
|
ES256 public ECC key, perl HASH ref with JWK key structure,
|
||||||
|
a reference to SCALAR string with PEM or DER or JSON/JWK data,
|
||||||
|
an instance of Crypt::PK::ECC
|
||||||
|
ES384 public ECC key, see ES256
|
||||||
|
ES512 public ECC key, see ES256
|
||||||
|
|
||||||
|
JWE alg header key value
|
||||||
|
------------------ ----------------------------------
|
||||||
|
dir string (raw octects) or perl HASH ref with JWK, kty=>'oct', length depends on 'enc' algorithm
|
||||||
|
A128KW string (raw octects) 16 bytes (or perl HASH ref with JWK, kty=>'oct')
|
||||||
|
A192KW string (raw octects) 24 bytes (or perl HASH ref with JWK, kty=>'oct')
|
||||||
|
A256KW string (raw octects) 32 bytes (or perl HASH ref with JWK, kty=>'oct')
|
||||||
|
A128GCMKW string (raw octects) 16 bytes (or perl HASH ref with JWK, kty=>'oct')
|
||||||
|
A192GCMKW string (raw octects) 24 bytes (or perl HASH ref with JWK, kty=>'oct')
|
||||||
|
A256GCMKW string (raw octects) 32 bytes (or perl HASH ref with JWK, kty=>'oct')
|
||||||
|
PBES2-HS256+A128KW string (raw octects) of any length (or perl HASH ref with JWK, kty=>'oct')
|
||||||
|
PBES2-HS384+A192KW string (raw octects) of any length (or perl HASH ref with JWK, kty=>'oct')
|
||||||
|
PBES2-HS512+A256KW string (raw octects) of any length (or perl HASH ref with JWK, kty=>'oct')
|
||||||
|
RSA-OAEP private RSA key, perl HASH ref with JWK key structure,
|
||||||
|
a reference to SCALAR string with PEM or DER or JSON/JWK data,
|
||||||
|
an instance of Crypt::PK::RSA or Crypt::OpenSSL::RSA
|
||||||
|
RSA-OAEP-256 private RSA key, see RSA-OAEP
|
||||||
|
RSA1_5 private RSA key, see RSA-OAEP
|
||||||
|
ECDH-ES private ECC key, perl HASH ref with JWK key structure,
|
||||||
|
a reference to SCALAR string with PEM or DER or JSON/JWK data,
|
||||||
|
an instance of Crypt::PK::ECC
|
||||||
|
ECDH-ES+A128KW private ECC key, see ECDH-ES
|
||||||
|
ECDH-ES+A192KW private ECC key, see ECDH-ES
|
||||||
|
ECDH-ES+A256KW private ECC key, see ECDH-ES
|
||||||
|
|
||||||
|
Example with key from "jwk" token header:
|
||||||
|
|
||||||
|
my $data = decode_jwt(token=>$t);
|
||||||
|
my ($header, $data) = decode_jwt(token=>$t, decode_header=>1);
|
||||||
|
|
||||||
|
Examples with raw octet keys:
|
||||||
|
|
||||||
|
#string
|
||||||
|
my $data = decode_jwt(token=>$t, key=>'secretkey');
|
||||||
|
#binary key
|
||||||
|
my $data = decode_jwt(token=>$t, key=>pack("H*", "788A6E38F36B7596EF6A669E94"));
|
||||||
|
#perl HASH ref with JWK structure (key type 'oct')
|
||||||
|
my $data = decode_jwt(token=>$t, key=>{kty=>'oct', k=>"GawgguFyGrWKav7AX4VKUg"});
|
||||||
|
|
||||||
|
Examples with RSA keys:
|
||||||
|
|
||||||
|
my $pem_key_string = <<'EOF';
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCoVm/Sl5r+Ofky
|
||||||
|
jioRSZK26GW6WyjyfWKddsSi13/NOtCn0rRErSF/u3QrgGMpWFqKohqbi1VVC+SZ
|
||||||
|
...
|
||||||
|
8c1vm2YFafgdkSk9Qd1oU2Fv1aOQy4VovOFzJ3CcR+2r7cbRfcpLGnintHtp9yek
|
||||||
|
02p+d5g4OChfFNDhDtnIqjvY
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
EOF
|
||||||
|
|
||||||
|
my $jwk_key_json_string = '{"kty":"RSA","n":"0vx7agoebG...L6tSoc_BJECP","e":"AQAB"}';
|
||||||
|
|
||||||
|
#a reference to SCALAR string with PEM or DER or JSON/JWK data,
|
||||||
|
my $data = decode_jwt(token=>$t, key=>\$pem_key_string);
|
||||||
|
my $data = decode_jwt(token=>$t, key=>\$der_key_string);
|
||||||
|
my $data = decode_jwt(token=>$t, key=>\$jwk_key_json_string);
|
||||||
|
|
||||||
|
#instance of Crypt::PK::RSA
|
||||||
|
my $data = decode_jwt(token=>$t, key=>Crypt::PK::RSA->new('keyfile.pem'));
|
||||||
|
my $data = decode_jwt(token=>$t, key=>Crypt::PK::RSA->new(\$pem_key_string));
|
||||||
|
|
||||||
|
#instance of Crypt::OpenSSL::RSA
|
||||||
|
my $data = decode_jwt(token=>$t, key=>Crypt::OpenSSL::RSA->new_private_key($pem_key_string));
|
||||||
|
|
||||||
|
#instance of Crypt::X509 (public key only)
|
||||||
|
my $data = decode_jwt(token=>$t, key=>Crypt::X509->new(cert=>$cert));
|
||||||
|
|
||||||
|
#instance of Crypt::OpenSSL::X509 (public key only)
|
||||||
|
my $data = decode_jwt(token=>$t, key=>Crypt::OpenSSL::X509->new_from_file('cert.pem'));
|
||||||
|
my $data = decode_jwt(token=>$t, key=>Crypt::OpenSSL::X509->new_from_string($cert));
|
||||||
|
|
||||||
|
#perl HASH ref with JWK structure (key type 'RSA')
|
||||||
|
my $rsa_priv = {
|
||||||
|
kty => "RSA",
|
||||||
|
n => "0vx7agoebGcQSuuPiLJXZpt...eZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
|
||||||
|
e => "AQAB",
|
||||||
|
d => "X4cTteJY_gn4FYPsXB8rdXi...FLN5EEaG6RoVH-HLKD9Mdx5ooGURknhnrRwUkC7h5fJLMWbFAKLWY2v7B6NqSzUvx0_YSf",
|
||||||
|
p => "83i-7IvMGXoMXCskv73TKr8...Z27zvoj6pbUQyLPBQxtPnwD20-60eTmD2ujMt5PoMrm8RmNhVWtjjMmMjOpSicFHjXOuVI",
|
||||||
|
q => "3dfOR9cuYq-0S-mkFLzgItg...q3hWeMuG0ouqnb3obLyuqjVZQ1dIrdgTnCdYzBcOW5r37AFXjift_NGiovonzhKpoVVS78",
|
||||||
|
dp => "G4sPXkc6Ya9y8oJW9_ILj4...zi_H7TkS8x5SdX3oE0oiYwxIiemTAu0UOa5pgFGyJ4c8t2VF40XRugKTP8akhFo5tA77Qe",
|
||||||
|
dq => "s9lAH9fggBsoFR8Oac2R_E...T2kGOhvIllTE1efA6huUvMfBcpn8lqW6vzzYY5SSF7pMd_agI3G8IbpBUb0JiraRNUfLhc",
|
||||||
|
qi => "GyM_p6JrXySiz1toFgKbWV...4ypu9bMWx3QJBfm0FoYzUIZEVEcOqwmRN81oDAaaBk0KWGDjJHDdDmFW3AN7I-pux_mHZG",
|
||||||
|
};
|
||||||
|
my $data = decode_jwt(token=>$t, key=>$rsa_priv});
|
||||||
|
|
||||||
|
Examples with ECC keys:
|
||||||
|
|
||||||
|
my $pem_key_string = <<'EOF';
|
||||||
|
-----BEGIN EC PRIVATE KEY-----
|
||||||
|
MHcCAQEEIBG1c3z52T8XwMsahGVdOZWgKCQJfv+l7djuJjgetdbDoAoGCCqGSM49
|
||||||
|
AwEHoUQDQgAEoBUyo8CQAFPeYPvv78ylh5MwFZjTCLQeb042TjiMJxG+9DLFmRSM
|
||||||
|
lBQ9T/RsLLc+PmpB1+7yPAR+oR5gZn3kJQ==
|
||||||
|
-----END EC PRIVATE KEY-----
|
||||||
|
EOF
|
||||||
|
|
||||||
|
my $jwk_key_json_string = '{"kty":"EC","crv":"P-256","x":"MKB..7D4","y":"4Et..FyM"}';
|
||||||
|
|
||||||
|
#a reference to SCALAR string with PEM or DER or JSON/JWK data,
|
||||||
|
my $data = decode_jwt(token=>$t, key=>\$pem_key_string);
|
||||||
|
my $data = decode_jwt(token=>$t, key=>\$der_key_string);
|
||||||
|
my $data = decode_jwt(token=>$t, key=>\$jwk_key_json_string);
|
||||||
|
|
||||||
|
#instance of Crypt::PK::ECC
|
||||||
|
my $data = decode_jwt(token=>$t, key=>Crypt::PK::ECC->new('keyfile.pem'));
|
||||||
|
my $data = decode_jwt(token=>$t, key=>Crypt::PK::ECC->new(\$pem_key_string));
|
||||||
|
|
||||||
|
#perl HASH ref with JWK structure (key type 'RSA')
|
||||||
|
my $ecc_priv = {
|
||||||
|
kty => "EC",
|
||||||
|
crv => "P-256",
|
||||||
|
x => "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
|
||||||
|
y => "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
|
||||||
|
d => "870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE",
|
||||||
|
};
|
||||||
|
my $data = decode_jwt(token=>$t, key=>$ecc_priv});
|
||||||
|
|
||||||
|
keypass
|
||||||
|
When 'key' parameter is an encrypted private RSA or ECC key this
|
||||||
|
optional parameter may contain a password for private key
|
||||||
|
decryption.
|
||||||
|
|
||||||
|
kid_keys
|
||||||
|
This parametes can be either a JWK Set JSON string (see RFC7517) or
|
||||||
|
a perl HASH ref with JWK Set structure like this:
|
||||||
|
|
||||||
|
my $keylist = {
|
||||||
|
keys => [
|
||||||
|
{ kid=>"key1", kty=>"oct", k=>"GawgguFyGrWKav7AX4VKUg" },
|
||||||
|
{ kid=>"key2", kty=>"oct", k=>"ulxLGy4XqhbpkR5ObGh1gX" },
|
||||||
|
]
|
||||||
|
};
|
||||||
|
my $payload = decode_jwt(token=>$t, kid_keys=>$keylist);
|
||||||
|
|
||||||
|
When the token header contains 'kid' item the corresponding key is
|
||||||
|
looked up in "kid_keys" list and used for token decoding (you do not
|
||||||
|
need to pass the explicit key via "key" parameter).
|
||||||
|
|
||||||
|
allow_none
|
||||||
|
1 - accept JWS tokens with "none" 'alg' header value (which means
|
||||||
|
that token has no signature), BEWARE: DANGEROUS, UNSECURE!!!
|
||||||
|
|
||||||
|
0 (default) - do not allow JWS with "none" 'alg' header value
|
||||||
|
|
||||||
|
ignore_signature
|
||||||
|
1 - do not check signature on JWS tokens, BEWARE: DANGEROUS,
|
||||||
|
UNSECURE!!!
|
||||||
|
|
||||||
|
0 (default) - check signature on JWS tokens
|
||||||
|
|
||||||
|
accepted_alg
|
||||||
|
"undef" (default) means accept all 'alg' algorithms except 'none'
|
||||||
|
(for accepting 'none' use "allow_none")
|
||||||
|
|
||||||
|
"string" name of accepted 'alg' algorithm (only one)
|
||||||
|
|
||||||
|
"ARRAY ref" a list of accepted 'alg' algorithms
|
||||||
|
|
||||||
|
"Regexp" that has to match 'alg' algorithm name
|
||||||
|
|
||||||
|
my $payload = decode_jwt(token=>$t, key=>$k, accepted_alg=>'HS256');
|
||||||
|
#or
|
||||||
|
my $payload = decode_jwt(token=>$t, key=>$k, accepted_alg=>['HS256','HS384']);
|
||||||
|
#or
|
||||||
|
my $payload = decode_jwt(token=>$t, key=>$k, accepted_alg=>qr/^HS(256|384|512)$/);
|
||||||
|
|
||||||
|
accepted_enc
|
||||||
|
"undef" (default) means accept all 'enc' algorithms
|
||||||
|
|
||||||
|
"string" name of accepted 'enc' algorithm (only one)
|
||||||
|
|
||||||
|
"ARRAY ref" a list of accepted 'enc' algorithms
|
||||||
|
|
||||||
|
"Regexp" that has to match 'enc' algorithm name
|
||||||
|
|
||||||
|
my $payload = decode_jwt(token=>$t, key=>$k, accepted_enc=>'A192GCM');
|
||||||
|
#or
|
||||||
|
my $payload = decode_jwt(token=>$t, key=>$k, accepted_enc=>['A192GCM','A256GCM']);
|
||||||
|
#or
|
||||||
|
my $payload = decode_jwt(token=>$t, key=>$k, accepted_enc=>qr/^A(128|192|256)GCM$/);
|
||||||
|
|
||||||
|
decode_payload
|
||||||
|
0 - do not decode payload, return it as a raw string (octects).
|
||||||
|
|
||||||
|
1 - decode payload from JSON string, return it as perl hash ref (or
|
||||||
|
array ref) - decode_json failure means fatal error (croak).
|
||||||
|
|
||||||
|
"undef" (default) - if possible decode payload from JSON string, if
|
||||||
|
decode_json fails return payload as a raw string (octets).
|
||||||
|
|
||||||
|
decode_header
|
||||||
|
0 (default) - do not return decoded header as a return value of
|
||||||
|
decode_jwt()
|
||||||
|
|
||||||
|
1 - return decoded header as a return value of decode_jwt()
|
||||||
|
|
||||||
|
my $payload = decode_jwt(token=>$t, key=>$k);
|
||||||
|
#or
|
||||||
|
my ($header, $payload) = decode_jwt(token=>$t, key=>$k, decode_header=>1);
|
||||||
|
|
||||||
|
verify_iss
|
||||||
|
"CODE ref" - subroutine (with 'iss' claim value passed as argument)
|
||||||
|
should return "true" otherwise verification fails
|
||||||
|
|
||||||
|
"Regexp ref" - 'iss' claim value has to match given regexp otherwise
|
||||||
|
verification fails
|
||||||
|
|
||||||
|
"undef" (default) - do not verify 'iss' claim
|
||||||
|
|
||||||
|
verify_aud
|
||||||
|
"CODE ref" - subroutine (with 'aud' claim value passed as argument)
|
||||||
|
should return "true" otherwise verification fails
|
||||||
|
|
||||||
|
"Regexp ref" - 'aud' claim value has to match given regexp otherwise
|
||||||
|
verification fails
|
||||||
|
|
||||||
|
"undef" (default) - do not verify 'aud' claim
|
||||||
|
|
||||||
|
verify_sub
|
||||||
|
"CODE ref" - subroutine (with 'sub' claim value passed as argument)
|
||||||
|
should return "true" otherwise verification fails
|
||||||
|
|
||||||
|
"Regexp ref" - 'sub' claim value has to match given regexp otherwise
|
||||||
|
verification fails
|
||||||
|
|
||||||
|
"undef" (default) - do not verify 'sub' claim
|
||||||
|
|
||||||
|
verify_jti
|
||||||
|
"CODE ref" - subroutine (with 'jti' claim value passed as argument)
|
||||||
|
should return "true" otherwise verification fails
|
||||||
|
|
||||||
|
"Regexp ref" - 'jti' claim value has to match given regexp otherwise
|
||||||
|
verification fails
|
||||||
|
|
||||||
|
"undef" (default) - do not verify 'jti' claim
|
||||||
|
|
||||||
|
verify_iat
|
||||||
|
"undef" - Issued At 'iat' claim must be valid (not in the future) if
|
||||||
|
present
|
||||||
|
|
||||||
|
0 (default) - ignore 'iat' claim
|
||||||
|
|
||||||
|
1 - require valid 'iat' claim
|
||||||
|
|
||||||
|
verify_nbf
|
||||||
|
"undef" (default) - Not Before 'nbf' claim must be valid if present
|
||||||
|
|
||||||
|
0 - ignore 'nbf' claim
|
||||||
|
|
||||||
|
1 - require valid 'nbf' claim
|
||||||
|
|
||||||
|
verify_exp
|
||||||
|
"undef" (default) - Expiration Time 'exp' claim must be valid if
|
||||||
|
present
|
||||||
|
|
||||||
|
0 - ignore 'exp' claim
|
||||||
|
|
||||||
|
1 - require valid 'exp' claim
|
||||||
|
|
||||||
|
leeway
|
||||||
|
Tolerance in seconds related to "verify_exp", "verify_nbf" and
|
||||||
|
"verify_iat". Default is 0.
|
||||||
|
|
||||||
|
ignore_claims
|
||||||
|
1 - do not check claims (iat, exp, nbf, iss, aud, sub, jti), BEWARE:
|
||||||
|
DANGEROUS, UNSECURE!!!
|
||||||
|
|
||||||
|
0 (default) - check claims
|
||||||
|
|
||||||
|
encode_jwt
|
||||||
|
my $token = encode_jwt(%named_args);
|
||||||
|
|
||||||
|
Named arguments:
|
||||||
|
|
||||||
|
payload
|
||||||
|
Value of this mandatory parameter can be a string/buffer or HASH ref
|
||||||
|
or ARRAY ref
|
||||||
|
|
||||||
|
my $token = encode_jwt(payload=>"any raw data", key=>$k, alg=>'HS256');
|
||||||
|
#or
|
||||||
|
my $token = encode_jwt(payload=>{a=>1,b=>2}, key=>$k, alg=>'HS256');
|
||||||
|
#or
|
||||||
|
my $token = encode_jwt(payload=>[11,22,33,44], key=>$k, alg=>'HS256');
|
||||||
|
|
||||||
|
HASH refs and ARRAY refs payloads are serialized as JSON strings
|
||||||
|
|
||||||
|
alg The 'alg' header value is mandatory for both JWE and JWS tokens.
|
||||||
|
|
||||||
|
Supported JWE 'alg' algorithms:
|
||||||
|
|
||||||
|
dir
|
||||||
|
A128KW
|
||||||
|
A192KW
|
||||||
|
A256KW
|
||||||
|
A128GCMKW
|
||||||
|
A192GCMKW
|
||||||
|
A256GCMKW
|
||||||
|
PBES2-HS256+A128KW
|
||||||
|
PBES2-HS384+A192KW
|
||||||
|
PBES2-HS512+A256KW
|
||||||
|
RSA-OAEP
|
||||||
|
RSA-OAEP-256
|
||||||
|
RSA1_5
|
||||||
|
ECDH-ES+A128KW
|
||||||
|
ECDH-ES+A192KW
|
||||||
|
ECDH-ES+A256KW
|
||||||
|
ECDH-ES
|
||||||
|
|
||||||
|
Supported JWS algorithms:
|
||||||
|
|
||||||
|
none ... no integrity (NOTE: disabled by default)
|
||||||
|
HS256 ... HMAC+SHA256 integrity
|
||||||
|
HS384 ... HMAC+SHA384 integrity
|
||||||
|
HS512 ... HMAC+SHA512 integrity
|
||||||
|
RS256 ... RSA+PKCS1-V1_5 + SHA256 signature
|
||||||
|
RS384 ... RSA+PKCS1-V1_5 + SHA384 signature
|
||||||
|
RS512 ... RSA+PKCS1-V1_5 + SHA512 signature
|
||||||
|
PS256 ... RSA+PSS + SHA256 signature
|
||||||
|
PS384 ... RSA+PSS + SHA384 signature
|
||||||
|
PS512 ... RSA+PSS + SHA512 signature
|
||||||
|
ES256 ... ECDSA + SHA256 signature
|
||||||
|
ES384 ... ECDSA + SHA384 signature
|
||||||
|
ES512 ... ECDSA + SHA512 signature
|
||||||
|
|
||||||
|
enc The 'enc' header is mandatory for JWE tokens.
|
||||||
|
|
||||||
|
Supported 'enc' algorithms:
|
||||||
|
|
||||||
|
A128GCM
|
||||||
|
A192GCM
|
||||||
|
A256GCM
|
||||||
|
A128CBC-HS256
|
||||||
|
A192CBC-HS384
|
||||||
|
A256CBC-HS512
|
||||||
|
|
||||||
|
key A key used for token encryption (JWE) or token signing (JWS). The
|
||||||
|
value depends on "alg" token header value.
|
||||||
|
|
||||||
|
JWS alg header key value
|
||||||
|
------------------ ----------------------------------
|
||||||
|
none no key required
|
||||||
|
HS256 string (raw octects) of any length (or perl HASH ref with JWK, kty=>'oct')
|
||||||
|
HS384 dtto
|
||||||
|
HS512 dtto
|
||||||
|
RS256 private RSA key, perl HASH ref with JWK key structure,
|
||||||
|
a reference to SCALAR string with PEM or DER or JSON/JWK data,
|
||||||
|
object: Crypt::PK::RSA, Crypt::OpenSSL::RSA, Crypt::X509 or Crypt::OpenSSL::X509
|
||||||
|
RS384 private RSA key, see RS256
|
||||||
|
RS512 private RSA key, see RS256
|
||||||
|
PS256 private RSA key, see RS256
|
||||||
|
PS384 private RSA key, see RS256
|
||||||
|
PS512 private RSA key, see RS256
|
||||||
|
ES256 private ECC key, perl HASH ref with JWK key structure,
|
||||||
|
a reference to SCALAR string with PEM or DER or JSON/JWK data,
|
||||||
|
an instance of Crypt::PK::ECC
|
||||||
|
ES384 private ECC key, see ES256
|
||||||
|
ES512 private ECC key, see ES256
|
||||||
|
|
||||||
|
JWE alg header key value
|
||||||
|
------------------ ----------------------------------
|
||||||
|
dir string (raw octects) or perl HASH ref with JWK, kty=>'oct', length depends on 'enc' algorithm
|
||||||
|
A128KW string (raw octects) 16 bytes (or perl HASH ref with JWK, kty=>'oct')
|
||||||
|
A192KW string (raw octects) 24 bytes (or perl HASH ref with JWK, kty=>'oct')
|
||||||
|
A256KW string (raw octects) 32 bytes (or perl HASH ref with JWK, kty=>'oct')
|
||||||
|
A128GCMKW string (raw octects) 16 bytes (or perl HASH ref with JWK, kty=>'oct')
|
||||||
|
A192GCMKW string (raw octects) 24 bytes (or perl HASH ref with JWK, kty=>'oct')
|
||||||
|
A256GCMKW string (raw octects) 32 bytes (or perl HASH ref with JWK, kty=>'oct')
|
||||||
|
PBES2-HS256+A128KW string (raw octects) of any length (or perl HASH ref with JWK, kty=>'oct')
|
||||||
|
PBES2-HS384+A192KW string (raw octects) of any length (or perl HASH ref with JWK, kty=>'oct')
|
||||||
|
PBES2-HS512+A256KW string (raw octects) of any length (or perl HASH ref with JWK, kty=>'oct')
|
||||||
|
RSA-OAEP public RSA key, perl HASH ref with JWK key structure,
|
||||||
|
a reference to SCALAR string with PEM or DER or JSON/JWK data,
|
||||||
|
an instance of Crypt::PK::RSA or Crypt::OpenSSL::RSA
|
||||||
|
RSA-OAEP-256 public RSA key, see RSA-OAEP
|
||||||
|
RSA1_5 public RSA key, see RSA-OAEP
|
||||||
|
ECDH-ES public ECC key, perl HASH ref with JWK key structure,
|
||||||
|
a reference to SCALAR string with PEM or DER or JSON/JWK data,
|
||||||
|
an instance of Crypt::PK::ECC
|
||||||
|
ECDH-ES+A128KW public ECC key, see ECDH-ES
|
||||||
|
ECDH-ES+A192KW public ECC key, see ECDH-ES
|
||||||
|
ECDH-ES+A256KW public ECC key, see ECDH-ES
|
||||||
|
|
||||||
|
keypass
|
||||||
|
When 'key' parameter is an encrypted private RSA or ECC key this
|
||||||
|
optional parameter may contain a password for private key
|
||||||
|
decryption.
|
||||||
|
|
||||||
|
allow_none
|
||||||
|
1 - allow JWS with "none" 'alg' header value (which means that token
|
||||||
|
has no signature), BEWARE: DANGEROUS, UNSECURE!!!
|
||||||
|
|
||||||
|
0 (default) - do not allow JWS with "none" 'alg' header value
|
||||||
|
|
||||||
|
extra_headers
|
||||||
|
This optional parameter may contain a HASH ref with items that will
|
||||||
|
be added to JWT header.
|
||||||
|
|
||||||
|
If you want to use PBES2-based 'alg' like "PBES2-HS512+A256KW" you
|
||||||
|
can set PBES2 salt len (p2s) in bytes and iteration count (p2c) via
|
||||||
|
"extra_headers" like this:
|
||||||
|
|
||||||
|
my $token = encode_jwt(payload=>$p, key=>$k, alg=>'PBES2-HS512+A256KW', extra_headers=>{p2c=8000, p2s=>32});
|
||||||
|
#NOTE: handling of p2s header is a special case, in the end it is replaced with the generated salt
|
||||||
|
|
||||||
|
unprotected_headers
|
||||||
|
A hash with additional integrity unprotected headers - JWS and JWE
|
||||||
|
(not available for "compact" serialization);
|
||||||
|
|
||||||
|
shared_unprotected_headers
|
||||||
|
A hash with additional integrity unprotected headers - JWE only (not
|
||||||
|
available for "compact" serialization);
|
||||||
|
|
||||||
|
aad Additional Authenticated Data - scalar value with any (even raw
|
||||||
|
octects) data - JWE only (not available for "compact"
|
||||||
|
serialization);
|
||||||
|
|
||||||
|
serialization
|
||||||
|
Specify serialization method: "compat" (= default) for Compact
|
||||||
|
JWS/JWE serialization or "flattened" for Flattened JWS/JWE JSON
|
||||||
|
serialization.
|
||||||
|
|
||||||
|
General JSON serialization is not supported yet.
|
||||||
|
|
||||||
|
zip Compression method, currently 'deflate' is the only one supported.
|
||||||
|
"undef" (default) means no compression.
|
||||||
|
|
||||||
|
my $token = encode_jwt(payload=>$p, key=>$k, alg=>'HS256', zip=>'deflate');
|
||||||
|
#or define compression level
|
||||||
|
my $token = encode_jwt(payload=>$p, key=>$k, alg=>'HS256', zip=>['deflate', 9]);
|
||||||
|
|
||||||
|
auto_iat
|
||||||
|
1 - set 'iat' (Issued At) claim to current time (epoch seconds since
|
||||||
|
1970) at the moment of token encoding
|
||||||
|
|
||||||
|
0 (default) - do not set 'iat' claim
|
||||||
|
|
||||||
|
NOTE: claims are part of the payload and can be used only if the
|
||||||
|
payload is a HASH ref!
|
||||||
|
|
||||||
|
relative_exp
|
||||||
|
Set 'exp' claim (Expiration Time) to current time + "relative_exp"
|
||||||
|
value (in seconds).
|
||||||
|
|
||||||
|
NOTE: claims are part of the payload and can be used only if the
|
||||||
|
payload is a HASH ref!
|
||||||
|
|
||||||
|
relative_nbf
|
||||||
|
Set 'nbf' claim (Not Before) to current time + "relative_nbf" value
|
||||||
|
(in seconds).
|
||||||
|
|
||||||
|
NOTE: claims are part of the payload and can be used only if the
|
||||||
|
payload is a HASH ref!
|
||||||
|
|
||||||
|
SEE ALSO
|
||||||
|
Crypt::Cipher::AES, Crypt::AuthEnc::GCM, Crypt::PK::RSA, Crypt::PK::ECC,
|
||||||
|
Crypt::KeyDerivation, Crypt::KeyWrap
|
||||||
|
|
||||||
|
LICENSE
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the same terms as Perl itself.
|
||||||
|
|
||||||
|
COPYRIGHT
|
||||||
|
Copyright (c) 2015 DCIT, a.s. <http://www.dcit.cz> / Karel Miko
|
||||||
|
|
1262
lib/Crypt/JWT.pm
Normal file
1262
lib/Crypt/JWT.pm
Normal file
File diff suppressed because it is too large
Load Diff
603
lib/Crypt/KeyWrap.pm
Normal file
603
lib/Crypt/KeyWrap.pm
Normal file
@ -0,0 +1,603 @@
|
|||||||
|
package Crypt::KeyWrap;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
our $VERSION = '0.018';
|
||||||
|
|
||||||
|
use Exporter 'import';
|
||||||
|
our %EXPORT_TAGS = ( all => [qw(aes_key_wrap aes_key_unwrap gcm_key_wrap gcm_key_unwrap pbes2_key_wrap pbes2_key_unwrap ecdh_key_wrap ecdh_key_unwrap ecdhaes_key_wrap ecdhaes_key_unwrap rsa_key_wrap rsa_key_unwrap)] );
|
||||||
|
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
|
||||||
|
our @EXPORT = qw();
|
||||||
|
|
||||||
|
use Carp;
|
||||||
|
use Crypt::Mode::ECB;
|
||||||
|
use Crypt::AuthEnc::GCM qw(gcm_encrypt_authenticate gcm_decrypt_verify);
|
||||||
|
use Crypt::PRNG qw(random_bytes);
|
||||||
|
use Crypt::KeyDerivation qw(pbkdf2);
|
||||||
|
use Crypt::Digest qw(digest_data);
|
||||||
|
use Config;
|
||||||
|
|
||||||
|
# JWS: https://tools.ietf.org/html/rfc7515
|
||||||
|
# JWE: https://tools.ietf.org/html/rfc7516
|
||||||
|
# JWK: https://tools.ietf.org/html/rfc7517
|
||||||
|
# JWA: https://tools.ietf.org/html/rfc7518 - !!! this is important !!!
|
||||||
|
|
||||||
|
sub _LSB {
|
||||||
|
my ($bytes, $data) = @_;
|
||||||
|
my $len = length $data;
|
||||||
|
return $len > $bytes ? substr($data, $len-$bytes, $bytes) : $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _MSB {
|
||||||
|
my ($bytes, $data) = @_;
|
||||||
|
my $len = length $data;
|
||||||
|
return $len > $bytes ? substr($data, 0, $bytes) : $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _N2RAW {
|
||||||
|
my ($bytes, $n) = @_;
|
||||||
|
if ($bytes == 8) {
|
||||||
|
return pack("N", 0) . pack("N", $n) if $Config{uvsize} == 4; #workaround
|
||||||
|
return pack("N", $n >> 32) . pack("N", $n & 0xFFFFFFFF);
|
||||||
|
}
|
||||||
|
return pack("N", $n & 0xFFFFFFFF) if $bytes == 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub aes_key_wrap {
|
||||||
|
my ($kek, $pt_data, $cipher, $padding, $inverse) = @_;
|
||||||
|
$cipher = 'AES' unless defined $cipher;
|
||||||
|
$padding = $cipher eq 'AES' ? 1 : 0 unless defined $padding;
|
||||||
|
|
||||||
|
my ($A, $B, $P, $R);
|
||||||
|
|
||||||
|
croak "aes_key_wrap: no KEK" unless defined $kek;
|
||||||
|
croak "aes_key_wrap: no PT data" unless defined $pt_data;
|
||||||
|
my $klen = length $kek;
|
||||||
|
croak "aes_key_wrap: invalid KEK length" unless $klen == 16 || $klen == 24 || $klen == 32;
|
||||||
|
croak "aes_key_wrap: cipher must be AES or DES_EDE" unless $cipher eq 'AES' || $cipher eq 'DES_EDE';
|
||||||
|
croak "aes_key_wrap: padding not allowed with DES_EDE" if $padding && $cipher eq 'DES_EDE';
|
||||||
|
|
||||||
|
my $ECB = Crypt::Mode::ECB->new($cipher, 0);
|
||||||
|
my $blck = $cipher eq 'DES_EDE' ? 4 : 8; # semiblock size in bytes, for AES 8, for 3DES 4
|
||||||
|
|
||||||
|
my $IV = pack("H*", "A6" x $blck);
|
||||||
|
my $len = length $pt_data;
|
||||||
|
if ($len % $blck > 0) {
|
||||||
|
croak "aes_key_wrap: pt_data length not multiply of $blck" if !$padding;
|
||||||
|
$pt_data .= chr(0) x ($blck - ($len % $blck));
|
||||||
|
$IV = pack("H*", "A65959A6") . pack("N", $len);
|
||||||
|
}
|
||||||
|
|
||||||
|
my $n = length($pt_data) / $blck;
|
||||||
|
$P->[$_] = substr($pt_data, $_*$blck, $blck) for (0..$n-1);
|
||||||
|
|
||||||
|
if ($n == 1) {
|
||||||
|
return $inverse ? $ECB->decrypt($IV . $P->[0], $kek)
|
||||||
|
: $ECB->encrypt($IV . $P->[0], $kek);
|
||||||
|
}
|
||||||
|
|
||||||
|
$A = $IV;
|
||||||
|
$R->[$_] = $P->[$_] for (0..$n-1);
|
||||||
|
|
||||||
|
for my $j (0..5) {
|
||||||
|
for my $i (0..$n-1) {
|
||||||
|
$B = $inverse ? $ECB->decrypt($A . $R->[$i], $kek)
|
||||||
|
: $ECB->encrypt($A . $R->[$i], $kek);
|
||||||
|
$A = _MSB($blck, $B) ^ _N2RAW($blck, ($n*$j)+$i+1);
|
||||||
|
$R->[$i] = _LSB($blck, $B);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
my $rv = $A;
|
||||||
|
$rv .= $R->[$_] for (0..$n-1);
|
||||||
|
return $rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub aes_key_unwrap {
|
||||||
|
my ($kek, $ct_data, $cipher, $padding, $inverse) = @_;
|
||||||
|
$cipher = 'AES' unless defined $cipher;
|
||||||
|
$padding = $cipher eq 'AES' ? 1 : 0 unless defined $padding;
|
||||||
|
|
||||||
|
my ($A, $B, $C, $P, $R);
|
||||||
|
|
||||||
|
croak "aes_key_unwrap: no KEK" unless defined $kek;
|
||||||
|
croak "aes_key_unwrap: no CT data" unless defined $ct_data;
|
||||||
|
my $klen = length $kek;
|
||||||
|
croak "aes_key_unwrap: invalid KEK length" unless $klen == 16 || $klen == 24 || $klen == 32;
|
||||||
|
croak "aes_key_unwrap: cipher must be AES or DES_EDE" unless $cipher eq 'AES' || $cipher eq 'DES_EDE';
|
||||||
|
croak "aes_key_unwrap: padding not allowed with DES_EDE" if $padding && $cipher eq 'DES_EDE';
|
||||||
|
|
||||||
|
my $ECB = Crypt::Mode::ECB->new($cipher, 0);
|
||||||
|
my $blck = $cipher eq 'DES_EDE' ? 4 : 8; # semiblock size in bytes, for AES 8, for 3DES 4
|
||||||
|
|
||||||
|
my $n = length($ct_data) / $blck - 1;
|
||||||
|
$C->[$_] = substr($ct_data, $_*$blck, $blck) for (0..$n); # n+1 semiblocks
|
||||||
|
|
||||||
|
if ($n==1) {
|
||||||
|
$B = $inverse ? $ECB->encrypt($C->[0] . $C->[1], $kek)
|
||||||
|
: $ECB->decrypt($C->[0] . $C->[1], $kek);
|
||||||
|
$A = _MSB($blck, $B);
|
||||||
|
$R->[0] = _LSB($blck, $B);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$A = $C->[0];
|
||||||
|
$R->[$_] = $C->[$_+1] for (0..$n-1);
|
||||||
|
for(my $j=5; $j>=0; $j--) {
|
||||||
|
for(my $i=$n-1; $i>=0; $i--) {
|
||||||
|
$B = $inverse ? $ECB->encrypt(($A ^ _N2RAW($blck, $n*$j+$i+1)) . $R->[$i], $kek)
|
||||||
|
: $ECB->decrypt(($A ^ _N2RAW($blck, $n*$j+$i+1)) . $R->[$i], $kek);
|
||||||
|
$A = _MSB($blck, $B);
|
||||||
|
$R->[$i] = _LSB($blck, $B);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
my $rv = '';
|
||||||
|
$rv .= $R->[$_] for (0..$n-1);
|
||||||
|
|
||||||
|
my $A_hex = unpack("H*", $A);
|
||||||
|
if ($A_hex eq 'a6'x$blck) {
|
||||||
|
return $rv;
|
||||||
|
}
|
||||||
|
elsif ($A_hex =~ /^a65959a6/ && $blck == 8) {
|
||||||
|
warn "key_unwrap: unexpected padding" unless $padding;
|
||||||
|
my $n = unpack("N", substr($A, 4, 4));
|
||||||
|
my $z = length($rv) - $n;
|
||||||
|
my $tail = unpack("H*", substr($rv, -$z));
|
||||||
|
croak "aes_key_unwrap: invalid data" unless $tail eq "00"x$z;
|
||||||
|
return substr($rv, 0, $n);
|
||||||
|
}
|
||||||
|
croak "aes_key_unwrap: unexpected data [$cipher/$A_hex]";
|
||||||
|
}
|
||||||
|
|
||||||
|
# AES GCM KW - https://tools.ietf.org/html/rfc7518#section-4.7
|
||||||
|
|
||||||
|
sub gcm_key_wrap {
|
||||||
|
my ($kek, $pt_data, $aad, $cipher, $iv) = @_;
|
||||||
|
$cipher = 'AES' unless defined $cipher;
|
||||||
|
$iv = random_bytes(Crypt::Cipher->blocksize($cipher)) unless defined $iv;
|
||||||
|
my ($ct_data, $tag) = gcm_encrypt_authenticate($cipher, $kek, $iv, $aad, $pt_data);
|
||||||
|
return ($ct_data, $tag, $iv);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub gcm_key_unwrap {
|
||||||
|
my ($kek, $ct_data, $tag, $iv, $aad, $cipher) = @_;
|
||||||
|
$cipher ||= 'AES';
|
||||||
|
my $pt_data = gcm_decrypt_verify($cipher, $kek, $iv, $aad, $ct_data, $tag);
|
||||||
|
return $pt_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
# PBES2/PBKDF2 KW - https://tools.ietf.org/html/rfc7518#section-4.8
|
||||||
|
|
||||||
|
sub pbes2_key_wrap {
|
||||||
|
my ($kek, $pt_data, $alg, $salt, $iter) = @_;
|
||||||
|
my ($hash_name, $len);
|
||||||
|
if ($alg =~ /^PBES2-HS(256|384|512)\+A(128|192|256)KW$/) {
|
||||||
|
$hash_name = "SHA$1";
|
||||||
|
$len = $2/8;
|
||||||
|
my $aes_key = pbkdf2($kek, $alg."\x00".$salt, $iter, $hash_name, $len);
|
||||||
|
my $ct_data = aes_key_wrap($aes_key, $pt_data);
|
||||||
|
return $ct_data;
|
||||||
|
}
|
||||||
|
croak "pbes2_key_wrap: invalid alg '$alg'";
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub pbes2_key_unwrap {
|
||||||
|
my ($kek, $ct_data, $alg, $salt, $iter) = @_;
|
||||||
|
my ($hash_name, $len);
|
||||||
|
if ($alg =~ /^PBES2-HS(256|384|512)\+A(128|192|256)KW$/) {
|
||||||
|
$hash_name = "SHA$1";
|
||||||
|
$len = $2/8;
|
||||||
|
my $aes_key = pbkdf2($kek, $alg."\x00".$salt, $iter, $hash_name, $len);
|
||||||
|
my $pt_data = aes_key_unwrap($aes_key, $ct_data);
|
||||||
|
return $pt_data;
|
||||||
|
}
|
||||||
|
croak "pbes2_key_unwrap: invalid alg '$alg'";
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
# RSA KW
|
||||||
|
# https://tools.ietf.org/html/rfc7518#section-4.2
|
||||||
|
# https://tools.ietf.org/html/rfc7518#section-4.3
|
||||||
|
|
||||||
|
sub rsa_key_wrap {
|
||||||
|
my ($kek_public, $pt_data, $alg) = @_;
|
||||||
|
croak "rsa_key_wrap: no Crypt::PK::RSA" unless ref $kek_public eq 'Crypt::PK::RSA';
|
||||||
|
my ($padding, $hash_name);
|
||||||
|
if ($alg eq 'RSA-OAEP') { ($padding, $hash_name) = ('oaep', 'SHA1') }
|
||||||
|
elsif ($alg eq 'RSA-OAEP-256') { ($padding, $hash_name) = ('oaep', 'SHA256') }
|
||||||
|
elsif ($alg eq 'RSA1_5') { $padding = 'v1.5' }
|
||||||
|
croak "rsa_key_wrap: invalid algorithm '$alg'" unless $padding;
|
||||||
|
my $ct_data = $kek_public->encrypt($pt_data, $padding, $hash_name);
|
||||||
|
return $ct_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub rsa_key_unwrap {
|
||||||
|
my ($kek_private, $ct_data, $alg) = @_;
|
||||||
|
croak "rsa_key_unwrap: no Crypt::PK::RSA" unless ref $kek_private eq 'Crypt::PK::RSA';
|
||||||
|
croak "rsa_key_unwrap: no private key" unless $kek_private->is_private;
|
||||||
|
my ($padding, $hash_name);
|
||||||
|
if ($alg eq 'RSA-OAEP') { ($padding, $hash_name) = ('oaep', 'SHA1') }
|
||||||
|
elsif ($alg eq 'RSA-OAEP-256') { ($padding, $hash_name) = ('oaep', 'SHA256') }
|
||||||
|
elsif ($alg eq 'RSA1_5') { $padding = 'v1.5' }
|
||||||
|
croak "rsa_key_unwrap: invalid algorithm '$alg'" unless $padding;
|
||||||
|
my $pt_data = $kek_private->decrypt($ct_data, $padding, $hash_name);
|
||||||
|
return $pt_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ConcatKDF - http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar2.pdf
|
||||||
|
# ECDH KW - https://tools.ietf.org/html/rfc7518#section-4.6
|
||||||
|
|
||||||
|
sub _concat_kdf {
|
||||||
|
my ($hash_name, $key_size, $shared_secret, $algorithm, $apu, $apv) = @_;
|
||||||
|
$apu = '' unless defined $apu;
|
||||||
|
$apv = '' unless defined $apv;
|
||||||
|
my $hsize = Crypt::Digest->hashsize($hash_name);
|
||||||
|
my $count = int($key_size / $hsize);
|
||||||
|
$count++ if ($key_size % $hsize) > 0;
|
||||||
|
my $data = '';
|
||||||
|
for my $i (1..$count) {
|
||||||
|
$data .= digest_data('SHA256', pack("N", 1) .
|
||||||
|
$shared_secret .
|
||||||
|
pack("N", length($algorithm)) . $algorithm .
|
||||||
|
pack("N", length($apu)) . $apu .
|
||||||
|
pack("N", length($apv)) . $apv .
|
||||||
|
pack("N", 8 *$key_size));
|
||||||
|
}
|
||||||
|
return substr($data, 0, $key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ecdh_key_wrap {
|
||||||
|
my ($kek_public, $enc, $apu, $apv) = @_;
|
||||||
|
croak "ecdh_key_wrap: no Crypt::PK::ECC" unless ref $kek_public eq 'Crypt::PK::ECC';
|
||||||
|
my $encryption_key_size = 256;
|
||||||
|
if ($enc =~ /^A(128|192|256)CBC-HS/) {
|
||||||
|
$encryption_key_size = $1*2;
|
||||||
|
}
|
||||||
|
if ($enc =~ /^A(128|192|256)GCM/) {
|
||||||
|
$encryption_key_size = $1;
|
||||||
|
}
|
||||||
|
my $ephemeral = Crypt::PK::ECC->new()->generate_key($kek_public->curve2hash);
|
||||||
|
my $shared_secret = $ephemeral->shared_secret($kek_public);
|
||||||
|
my $ct_data = _concat_kdf('SHA256', $encryption_key_size/8, $shared_secret, $enc, $apu, $apv);
|
||||||
|
return ($ct_data, $ephemeral->export_key_jwk('public'));
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ecdh_key_unwrap {
|
||||||
|
my ($kek_private, $enc, $epk, $apu, $apv) = @_;
|
||||||
|
croak "ecdh_key_unwrap: no Crypt::PK::ECC" unless ref $kek_private eq 'Crypt::PK::ECC';
|
||||||
|
croak "ecdh_key_unwrap: no private key" unless $kek_private->is_private;
|
||||||
|
my $encryption_key_size = 256;
|
||||||
|
if ($enc =~ /^A(128|192|256)CBC-HS/) {
|
||||||
|
$encryption_key_size = $1*2;
|
||||||
|
}
|
||||||
|
if ($enc =~ /^A(128|192|256)GCM/) {
|
||||||
|
$encryption_key_size = $1;
|
||||||
|
}
|
||||||
|
my $ephemeral = ref($epk) eq 'Crypt::PK::ECC' ? $epk : Crypt::PK::ECC->new(ref $epk ? $epk : \$epk);
|
||||||
|
my $shared_secret = $kek_private->shared_secret($ephemeral);
|
||||||
|
my $pt_data = _concat_kdf('SHA256', $encryption_key_size/8, $shared_secret, $enc, $apu, $apv);
|
||||||
|
return $pt_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ecdhaes_key_wrap {
|
||||||
|
my ($kek_public, $pt_data, $alg, $apu, $apv) = @_;
|
||||||
|
croak "ecdhaes_key_wrap: no Crypt::PK::ECC" unless ref $kek_public eq 'Crypt::PK::ECC';
|
||||||
|
my $encryption_key_size = 256;
|
||||||
|
if ($alg =~ /^ECDH-ES\+A(128|192|256)KW$/) {
|
||||||
|
$encryption_key_size = $1;
|
||||||
|
}
|
||||||
|
my $ephemeral = Crypt::PK::ECC->new()->generate_key($kek_public->curve2hash);
|
||||||
|
my $shared_secret = $ephemeral->shared_secret($kek_public);
|
||||||
|
my $kek = _concat_kdf('SHA256', $encryption_key_size/8, $shared_secret, $alg, $apu, $apv);
|
||||||
|
return (aes_key_wrap($kek, $pt_data), $ephemeral->export_key_jwk('public'));
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ecdhaes_key_unwrap {
|
||||||
|
my ($kek_private, $ct_data, $alg, $epk, $apu, $apv) = @_;
|
||||||
|
croak "ecdhaes_key_unwrap: no Crypt::PK::ECC" unless ref $kek_private eq 'Crypt::PK::ECC';
|
||||||
|
croak "ecdhaes_key_unwrap: no private key" unless $kek_private->is_private;
|
||||||
|
my $encryption_key_size = 256;
|
||||||
|
if ($alg =~ /^ECDH-ES\+A(128|192|256)KW$/) {
|
||||||
|
$encryption_key_size = $1;
|
||||||
|
}
|
||||||
|
my $ephemeral = ref($epk) eq 'Crypt::PK::ECC' ? $epk : Crypt::PK::ECC->new(ref $epk ? $epk : \$epk);
|
||||||
|
my $shared_secret = $kek_private->shared_secret($ephemeral);
|
||||||
|
my $kek = _concat_kdf('SHA256', $encryption_key_size/8, $shared_secret, $alg, $apu, $apv);
|
||||||
|
my $pt_data = aes_key_unwrap($kek, $ct_data);
|
||||||
|
return $pt_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
||||||
|
|
||||||
|
=pod
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
Crypt::KeyWrap - Key management/wrapping algorithms defined in RFC7518 (JWA)
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
# A192KW wrapping
|
||||||
|
use Crypt::KeyWrap qw(aes_key_wrap);
|
||||||
|
my $kek = pack("H*", "5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8"); # key encryption key
|
||||||
|
my $cek = pack("H*", "c37b7e6492584340bed12207808941155068f738"); # content encryption key
|
||||||
|
my $enc_cek = aes_key_wrap($kek, $pt_data); # encrypted content encryption key
|
||||||
|
|
||||||
|
# A192KW unwrapping
|
||||||
|
use Crypt::KeyWrap qw(aes_key_unwrap);
|
||||||
|
my $kek = pack("H*", "5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8");
|
||||||
|
my $enc_cek = pack("H*", "138bdeaa9b8fa7fc61f97742e72248ee5ae6ae5360d1ae6a5f54f373fa543b6a");
|
||||||
|
my $cek = aes_key_unwrap($kek, $pt_data);
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
Implements key management algorithms defined in L<https://tools.ietf.org/html/rfc7518>
|
||||||
|
|
||||||
|
BEWARE: experimental, interface of this module might change!
|
||||||
|
|
||||||
|
Supported algorithms (all defined in RFC7518):
|
||||||
|
|
||||||
|
A128KW see: aes_key_wrap() + aes_key_unwrap()
|
||||||
|
A192KW see: aes_key_wrap() + aes_key_unwrap()
|
||||||
|
A256KW see: aes_key_wrap() + aes_key_unwrap()
|
||||||
|
A128GCMKW see: gcm_key_wrap() + gcm_key_unwrap()
|
||||||
|
A192GCMKW see: gcm_key_wrap() + gcm_key_unwrap()
|
||||||
|
A256GCMKW see: gcm_key_wrap() + gcm_key_unwrap()
|
||||||
|
PBES2-HS256+A128KW see: pbes2_key_wrap() + pbes2_key_unwrap()
|
||||||
|
PBES2-HS384+A192KW see: pbes2_key_wrap() + pbes2_key_unwrap()
|
||||||
|
PBES2-HS512+A256KW see: pbes2_key_wrap() + pbes2_key_unwrap()
|
||||||
|
RSA-OAEP see: rsa_key_wrap() + rsa_key_unwrap()
|
||||||
|
RSA-OAEP-256 see: rsa_key_wrap() + rsa_key_unwrap()
|
||||||
|
RSA1_5 see: rsa_key_wrap() + rsa_key_unwrap()
|
||||||
|
ECDH-ES+A128KW see: ecdhaes_key_wrap() + ecdhaes_key_unwrap()
|
||||||
|
ECDH-ES+A192KW see: ecdhaes_key_wrap() + ecdhaes_key_unwrap()
|
||||||
|
ECDH-ES+A256KW see: ecdhaes_key_wrap() + ecdhaes_key_unwrap()
|
||||||
|
ECDH-ES see: ecdh_key_wrap() + ecdh_key_unwrap()
|
||||||
|
|
||||||
|
=head1 EXPORT
|
||||||
|
|
||||||
|
Nothing is exported by default.
|
||||||
|
|
||||||
|
You can export selected functions:
|
||||||
|
|
||||||
|
use Crypt::KeyWrap qw(aes_key_wrap gcm_key_wrap pbes2_key_wrap);
|
||||||
|
|
||||||
|
Or all of them at once:
|
||||||
|
|
||||||
|
use Crypt::KeyWrap ':all';
|
||||||
|
|
||||||
|
=head1 FUNCTIONS
|
||||||
|
|
||||||
|
=head2 aes_key_wrap
|
||||||
|
|
||||||
|
AES key wrap algorithm as defined in L<https://tools.ietf.org/html/rfc7518#section-4.4>
|
||||||
|
(implements algorithms C<A128KW>, C<A192KW>, C<A256KW>).
|
||||||
|
|
||||||
|
Implementation follows L<https://tools.ietf.org/html/rfc5649> and L<https://tools.ietf.org/html/rfc3394>.
|
||||||
|
|
||||||
|
The implementation is also compatible with L<http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf>
|
||||||
|
(it supports AES based KW, KWP + TDEA/DES_EDE based TKW).
|
||||||
|
|
||||||
|
AES Key Wrap algorithm.
|
||||||
|
|
||||||
|
$enc_cek = aes_key_wrap($kek, $cek);
|
||||||
|
# or
|
||||||
|
$enc_cek = aes_key_wrap($kek, $cek, $cipher, $padding, $inverse);
|
||||||
|
|
||||||
|
# params:
|
||||||
|
# $kek .. key encryption key (16bytes for AES128, 24 for AES192, 32 for AES256)
|
||||||
|
# $cek .. content encryption key
|
||||||
|
# optional params:
|
||||||
|
# $cipher .. 'AES' (default) or 'DES_EDE'
|
||||||
|
# $padding .. 1 (default) or 0 handle $cek padding (relevant for AES only)
|
||||||
|
# $inverse .. 0 (default) or 1 use cipher in inverse mode as defined by SP.800-38F
|
||||||
|
|
||||||
|
Values C<$enc_cek>, C<$cek> and C<$kek> are binary octets. If you disable padding you have to make sure that
|
||||||
|
C<$cek> length is multiply of 8 (for AES) or multiply of 4 (for DES_EDE);
|
||||||
|
|
||||||
|
=head2 aes_key_unwrap
|
||||||
|
|
||||||
|
AES key unwrap algorithm as defined in L<https://tools.ietf.org/html/rfc7518#section-4.4>
|
||||||
|
(implements algorithms C<A128KW>, C<A192KW>, C<A256KW>).
|
||||||
|
|
||||||
|
AES Key Unwrap algorithm.
|
||||||
|
|
||||||
|
$cek = aes_key_unwrap($kek, $enc_cek);
|
||||||
|
# or
|
||||||
|
$cek = aes_key_unwrap($kek, $enc_cek, $cipher, $padding, $inverse);
|
||||||
|
|
||||||
|
# params:
|
||||||
|
# $kek .. key encryption key (16bytes for AES128, 24 for AES192, 32 for AES256)
|
||||||
|
# $enc_cek .. encrypted content encryption key
|
||||||
|
# optional params:
|
||||||
|
# $cipher .. 'AES' (default) or 'DES_EDE'
|
||||||
|
# $padding .. 1 (default) or 0 - use $cek padding (relevant for AES only)
|
||||||
|
# $inverse .. 0 (default) or 1 - use cipher in inverse mode as defined by SP.800-38F
|
||||||
|
|
||||||
|
Values C<$enc_cek>, C<$cek> and C<$kek> are binary octets.
|
||||||
|
|
||||||
|
=head2 gcm_key_wrap
|
||||||
|
|
||||||
|
AES GCM key wrap algorithm as defined in L<https://tools.ietf.org/html/rfc7518#section-4.7>
|
||||||
|
(implements algorithms C<A128GCMKW>, C<A192GCMKW>, C<A256GCMKW>).
|
||||||
|
|
||||||
|
($enc_cek, $tag, $iv) = gcm_key_wrap($kek, $cek);
|
||||||
|
#or
|
||||||
|
($enc_cek, $tag, $iv) = gcm_key_wrap($kek, $cek, $aad);
|
||||||
|
#or
|
||||||
|
($enc_cek, $tag, $iv) = gcm_key_wrap($kek, $cek, $aad, $cipher, $iv);
|
||||||
|
|
||||||
|
# params:
|
||||||
|
# $kek .. key encryption key (16bytes for AES128, 24 for AES192, 32 for AES256)
|
||||||
|
# $cek .. content encryption key
|
||||||
|
# optional params:
|
||||||
|
# $aad .. additional authenticated data, DEFAULT is '' (empty string)
|
||||||
|
# $cipher .. cipher to be used by GCM, DEFAULT is 'AES'
|
||||||
|
# $iv .. initialization vector (if not defined a random IV is generated)
|
||||||
|
|
||||||
|
Values C<$enc_cek>, C<$cek>, C<$aad>, C<$iv>, C<$tag> and C<$kek> are binary octets.
|
||||||
|
|
||||||
|
=head2 gcm_key_unwrap
|
||||||
|
|
||||||
|
AES GCM key unwrap algorithm as defined in L<https://tools.ietf.org/html/rfc7518#section-4.7>
|
||||||
|
(implements algorithms C<A128GCMKW>, C<A192GCMKW>, C<A256GCMKW>).
|
||||||
|
|
||||||
|
$cek = gcm_key_unwrap($kek, $enc_cek, $tag, $iv);
|
||||||
|
# or
|
||||||
|
$cek = gcm_key_unwrap($kek, $enc_cek, $tag, $iv, $aad);
|
||||||
|
# or
|
||||||
|
$cek = gcm_key_unwrap($kek, $enc_cek, $tag, $iv, $aad, $cipher);
|
||||||
|
|
||||||
|
# params:
|
||||||
|
# $kek .. key encryption key (16bytes for AES128, 24 for AES192, 32 for AES256)
|
||||||
|
# $enc_cek .. encrypted content encryption key
|
||||||
|
# $tag .. GCM's tag
|
||||||
|
# $iv .. initialization vector
|
||||||
|
# optional params:
|
||||||
|
# $aad .. additional authenticated data, DEFAULT is '' (empty string)
|
||||||
|
# $cipher .. cipher to be used by GCM, DEFAULT is 'AES'
|
||||||
|
|
||||||
|
Values C<$enc_cek>, C<$cek>, C<$aad>, C<$iv>, C<$tag> and C<$kek> are binary octets.
|
||||||
|
|
||||||
|
=head2 pbes2_key_wrap
|
||||||
|
|
||||||
|
PBES2 key wrap algorithm as defined in L<https://tools.ietf.org/html/rfc7518#section-4.8>
|
||||||
|
(implements algorithms C<PBES2-HS256+A128KW>, C<PBES2-HS384+A192KW>, C<PBES2-HS512+A256KW>).
|
||||||
|
|
||||||
|
$enc_cek = pbes2_key_wrap($kek, $cek, $alg, $salt, $iter);
|
||||||
|
|
||||||
|
# params:
|
||||||
|
# $kek .. key encryption key (arbitrary length)
|
||||||
|
# $cek .. content encryption key
|
||||||
|
# $alg .. algorithm name e.g. 'PBES2-HS256+A128KW' (see rfc7518)
|
||||||
|
# $salt .. pbkdf2 salt
|
||||||
|
# $iter .. pbkdf2 iteration count
|
||||||
|
|
||||||
|
Values C<$enc_cek>, C<$cek>, C<$salt> and C<$kek> are binary octets.
|
||||||
|
|
||||||
|
=head2 pbes2_key_unwrap
|
||||||
|
|
||||||
|
PBES2 key unwrap algorithm as defined in L<https://tools.ietf.org/html/rfc7518#section-4.8>
|
||||||
|
(implements algorithms C<PBES2-HS256+A128KW>, C<PBES2-HS384+A192KW>, C<PBES2-HS512+A256KW>).
|
||||||
|
|
||||||
|
$cek = pbes2_key_unwrap($kek, $enc_cek, $alg, $salt, $iter);
|
||||||
|
|
||||||
|
# params:
|
||||||
|
# $kek .. key encryption key (arbitrary length)
|
||||||
|
# $enc_cek .. encrypted content encryption key
|
||||||
|
# $alg .. algorithm name e.g. 'PBES2-HS256+A128KW' (see rfc7518)
|
||||||
|
# $salt .. pbkdf2 salt
|
||||||
|
# $iter .. pbkdf2 iteration count
|
||||||
|
|
||||||
|
Values C<$enc_cek>, C<$cek>, C<$salt> and C<$kek> are binary octets.
|
||||||
|
|
||||||
|
=head2 rsa_key_wrap
|
||||||
|
|
||||||
|
PBES2 key wrap algorithm as defined in L<https://tools.ietf.org/html/rfc7518#section-4.2> and
|
||||||
|
L<https://tools.ietf.org/html/rfc7518#section-4.3> (implements algorithms C<RSA1_5>, C<RSA-OAEP-256>, C<RSA-OAEP>).
|
||||||
|
|
||||||
|
$enc_cek = rsa_key_wrap($kek, $cek, $alg);
|
||||||
|
|
||||||
|
# params:
|
||||||
|
# $kek .. RSA public key - Crypt::PK::RSA instance
|
||||||
|
# $cek .. content encryption key
|
||||||
|
# $alg .. algorithm name e.g. 'RSA-OAEP' (see rfc7518)
|
||||||
|
|
||||||
|
Values C<$enc_cek> and C<$cek> are binary octets.
|
||||||
|
|
||||||
|
=head2 rsa_key_unwrap
|
||||||
|
|
||||||
|
PBES2 key wrap algorithm as defined in L<https://tools.ietf.org/html/rfc7518#section-4.2> and
|
||||||
|
L<https://tools.ietf.org/html/rfc7518#section-4.3> (implements algorithms C<RSA1_5>, C<RSA-OAEP-256>, C<RSA-OAEP>).
|
||||||
|
|
||||||
|
$cek = rsa_key_unwrap($kek, $enc_cek, $alg);
|
||||||
|
|
||||||
|
# params:
|
||||||
|
# $kek .. RSA private key - Crypt::PK::RSA instance
|
||||||
|
# $enc_cek .. encrypted content encryption key
|
||||||
|
# $alg .. algorithm name e.g. 'RSA-OAEP' (see rfc7518)
|
||||||
|
|
||||||
|
Values C<$enc_cek> and C<$cek> are binary octets.
|
||||||
|
|
||||||
|
=head2 ecdhaes_key_wrap
|
||||||
|
|
||||||
|
ECDH+AESKW key agreement/wrap algorithm as defined in L<https://tools.ietf.org/html/rfc7518#section-4.6>
|
||||||
|
(implements algorithms C<ECDH-ES+A128KW>, C<ECDH-ES+A192KW>, C<ECDH-ES+A256KW>).
|
||||||
|
|
||||||
|
($enc_cek, $epk) = ecdhaes_key_wrap($kek, $cek, $alg, $apu, $apv);
|
||||||
|
|
||||||
|
# params:
|
||||||
|
# $kek .. ECC public key - Crypt::PK::ECC instance
|
||||||
|
# $cek .. content encryption key
|
||||||
|
# $alg .. algorithm name e.g. 'ECDH-ES+A256KW' (see rfc7518)
|
||||||
|
# optional params:
|
||||||
|
# $apu .. Agreement PartyUInfo Header Parameter
|
||||||
|
# $apv .. Agreement PartyVInfo Header Parameter
|
||||||
|
|
||||||
|
Values C<$enc_cek> and C<$cek> are binary octets.
|
||||||
|
|
||||||
|
=head2 ecdhaes_key_unwrap
|
||||||
|
|
||||||
|
ECDH+AESKW key agreement/unwrap algorithm as defined in L<https://tools.ietf.org/html/rfc7518#section-4.6>
|
||||||
|
(implements algorithms C<ECDH-ES+A128KW>, C<ECDH-ES+A192KW>, C<ECDH-ES+A256KW>).
|
||||||
|
|
||||||
|
$cek = ecdhaes_key_unwrap($kek, $enc_cek, $alg, $epk, $apu, $apv);
|
||||||
|
|
||||||
|
# params:
|
||||||
|
# $kek .. ECC private key - Crypt::PK::ECC instance
|
||||||
|
# $enc_cek .. encrypted content encryption key
|
||||||
|
# $alg .. algorithm name e.g. 'ECDH-ES+A256KW' (see rfc7518)
|
||||||
|
# $epk .. ephemeral ECC public key (JWK/JSON or Crypt::PK::ECC)
|
||||||
|
# optional params:
|
||||||
|
# $apu .. Agreement PartyUInfo Header Parameter
|
||||||
|
# $apv .. Agreement PartyVInfo Header Parameter
|
||||||
|
|
||||||
|
Values C<$enc_cek> and C<$cek> are binary octets.
|
||||||
|
|
||||||
|
=head2 ecdh_key_wrap
|
||||||
|
|
||||||
|
ECDH (Ephememeral Static) key agreement/wrap algorithm as defined in L<https://tools.ietf.org/html/rfc7518#section-4.6>
|
||||||
|
(implements algorithm C<ECDH-ES>).
|
||||||
|
|
||||||
|
($cek, $epk) = ecdh_key_wrap($kek, $enc, $apu, $apv);
|
||||||
|
|
||||||
|
# params:
|
||||||
|
# $kek .. ECC public key - Crypt::PK::ECC instance
|
||||||
|
# $enc .. encryption algorithm name e.g. 'A256GCM' (see rfc7518)
|
||||||
|
# optional params:
|
||||||
|
# $apu .. Agreement PartyUInfo Header Parameter
|
||||||
|
# $apv .. Agreement PartyVInfo Header Parameter
|
||||||
|
|
||||||
|
Value C<$cek> - binary octets, C<$epk> JWK/JSON string with ephemeral ECC public key.
|
||||||
|
|
||||||
|
=head2 ecdh_key_unwrap
|
||||||
|
|
||||||
|
ECDH (Ephememeral Static) key agreement/unwrap algorithm as defined in L<https://tools.ietf.org/html/rfc7518#section-4.6>
|
||||||
|
(implements algorithm C<ECDH-ES>).
|
||||||
|
|
||||||
|
$cek = ecdh_key_unwrap($kek, $enc, $epk, $apu, $apv);
|
||||||
|
|
||||||
|
# params:
|
||||||
|
# $kek .. ECC private key - Crypt::PK::ECC instance
|
||||||
|
# $enc .. encryption algorithm name e.g. 'A256GCM' (see rfc7518)
|
||||||
|
# $epk .. ephemeral ECC public key (JWK/JSON or Crypt::PK::ECC)
|
||||||
|
# optional params:
|
||||||
|
# $apu .. Agreement PartyUInfo Header Parameter
|
||||||
|
# $apv .. Agreement PartyVInfo Header Parameter
|
||||||
|
|
||||||
|
Value C<$cek> - binary octets.
|
||||||
|
|
||||||
|
=head1 SEE ALSO
|
||||||
|
|
||||||
|
L<Crypt::Cipher::AES>, L<Crypt::AuthEnc::GCM>, L<Crypt::PK::RSA>, L<Crypt::KeyDerivation>
|
||||||
|
|
||||||
|
=head1 LICENSE
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
|
||||||
|
|
||||||
|
=head1 COPYRIGHT
|
||||||
|
|
||||||
|
Copyright (c) 2015 DCIT, a.s. L<http://www.dcit.cz> / Karel Miko
|
7
t/compile.t
Normal file
7
t/compile.t
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use Test::More tests => 2;
|
||||||
|
|
||||||
|
use_ok('Crypt::KeyWrap');
|
||||||
|
use_ok('Crypt::JWT');
|
65
t/flattened.t
Normal file
65
t/flattened.t
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Test::More tests => 4;
|
||||||
|
|
||||||
|
use Crypt::JWT qw(decode_jwt encode_jwt);
|
||||||
|
|
||||||
|
### JWS - test case from https://github.com/Spomky-Labs/jose
|
||||||
|
|
||||||
|
my $key1 = {
|
||||||
|
'kid' => 'e9bc097a-ce51-4036-9562-d2ade882db0d',
|
||||||
|
'kty' => 'EC',
|
||||||
|
'crv' => 'P-256',
|
||||||
|
'x' => 'f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU',
|
||||||
|
'y' => 'x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0',
|
||||||
|
'd' => 'jpsQnnGQmL-YBIffH1136cspYG6-0iY7X1fCE9-E9LI',
|
||||||
|
};
|
||||||
|
|
||||||
|
my $jws = '{"payload":"eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ","protected":"eyJhbGciOiJFUzI1NiJ9","header":{"kid":"e9bc097a-ce51-4036-9562-d2ade882db0d"},"signature":"DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q"}';
|
||||||
|
|
||||||
|
my ($header, $data) = decode_jwt(token=>$jws, key=>$key1, verify_exp=>0, decode_header=>1);
|
||||||
|
is($data->{iss}, "joe");
|
||||||
|
is($data->{exp}, 1300819380);
|
||||||
|
is($header->{alg}, "ES256");
|
||||||
|
is($header->{kid}, "e9bc097a-ce51-4036-9562-d2ade882db0d");
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
#Example from RFC 7516 (JWE)
|
||||||
|
|
||||||
|
{
|
||||||
|
require JSON::MaybeXS;
|
||||||
|
|
||||||
|
#https://tools.ietf.org/html/rfc7516#appendix-A.2.3
|
||||||
|
my $jwk_hr = {
|
||||||
|
kty => "RSA",
|
||||||
|
n => "sXchDaQebHnPiGvyDOAT4saGEUetSyo9MKLOoWFsueri23bOdgWp4Dy1WlUzewbgBHod5pcM9H95GQRV3JDXboIRROSBigeC5yjU1hGzHHyXss8UDprecbAYxknTcQkhslANGRUZmdTOQ5qTRsLAt6BTYuyvVRdhS8exSZEy_c4gs_7svlJJQ4H9_NxsiIoLwAEk7-Q3UXERGYw_75IDrGA84-lA_-Ct4eTlXHBIY2EaV7t7LjJaynVJCpkv4LKjTTAumiGUIuQhrNhZLuF_RJLqHpM2kgWFLU7-VTdL1VbC2tejvcI2BlMkEpk1BzBZI0KQB0GaDWFLN-aEAw3vRw",
|
||||||
|
e => "AQAB",
|
||||||
|
d => "VFCWOqXr8nvZNyaaJLXdnNPXZKRaWCjkU5Q2egQQpTBMwhprMzWzpR8Sxq1OPThh_J6MUD8Z35wky9b8eEO0pwNS8xlh1lOFRRBoNqDIKVOku0aZb-rynq8cxjDTLZQ6Fz7jSjR1Klop-YKaUHc9GsEofQqYruPhzSA-QgajZGPbE_0ZaVDJHfyd7UUBUKunFMScbflYAAOYJqVIVwaYR5zWEEceUjNnTNo_CVSj-VvXLO5VZfCUAVLgW4dpf1SrtZjSt34YLsRarSb127reG_DUwg9Ch-KyvjT1SkHgUWRVGcyly7uvVGRSDwsXypdrNinPA4jlhoNdizK2zF2CWQ",
|
||||||
|
p => "9gY2w6I6S6L0juEKsbeDAwpd9WMfgqFoeA9vEyEUuk4kLwBKcoe1x4HG68ik918hdDSE9vDQSccA3xXHOAFOPJ8R9EeIAbTi1VwBYnbTp87X-xcPWlEPkrdoUKW60tgs1aNd_Nnc9LEVVPMS390zbFxt8TN_biaBgelNgbC95sM",
|
||||||
|
q => "uKlCKvKv_ZJMVcdIs5vVSU_6cPtYI1ljWytExV_skstvRSNi9r66jdd9-yBhVfuG4shsp2j7rGnIio901RBeHo6TPKWVVykPu1iYhQXw1jIABfw-MVsN-3bQ76WLdt2SDxsHs7q7zPyUyHXmps7ycZ5c72wGkUwNOjYelmkiNS0",
|
||||||
|
dp => "w0kZbV63cVRvVX6yk3C8cMxo2qCM4Y8nsq1lmMSYhG4EcL6FWbX5h9yuvngs4iLEFk6eALoUS4vIWEwcL4txw9LsWH_zKI-hwoReoP77cOdSL4AVcraHawlkpyd2TWjE5evgbhWtOxnZee3cXJBkAi64Ik6jZxbvk-RR3pEhnCs",
|
||||||
|
dq => "o_8V14SezckO6CNLKs_btPdFiO9_kC1DsuUTd2LAfIIVeMZ7jn1Gus_Ff7B7IVx3p5KuBGOVF8L-qifLb6nQnLysgHDh132NDioZkhH7mI7hPG-PYE_odApKdnqECHWw0J-F0JWnUd6D2B_1TvF9mXA2Qx-iGYn8OVV1Bsmp6qU",
|
||||||
|
qi => "eNho5yRBEBxhGBtQRww9QirZsB66TrfFReG_CcteI1aCneT0ELGhYlRlCtUkTRclIfuEPmNsNDPbLoLqqCVznFbvdB7x-Tl-m0l_eFTj2KiqwGqE9PZB9nNTwMVvH3VRRSLWACvPnSiwP8N5Usy-WRXS-V7TbpxIhvepTfE0NNo",
|
||||||
|
};
|
||||||
|
|
||||||
|
#https://tools.ietf.org/html/rfc7516#appendix-A.3.3
|
||||||
|
my $key = { "kty" => "oct", "k" => "GawgguFyGrWKav7AX4VKUg" };
|
||||||
|
|
||||||
|
#https://tools.ietf.org/html/rfc7516#appendix-A.5
|
||||||
|
my $jwe_flattened = JSON::MaybeXS::encode_json(
|
||||||
|
{
|
||||||
|
protected => "eyJlbmMiOiJBMTI4Q0JDLUhTMjU2In0",
|
||||||
|
unprotected => { "jku" => "https://server.example.com/keys.jwks" },
|
||||||
|
header => { "alg" => "A128KW", "kid" => "7" },
|
||||||
|
encrypted_key => "6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ",
|
||||||
|
iv => "AxY8DCtDaGlsbGljb3RoZQ",
|
||||||
|
ciphertext => "KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY",
|
||||||
|
tag => "Mz-VPPyU4RlcuYv1IwIvzw",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
my ($header, $data) = decode_jwt(token=>$jwe_flattened, key=>$key, verify_exp=>0, decode_header=>1);
|
||||||
|
|
||||||
|
#diag explain $header;
|
||||||
|
#diag explain $data;
|
||||||
|
}
|
34
t/jws_no_key.t
Normal file
34
t/jws_no_key.t
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Test::More;
|
||||||
|
|
||||||
|
plan tests => 2;
|
||||||
|
|
||||||
|
use Crypt::JWT qw(encode_jwt decode_jwt);
|
||||||
|
|
||||||
|
my $jws =
|
||||||
|
'eyJqd2siOnsiZSI6IkFRQUIiLCJuIjoieVFJdnpEU3h2a2EzQTNhVFYzS2Yza29PeElWMjNqZGlaa1BkOU8xb3RsN0JYLWZJS2dEYk00QnBHSkxZLUhrTG5aZUxpcXgwSFpKaF94U09IVXhWNnVpLUpIU00yZkFrTnEzMHd4QzMycDZmVDk2b3RuT3ZsTEhPTVVpNEZwUFR0NDVFQmcyemlqRXRfRWNFM3g0OFJjT2ZQVGk3SDBmWnhBdXVYcmJrYmU1SHFqczVxVWp2bDFKWUdKdTA1TlItdnE2NUwyUC1oOFA5eUJBT1pRZjhRMVhBSGg1RlFQd08tQjZ3T1p6aTNjeTEtRUhXZkhpWXpxeTMxWU01ZmxIaFZ4QndWRmUyMUlINEh3WWp2SE5KMURFaEl2R2FSQTBWc09ZNlFqVUxPS19XTVlQVnExc211TmdEZThlZ1V4RnV2R2N4aWJ4NTUydHJkSHVBaWFUVGlRIiwia3R5IjoiUlNBIn0sImFsZyI6IlJTMjU2Iiwibm9uY2UiOm51bGx9.eyJjb250YWN0IjpbIm1haWx0bzpmQGcudGxkIl0sInJlc291cmNlIjoibmV3LXJlZyJ9.wrY6y0kvA3qgR38ZuAA471ygN9fmSHdfWDIayjkBKGmeGbn0f30_LQBC9FiFDFgFJ8Owyy3bOkPWvHx7yhRnP5XnEYdzNtKy4t2LyKq_JSEVQf6p1zycsVaxVLCmZ6ZbRidxIFLhbkcmu2uc4BEVGQQEj3UesccIv-AS2JCQFqK5ca-HQeaLEMntXOz5p7DYZtauYjHuXQ60i25mClm51jScJfP-wk7yYnnohGYKDinwiYlH4Nw8p4yElzWL1dI-U8fiFoxnduGaflPIZ80hkk0p7delrZt3RvmaDdu4cLJ16TgrMw_nMZfbAK0IJXByAsbej78HwIAchdzHyRPmgA';
|
||||||
|
|
||||||
|
my ( $header, $payload ) = decode_jwt( token => $jws, decode_header => 1 );
|
||||||
|
|
||||||
|
is_deeply(
|
||||||
|
$header,
|
||||||
|
{
|
||||||
|
'alg' => 'RS256',
|
||||||
|
'jwk' => {
|
||||||
|
'e' => 'AQAB',
|
||||||
|
'kty' => 'RSA',
|
||||||
|
'n' =>
|
||||||
|
'yQIvzDSxvka3A3aTV3Kf3koOxIV23jdiZkPd9O1otl7BX-fIKgDbM4BpGJLY-HkLnZeLiqx0HZJh_xSOHUxV6ui-JHSM2fAkNq30wxC32p6fT96otnOvlLHOMUi4FpPTt45EBg2zijEt_EcE3x48RcOfPTi7H0fZxAuuXrbkbe5Hqjs5qUjvl1JYGJu05NR-vq65L2P-h8P9yBAOZQf8Q1XAHh5FQPwO-B6wOZzi3cy1-EHWfHiYzqy31YM5flHhVxBwVFe21IH4HwYjvHNJ1DEhIvGaRA0VsOY6QjULOK_WMYPVq1smuNgDe8egUxFuvGcxibx552trdHuAiaTTiQ'
|
||||||
|
},
|
||||||
|
'nonce' => undef
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
is_deeply(
|
||||||
|
$payload,
|
||||||
|
{
|
||||||
|
'contact' => ['mailto:f@g.tld'],
|
||||||
|
'resource' => 'new-reg'
|
||||||
|
}
|
||||||
|
);
|
505
t/jwt_decode_tv.t
Normal file
505
t/jwt_decode_tv.t
Normal file
@ -0,0 +1,505 @@
|
|||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Test::More;
|
||||||
|
|
||||||
|
use Crypt::JWT qw(decode_jwt);
|
||||||
|
use Crypt::Misc qw(encode_b64u);
|
||||||
|
|
||||||
|
my $key = "a0a2abd8-6162-41c3-83d6-1cf559b46afc";
|
||||||
|
|
||||||
|
my $aes128Key = join '', map { chr($_) } (194,164,235,6,138,248,171,239,24,216,11,22,137,199,215,133);
|
||||||
|
my $aes192Key = join '', map { chr($_) } (139, 156, 136, 148, 17, 147, 27, 233, 145, 80, 115, 197, 223, 11, 100, 221, 5, 50, 155, 226, 136, 222, 216, 14);
|
||||||
|
my $aes256Key = join '', map { chr($_) } (164,60,194,0,161,189,41,38,130,89,141,164,45,170,159,209,69,137,243,216,191,131,47,250,32,107,231,117,37,158,225,234);
|
||||||
|
my $aes384Key = join '', map { chr($_) } (185, 30, 233, 199, 32, 98, 209, 3, 114, 250, 30, 124, 207, 173, 227, 152, 243, 202, 238, 165, 227, 199, 202, 230, 218, 185, 216, 113, 13, 53, 40, 100, 100, 20, 59, 67, 88, 97, 191, 3, 161, 37, 147, 223, 149, 237, 190, 156);
|
||||||
|
my $aes512Key = join '', map { chr($_) } (238, 71, 183, 66, 57, 207, 194, 93, 82, 80, 80, 152, 92, 242, 84, 206, 194, 46, 67, 43, 231, 118, 208, 168, 156, 212, 33, 105, 27, 45, 60, 160, 232, 63, 61, 235, 68, 171, 206, 35, 152, 11, 142, 121, 174, 165, 140, 11, 172, 212, 13, 101, 13, 190, 82, 244, 109, 113, 70, 150, 251, 82, 215, 226);
|
||||||
|
|
||||||
|
my $Ecc256Public_PEM = <<'EOF';
|
||||||
|
t/jwt_decode_tv.t ...... 46/? -----BEGIN PUBLIC KEY-----
|
||||||
|
MIIBMzCB7AYHKoZIzj0CATCB4AIBATAsBgcqhkjOPQEBAiEA/////wAAAAEAAAAA
|
||||||
|
AAAAAAAAAAD///////////////8wRAQg/////wAAAAEAAAAAAAAAAAAAAAD/////
|
||||||
|
//////////wEIFrGNdiqOpPns+u9VXaYhrxlHQawzFOw9jvOPD4n0mBLBEEEaxfR
|
||||||
|
8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5RdiYwpZP40Li/hp/m47n60p8D54WK84z
|
||||||
|
V2sxXs7LtkBoN79R9QIhAP////8AAAAA//////////+85vqtpxeehPO5ysL8YyVR
|
||||||
|
AgEBA0IABARyHd86A7+qQ4DlIfKynZaFGdGLpkU3GlQwqaVD6GIJg3QIDhaWEksY
|
||||||
|
tZ9OWjNHn9a6+i/P9o5/NrdISP0VWDU=
|
||||||
|
-----END PUBLIC KEY-----
|
||||||
|
EOF
|
||||||
|
|
||||||
|
my $Ecc256Public = {
|
||||||
|
kty => "EC",
|
||||||
|
crv => "P-256",
|
||||||
|
x => encode_b64u(join '', map { chr($_) } (4, 114, 29, 223, 58, 3, 191, 170, 67, 128, 229, 33, 242, 178, 157, 150, 133, 25, 209, 139, 166, 69, 55, 26, 84, 48, 169, 165, 67, 232, 98, 9)),
|
||||||
|
y => encode_b64u(join '', map { chr($_) } (131, 116, 8, 14, 22, 150, 18, 75, 24, 181, 159, 78, 90, 51, 71, 159, 214, 186, 250, 47, 207, 246, 142, 127, 54, 183, 72, 72, 253, 21, 88, 53)),
|
||||||
|
};
|
||||||
|
my $Ecc256Private = {
|
||||||
|
kty => "EC",
|
||||||
|
crv => "P-256",
|
||||||
|
x => encode_b64u(join '', map { chr($_) } (4, 114, 29, 223, 58, 3, 191, 170, 67, 128, 229, 33, 242, 178, 157, 150, 133, 25, 209, 139, 166, 69, 55, 26, 84, 48, 169, 165, 67, 232, 98, 9)),
|
||||||
|
y => encode_b64u(join '', map { chr($_) } (131, 116, 8, 14, 22, 150, 18, 75, 24, 181, 159, 78, 90, 51, 71, 159, 214, 186, 250, 47, 207, 246, 142, 127, 54, 183, 72, 72, 253, 21, 88, 53)),
|
||||||
|
d => encode_b64u(join '', map { chr($_) } (42, 148, 231, 48, 225, 196, 166, 201, 23, 190, 229, 199, 20, 39, 226, 70, 209, 148, 29, 70, 125, 14, 174, 66, 9, 198, 80, 251, 95, 107, 98, 206)),
|
||||||
|
};
|
||||||
|
my $Ecc384Public = {
|
||||||
|
kty => "EC",
|
||||||
|
crv => "P-384",
|
||||||
|
x => encode_b64u(join '', map { chr($_) } (70, 151, 220, 179, 62, 0, 79, 232, 114, 64, 58, 75, 91, 209, 232, 128, 7, 137, 151, 42, 13, 148, 15, 133, 93, 215, 7, 3, 136, 124, 14, 101, 242, 207, 192, 69, 212, 145, 88, 59, 222, 33, 127, 46, 30, 218, 175, 79)),
|
||||||
|
y => encode_b64u(join '', map { chr($_) } (189, 202, 196, 30, 153, 53, 22, 122, 171, 4, 188, 42, 71, 2, 9, 193, 191, 17, 111, 180, 78, 6, 110, 153, 240, 147, 203, 45, 152, 236, 181, 156, 232, 223, 227, 148, 68, 148, 221, 176, 57, 149, 44, 203, 83, 85, 75, 55)),
|
||||||
|
};
|
||||||
|
my $Ecc384Private = {
|
||||||
|
kty => "EC",
|
||||||
|
crv => "P-384",
|
||||||
|
x => encode_b64u(join '', map { chr($_) } (70, 151, 220, 179, 62, 0, 79, 232, 114, 64, 58, 75, 91, 209, 232, 128, 7, 137, 151, 42, 13, 148, 15, 133, 93, 215, 7, 3, 136, 124, 14, 101, 242, 207, 192, 69, 212, 145, 88, 59, 222, 33, 127, 46, 30, 218, 175, 79)),
|
||||||
|
y => encode_b64u(join '', map { chr($_) } (189, 202, 196, 30, 153, 53, 22, 122, 171, 4, 188, 42, 71, 2, 9, 193, 191, 17, 111, 180, 78, 6, 110, 153, 240, 147, 203, 45, 152, 236, 181, 156, 232, 223, 227, 148, 68, 148, 221, 176, 57, 149, 44, 203, 83, 85, 75, 55)),
|
||||||
|
d => encode_b64u(join '', map { chr($_) } (137, 199, 183, 105, 188, 90, 128, 82, 116, 47, 161, 100, 221, 97, 208, 64, 173, 247, 9, 42, 186, 189, 181, 110, 24, 225, 254, 136, 75, 156, 242, 209, 94, 218, 58, 14, 33, 190, 15, 82, 141, 238, 207, 214, 159, 140, 247, 139)),
|
||||||
|
};
|
||||||
|
my $Ecc512Public = {
|
||||||
|
kty => "EC",
|
||||||
|
crv => "P-521",
|
||||||
|
x => encode_b64u(join '', map { chr($_) } (0, 248, 73, 203, 53, 184, 34, 69, 111, 217, 230, 255, 108, 212, 241, 229, 95, 239, 93, 131, 100, 37, 86, 152, 87, 98, 170, 43, 25, 35, 80, 137, 62, 112, 197, 113, 138, 116, 114, 55, 165, 128, 8, 139, 148, 237, 109, 121, 40, 205, 3, 61, 127, 28, 195, 58, 43, 228, 224, 228, 82, 224, 219, 148, 204, 96)),
|
||||||
|
y => encode_b64u(join '', map { chr($_) } (0, 60, 71, 97, 112, 106, 35, 121, 80, 182, 20, 167, 143, 8, 246, 108, 234, 160, 193, 10, 3, 148, 45, 11, 58, 177, 190, 172, 26, 178, 188, 240, 91, 25, 67, 79, 64, 241, 203, 65, 223, 218, 12, 227, 82, 178, 66, 160, 19, 194, 217, 172, 61, 250, 23, 78, 218, 130, 160, 105, 216, 208, 235, 124, 46, 32)),
|
||||||
|
};
|
||||||
|
my $Ecc512Private = {
|
||||||
|
kty => "EC",
|
||||||
|
crv => "P-521",
|
||||||
|
x => encode_b64u(join '', map { chr($_) } (0, 248, 73, 203, 53, 184, 34, 69, 111, 217, 230, 255, 108, 212, 241, 229, 95, 239, 93, 131, 100, 37, 86, 152, 87, 98, 170, 43, 25, 35, 80, 137, 62, 112, 197, 113, 138, 116, 114, 55, 165, 128, 8, 139, 148, 237, 109, 121, 40, 205, 3, 61, 127, 28, 195, 58, 43, 228, 224, 228, 82, 224, 219, 148, 204, 96)),
|
||||||
|
y => encode_b64u(join '', map { chr($_) } (0, 60, 71, 97, 112, 106, 35, 121, 80, 182, 20, 167, 143, 8, 246, 108, 234, 160, 193, 10, 3, 148, 45, 11, 58, 177, 190, 172, 26, 178, 188, 240, 91, 25, 67, 79, 64, 241, 203, 65, 223, 218, 12, 227, 82, 178, 66, 160, 19, 194, 217, 172, 61, 250, 23, 78, 218, 130, 160, 105, 216, 208, 235, 124, 46, 32)),
|
||||||
|
d => encode_b64u(join '', map { chr($_) } (0, 222, 129, 9, 133, 207, 123, 116, 176, 83, 95, 169, 29, 121, 160, 137, 22, 21, 176, 59, 203, 129, 62, 111, 19, 78, 14, 174, 20, 211, 56, 160, 83, 42, 74, 219, 208, 39, 231, 33, 84, 114, 71, 106, 109, 161, 116, 243, 166, 146, 252, 231, 137, 228, 99, 149, 152, 123, 201, 157, 155, 131, 181, 106, 179, 112)),
|
||||||
|
};
|
||||||
|
|
||||||
|
my $rsaPub = <<'EOF';
|
||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqFZv0pea/jn5Mo4qEUmS
|
||||||
|
tuhlulso8n1inXbEotd/zTrQp9K0RK0hf7t0K4BjKVhaiqIam4tVVQvkmYeBeYr1
|
||||||
|
MmnO/0N97dMBz/7fmvyv0hgHaBdQ5mR5u3LTlHo8tjRE7+GzZmGs6jMcyj7HbXob
|
||||||
|
DPQJZpqNy6JjliDVXxW8nWJDetxGBlqmTj1E1fr2RCsZLreDOPSDIedG1upz9Rra
|
||||||
|
ShsIDzeefOcKibcAaKeeVI3rkAU8/mOauLSXv37hlk0h6sStJb3qZQXyOUkVkjXI
|
||||||
|
khvNu/ve0v7LiLT4G/OxYGzpOQcCnimKdojzNP6GtVDaMPh+QkSJE32UCos9R3wI
|
||||||
|
2QIDAQAB
|
||||||
|
-----END PUBLIC KEY-----
|
||||||
|
EOF
|
||||||
|
|
||||||
|
my $rsaPriv = <<'EOF';
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCoVm/Sl5r+Ofky
|
||||||
|
jioRSZK26GW6WyjyfWKddsSi13/NOtCn0rRErSF/u3QrgGMpWFqKohqbi1VVC+SZ
|
||||||
|
h4F5ivUyac7/Q33t0wHP/t+a/K/SGAdoF1DmZHm7ctOUejy2NETv4bNmYazqMxzK
|
||||||
|
PsdtehsM9Almmo3LomOWINVfFbydYkN63EYGWqZOPUTV+vZEKxkut4M49IMh50bW
|
||||||
|
6nP1GtpKGwgPN5585wqJtwBop55UjeuQBTz+Y5q4tJe/fuGWTSHqxK0lveplBfI5
|
||||||
|
SRWSNciSG827+97S/suItPgb87FgbOk5BwKeKYp2iPM0/oa1UNow+H5CRIkTfZQK
|
||||||
|
iz1HfAjZAgMBAAECggEBAJSYcG9KSpQdor8gxTurYWo6LQpazAN58SIkpCFG71a/
|
||||||
|
k06BbYWt+oMhesOnumDV0F7OB4TEctf2/p0UA5PBuP3+bq3f6vqTp+buCn5qjd18
|
||||||
|
PpWA93XYvahdDS3k1VDVRQEnj9BRamz2H3TcA/i8r8I4bU/4IDDgMN5mL1OXAX8+
|
||||||
|
vt7j3YZdwsEBQk4MDrnfwQPadjDzFBxvNsDCv7DTtSNE2KY5u058DQcIimzH/ouQ
|
||||||
|
ip7qIYKGKxA2C3jIN399ngZY5QhTWGqArU/pq9WXtDkyTQ9OL23y6LVfgQSrpSKW
|
||||||
|
zjknlaShu4CcWR5r+4p+zxOf1s2sShVaB1t8Eer/xs0CgYEA0qaOkT174vRG3E/6
|
||||||
|
7gU3lgOgoT6L3pVHuu7wfrIEoxycPa5/mZVG54SgvQUofGUYEGjR0lavUAjClw9t
|
||||||
|
OzcODHX8RAxkuDntAFntBxgRM+IzAy8QzeRl/cbhgVjBTAhBcxg+3VySv5GdxFyr
|
||||||
|
QaIo8Oy/PPI1L4EFKZHmicBd3tsCgYEAzJPqCDKqaJH9TAGfzt6b4aNt9fpirEcd
|
||||||
|
pAF1bCedFfQmUZM0LG3rMtOAIhjEXgADt5GB8ZNK3BQl8BJyMmKs57oKmbVcODER
|
||||||
|
CtPqjECXXsxH+az9nzxatPvcb7imFW8OlWslwr4IIRKdEjzEYs4syQJz7k2ktqOp
|
||||||
|
YI5/UfYnw1sCgYApNaZMaZ/T3YADV646ZFDkix8gjFDmoYOf4WCxGHhpxI4YTwvt
|
||||||
|
atOtNTgQ4nJyK4DSrP7nTEgNuzj+PmlbHUElVOueEGKf280utWj2a1HqOYVLSSjb
|
||||||
|
bqQ5SnARUuC11COhtYuO2K5oxb78jDiApY2m3FnpPWUEPxRYdo+IQVbb4wKBgCZ9
|
||||||
|
JajJL3phDRDBtXlMNHOtNcDzjKDw+Eik5Zylj05UEumCEmzReVCkrhS8KCWvRwPA
|
||||||
|
Ynw6w/jH6aNTNRz5p6IpRFlK38DKqnQpDpW4iUISmPAGdekBh+dJA14ZlVWvAUVn
|
||||||
|
VUFgU1M1l0uZFzGnrJFc3sbU4Mpj3DgIVzfqYezFAoGBALEQD4oCaZfEv77H9c4S
|
||||||
|
U6xzPe8UcLgdukek5vifLCkT2+6eccTZZjgQRb1plsXbaPHQRJTZcnUmWp9+98gS
|
||||||
|
8c1vm2YFafgdkSk9Qd1oU2Fv1aOQy4VovOFzJ3CcR+2r7cbRfcpLGnintHtp9yek
|
||||||
|
02p+d5g4OChfFNDhDtnIqjvY
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
EOF
|
||||||
|
|
||||||
|
### Plaintext
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJub25lIn0.eyJoZWxsbyI6ICJ3b3JsZCJ9.";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$key, allow_none=>1) } or warn $@;
|
||||||
|
my $expected = '{"hello": "world"}';
|
||||||
|
is($json, $expected, 'Plaintext');
|
||||||
|
is($json, $expected, 'Plaintext');
|
||||||
|
}
|
||||||
|
### HS256
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJIUzI1NiIsImN0eSI6InRleHRcL3BsYWluIn0.eyJoZWxsbyI6ICJ3b3JsZCJ9.chIoYWrQMA8XL5nFz6oLDJyvgHk2KA4BrFGrKymjC8E";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$key) } or warn $@;
|
||||||
|
my $expected = '{"hello": "world"}';
|
||||||
|
is($json, $expected, 'HS256');
|
||||||
|
}
|
||||||
|
### HS384
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJIUzM4NCIsImN0eSI6InRleHRcL3BsYWluIn0.eyJoZWxsbyI6ICJ3b3JsZCJ9.McDgk0h4mRdhPM0yDUtFG_omRUwwqVS2_679Yeivj-a7l6bHs_ahWiKl1KoX_hU_";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$key) } or warn $@;
|
||||||
|
my $expected = '{"hello": "world"}';
|
||||||
|
is($json, $expected, 'HS384');
|
||||||
|
}
|
||||||
|
### HS512
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJIUzUxMiIsImN0eSI6InRleHRcL3BsYWluIn0.eyJoZWxsbyI6ICJ3b3JsZCJ9.9KirTNe8IRwFCBLjO8BZuXf3U2ZVagdsg7F9ZsvMwG3FuqY9W0vqwjzPOjLqPN-GkjPm6C3qWPnINhpr5bEDJQ";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$key) } or warn $@;
|
||||||
|
my $expected = '{"hello": "world"}';
|
||||||
|
is($json, $expected, 'HS512');
|
||||||
|
}
|
||||||
|
### RS256
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJSUzI1NiIsImN0eSI6InRleHRcL3BsYWluIn0.eyJoZWxsbyI6ICJ3b3JsZCJ9.NL_dfVpZkhNn4bZpCyMq5TmnXbT4yiyecuB6Kax_lV8Yq2dG8wLfea-T4UKnrjLOwxlbwLwuKzffWcnWv3LVAWfeBxhGTa0c4_0TX_wzLnsgLuU6s9M2GBkAIuSMHY6UTFumJlEeRBeiqZNrlqvmAzQ9ppJHfWWkW4stcgLCLMAZbTqvRSppC1SMxnvPXnZSWn_Fk_q3oGKWw6Nf0-j-aOhK0S0Lcr0PV69ZE4xBYM9PUS1MpMe2zF5J3Tqlc1VBcJ94fjDj1F7y8twmMT3H1PI9RozO-21R0SiXZ_a93fxhE_l_dj5drgOek7jUN9uBDjkXUwJPAyp9YPehrjyLdw";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>\$rsaPub) } or warn $@;
|
||||||
|
my $expected = '{"hello": "world"}';
|
||||||
|
is($json, $expected, 'RS256');
|
||||||
|
}
|
||||||
|
### RS384
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJSUzM4NCIsImN0eSI6InRleHRcL3BsYWluIn0.eyJoZWxsbyI6ICJ3b3JsZCJ9.cOPca7YEOxnXVdIi7cJqfgRMmDFPCrZG1M7WCJ23U57rAWvCTaQgEFdLjs7aeRAPY5Su_MVWV7YixcawKKYOGVG9eMmjdGiKHVoRcfjwVywGIb-nuD1IBzGesrQe7mFQrcWKtYD9FurjCY1WuI2FzGPp5YhW5Zf4TwmBvOKz6j2D1vOFfGsogzAyH4lqaMpkHpUAXddQxzu8rmFhZ54Rg4T-jMGVlsdrlAAlGA-fdRZ-V3F2PJjHQYUcyS6n1ULcy6ljEOgT5fY-_8DDLLpI8jAIdIhcHUAynuwvvnDr9bJ4xIy4olFRqcUQIHbcb5-WDeWul_cSGzTJdxDZsnDuvg";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>\$rsaPub) } or warn $@;
|
||||||
|
my $expected = '{"hello": "world"}';
|
||||||
|
is($json, $expected, 'RS384');
|
||||||
|
}
|
||||||
|
### RS512
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJSUzUxMiIsImN0eSI6InRleHRcL3BsYWluIn0.eyJoZWxsbyI6ICJ3b3JsZCJ9.KP_mwCVRIxcF6ErdrzNcXZQDFGcL-Hlyocc4tIl3tJfzSfc7rz7qOLPjHpZ6UFH1ncd5TlpRc1B_pgvY-l0BNtx_s7n_QA55X4c1oeD8csrIoXQ6A6mtvdVGoSlGu2JnP6N2aqlDmlcefKqjl_Z-8nwDMGTMkDNhHKfHlIb2_Dliwxeq8LmNMREEdvNH2XVp_ffxBjiaKv2Eqbwc6I17241GCEmjDCvnagSgjX_5uu-da2H7TK2gtPJYUo8r9nzC7uzZJ5SB8suZH0COSofsP-9wvH0FESO40evCyEBylqg3bh9M9dIzeq8_bdTiC5kG93Fal44OEY8_Zm88wB_VjQ";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>\$rsaPub) } or warn $@;
|
||||||
|
my $expected = '{"hello": "world"}';
|
||||||
|
is($json, $expected, 'RS512');
|
||||||
|
}
|
||||||
|
### ES256
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJFUzI1NiIsImN0eSI6InRleHRcL3BsYWluIn0.eyJoZWxsbyI6ICJ3b3JsZCJ9.EVnmDMlz-oi05AQzts-R3aqWvaBlwVZddWkmaaHyMx5Phb2NSLgyI0kccpgjjAyo1S5KCB3LIMPfmxCX_obMKA";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$Ecc256Public) } or warn $@;
|
||||||
|
my $expected = '{"hello": "world"}';
|
||||||
|
is($json, $expected, 'ES256');
|
||||||
|
}
|
||||||
|
### ES384
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJFUzM4NCIsImN0eSI6InRleHRcL3BsYWluIn0.eyJoZWxsbyI6ICJ3b3JsZCJ9.jVTHd9T0fIQDJLNvAq3LPpgj_npXtWb64FfEK8Sm65Nr9q2goUWASrM9jv3h-71UrP4cBpM3on3yN--o6B-Tl6bscVUfpm1swPp94f7XD9VYLEjGMjQOaozr13iBZJCY";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$Ecc384Public) } or warn $@;
|
||||||
|
my $expected = '{"hello": "world"}';
|
||||||
|
is($json, $expected, 'ES384');
|
||||||
|
}
|
||||||
|
### ES512
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJFUzUxMiIsImN0eSI6InRleHRcL3BsYWluIn0.eyJoZWxsbyI6ICJ3b3JsZCJ9.AHxJYFeTVpZmrfZsltpQKkkplmbkycQKFOFucD7hE4Sm3rCswUDi8hlSCfeYByugySYLFzogTQGk79PHP6vdl39sAUc9k2bhnv-NxRmJsN8ZxEx09qYKbc14qiNWZztLweQg0U-pU0DQ66rwJ0HikzSqgmyD1bJ6RxitJwceYLAovv0v";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$Ecc512Public) } or warn $@;
|
||||||
|
my $expected = '{"hello": "world"}';
|
||||||
|
is($json, $expected, 'ES512');
|
||||||
|
}
|
||||||
|
### PS256
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJQUzI1NiIsImN0eSI6InRleHRcL3BsYWluIn0.eyJoZWxsbyI6ICJ3b3JsZCJ9.S9xuR-IGfXEj5qsHcMtK-jcj1lezvVstw1AISp8dEQVRNgwOMZhUQnSCx9i1CA-pMucxR-lv4e7zd6h3cYCfMnyv7iuxraxNiNAgREhOT-bkBCZMNgb5t15xEtDSJ3MuBlK3YBtXyVcDDIdKH_Bwj-u363y6LuvZ8FEOGmIK5WSFi18Xjg-ihhvH1C6UzH1G82wrRbX6DyJKqrUnHAg8yzUJVP1AdgjWRt5BKpuYbXSib-MKZZkaE4q_hCb-j25xCzn8Ez8a7PO7p0fDGvZuOk_yzSfvXSavg7iE0GLuUTNv3nQ_xW-rfbrpYeyXNtstoK3JPFpdtORTyH1iIh7VVA";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>\$rsaPub) } or warn $@;
|
||||||
|
my $expected = '{"hello": "world"}';
|
||||||
|
is($json, $expected, 'PS256');
|
||||||
|
}
|
||||||
|
### PS384
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJQUzM4NCIsImN0eSI6InRleHRcL3BsYWluIn0.eyJoZWxsbyI6ICJ3b3JsZCJ9.EKqVLw6nLGNt1h7KNFZbzkKhf788VBYCfnigYc0dBZBa64MrfbIFHtJuFgIGkCVSDYH-qs-i4w9ke6mD8mxTZFniMgzFXXaCFIrv6QZeMbKh6VYtSEPp7l0B1zMZiQw6egZbZ6a8VBkCRipuZggSlUTg5tHMMTj_jNVxxlY4uUwXlz7vakpbqgXe19pCDJrzEoXE0cNKV13eRCNA1tXOHx0dFL7Jm9NUq7blvhJ8iTw1jMFzK8bV6g6L7GclHBMoJ3MIvRp71m6idir-QeW1KCUfVtBs3HRn3a822LW02vGqopSkaGdRzQZOI28136AMeW4679UXE852srA2v3mWHQ";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>\$rsaPub) } or warn $@;
|
||||||
|
my $expected = '{"hello": "world"}';
|
||||||
|
is($json, $expected, 'PS384');
|
||||||
|
}
|
||||||
|
### PS512
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJQUzUxMiIsImN0eSI6InRleHRcL3BsYWluIn0.eyJoZWxsbyI6ICJ3b3JsZCJ9.IvbnmxhKvM70C0n0grkF807wOQLyPOBwJOee-p7JHCQcSstNeml3Owdyw9C3HGHzOdK9db51yAkjJ2TCojxqHW4OR5Apna8tvafYgD2femn1V3GdkGj6ZvYdV3q4ldnmahVeO36vHYy5P0zFcEGU1_j3S3DwGmhw2ktZ4p5fLZ2up2qwhzlOjbtsQpWywHj7cLdeA32MLId9MTAPVGUHIZHw_W0xwjJRS6TgxD9vPQQnP70MY-q_2pVAhfRCM_pauPYO1XH5ldizrTvVr27q_-Uqtw-wV-UDUnyWYQUDDiMTpLBoX1EEXmsbvUGx0OH3yWEaNINoCsepgZvTKbiEQQ";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>\$rsaPub) } or warn $@;
|
||||||
|
my $expected = '{"hello": "world"}';
|
||||||
|
is($json, $expected, 'PS512');
|
||||||
|
}
|
||||||
|
### RSA_OAEP_A128CBC_HS256
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhDQkMtSFMyNTYifQ.dgIoddBRTBLi8b6fwjaIU5uUP_J-6jL5AtIvoNZDwN0JSmsXkm9SIFz7kQfwavBz_PPG6h0yId55YVFnCqrB5qCIbifmBQPEcB5acKCybHuoHhEBCnQpqxVtHLXZ0dUyd6Xs5h9ymgbbZMjpAoCUK7si90m4O5BCSdedZNQvdXWQW599CRftFVVe_mZOcgABuNIDMfIwyxmi2DVR5c2bSA0ji2Sy27SE_X0lCVHqrAwI-8Rlz1WTWLI6bhRh2jsUPK-6958E4fsXOWsTOp9fW97eW85InZPniv8B5HSG_D0NALhu5AIMsNt-ENeR0sefcphZGUzfyFoxK7EMpY7gAQ.jNw5xfYCvwHvviSuUFYpfw.0_Rvs5cA_QKSVMGbPr5ntFrd_BQhTql-hB9fzLhndAy9vLeHBLtv-bXeZatw4QJIufnpsSnXmRYjKqvWVCp-x-AKpPWzkaj6fvsQ8Mns1kWw5XZr-8SJrbT72LOnRBcTd4qjOYXEJZad8uIwQHDFkkmpm4d7FQ6PhW0-1gOS8FGuYjUupYDQX2ia-4jzqWisv2bE-mKn65q5wy_dT0w04rF-Mk_USyOG5d09kne3ZBv42stpS_xyDS3euVtPuxhQT5TzfPpBkG3CNwwm_HvTTg.E2opVK9nQXPXJbDKb06FBg";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>\$rsaPriv) } or warn $@;
|
||||||
|
my $expected = '{"exp":1391196668,"sub":"alice","nbf":1391196068,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"03ac026e-55aa-4475-a806-f09e83048922","iat":1391196068}';
|
||||||
|
is($json, $expected, 'RSA_OAEP_A128CBC_HS256');
|
||||||
|
}
|
||||||
|
### RSA_OAEP_A128CBC_HS256_Compressed
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJSU0EtT0FFUCIsInppcCI6IkRFRiIsImVuYyI6IkExMjhDQkMtSFMyNTYifQ.nXSS9jDwE0dXkcGI7UquZBhn2nsB2P8u-YSWEuTAgEeuV54qNU4SlE76bToI1z4LUuABHmZOv9S24xkF45b7Mrap_Fu4JXH8euXrQgKQb9o_HL5FvE8m4zk5Ow13MKGPvHvWKOaNEBFriwYIfPi6QBYrpuqn0BaANc_aMyInV0Fn7e8EAgVmvoagmy7Hxic2sPUeLEIlRCDSGa82mpiGusjo7VMJxymkhnMdKufpGPh4wod7pvgb-jDWasUHpsUkHqSKZxlrDQxcy1-Pu1G37TAnImlWPa9NU7500IXc-W07IJccXhR3qhA5QaIyBbmHY0j1Dn3808oSFOYSF85A9w.uwbZhK-8iNzcjvKRb1a2Ig.jxj1GfH9Ndu1y0b7NRz_yfmjrvX2rXQczyK9ZJGWTWfeNPGR_PZdJmddiam15Qtz7R-pzIeyR4_qQoMzOISkq6fDEvEWVZdHnnTUHQzCoGX1dZoG9jXEwfAk2G1vXYT2vynEQZ72xk0V_OBtKhpIAUEFsXwCUeLAAgjFNY4OGWZl_Kmv9RTGhnePZfVbrbwg.WuV64jlV03OZm99qHMP9wQ";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>\$rsaPriv) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392963710,"sub":"alice","nbf":1392963110,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"9fa7a38a-28fd-421c-825c-8fab3bbf3fb4","iat":1392963110}';
|
||||||
|
is($json, $expected, 'RSA_OAEP_A128CBC_HS256_Compressed');
|
||||||
|
}
|
||||||
|
### RSA_OAEP_A256CBC_HS512
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZDQkMtSFM1MTIifQ.gCLatpLEIHdwqXGNQ6pI2azteXmksiGvHZoXaFmGjvN6T71ky5Ov8DHmXyaFdxWVPxiPAf6RDpJlokSR34e1W9ey0m9xWELJ_hH_bEoH4s7-wI74edS06i35let0YvCubl3eIemuQNkaJEqoEaHx8sLZ-SsoRxi7tRAIABl4f_THC8CDLw7SXrVcp_b6xRtB9oSI2_y_vSAZXOTZPJBw_t4jwZLnsOUbBXXGKAGIpG0rrL8qMt1KwRW_79qQie2U1kDclD7EVMQ-ji5upayxaXOMLkPqfISgvyGKyaLs-8e_aRyVKbMpkCZNWaLnSAA6aJHynNsnuM8O4iEN-wRXmw.r2SOQ2k_YqZRpoIB6wSbqA.DeYxdBzfRiiJeAm8H58SO8NJCa4yg3beciqZRGiAqQDrFYdp9q1RHuNrd0UY7DfzBChW5Gp37FqMA3eRpZ_ERbMiYMSgBtqJgUTKWyXGYItThpg92-1Nm7LN_Sp16UOSBHMJmbXeS30NMEfudgk3qUzE2Qmec7msk3X3ylbgn8EIwSIeVpGcEi6OWFCX1lTIRm1bqV2JDxY3gbWUB2H2YVtgL7AaioMttBM8Mm5plDY1pTHXZzgSBrTCtqtmysCothzGkRRzuHDzeaWYbznkVg.Hpk41zlPhLX4UQvb_lbCLZ0zAhOI8A0dA-V31KFGs6A";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>\$rsaPriv) } or warn $@;
|
||||||
|
my $expected = '{"exp":1391196668,"sub":"alice","nbf":1391196068,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"19539b79-e5cf-4f99-a66e-00a980e1b0a9","iat":1391196068}';
|
||||||
|
is($json, $expected, 'RSA_OAEP_A256CBC_HS512');
|
||||||
|
}
|
||||||
|
### RSA_OAEP_A192CBC_HS384
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExOTJDQkMtSFMzODQifQ.BZ8MgMgby05auOw-Gb4ii-fgcRWAlCHd6pMZNFafle6BAT1accRGUsMGRzJRETUFFqoy3rzfdSdFcqgc7lmUQUXrVei6XCRei5VZJo1YlzIPN9rEig3sSJ99hg1mrXh3ezFX_JczTn7xEaRRzdatnkSvWBMMmbMWVjqlpkXSOr7P7x2Ctf-GQwXOKEVUrRFwe2D0qXC0ynWKrm7mkV-tlRHJf5NRdWLT5Tmxka8OJZ0W1MyJKNEemEMt1dThcnedPMBjb8y0IwPZ8Aiam87fWdqk20MDknNyxRoC_epBFZFaWFpZ383mKI2Ev-EqO2lCnFOkSvwcNmhnlOPXHJ40qQ.1aAvdZ8g580VUE55RqRBVw.IkoVJF73DSzi-ebiErrCAtpWPepbFZS6DX0S9Ka85aRfgmLQRQxBucxm48MixkRJ5QYCPGmtXRPyiQQE9zT1aA5Js6BoV8U2JK44HWga4cNkyUUr0Wpu0uz6GEBU620i9DmJasTb4iA3iTMboCpdrCTlzhJrYhSYc09Jo0WJRM83LjorxRjpUmLGqR4SgV1WYFKaben4iSqOVPThzQc7HEGrkbycZRNKj-BAkll7qRtN_1e5k83W9Wlf5taAWwSXMF2VL6XqR0bZXpPcpLi_vw.kePqK6KpRWohWEpSg8vfeCd0PQAqBmjW";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>\$rsaPriv) } or warn $@;
|
||||||
|
my $expected = '{"exp":1391196668,"sub":"alice","nbf":1391196068,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"59f54c91-5224-4484-9c3a-e57b87b6f212","iat":1391196068}';
|
||||||
|
is($json, $expected, 'RSA_OAEP_A192CBC_HS384');
|
||||||
|
}
|
||||||
|
### RSA_OAEP_256_A128CBC_HS256
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.bje66yTjMUpyGzbt3QvPNOmCmUPowgEmoBHXw-pByhST2VBSs0_67JKDymKW0VpmQC5Qb7ZLC6nNG8YW5pxTZDOeTQLodhAvzoNAsrx4M2R_N58ZVqBPLKTq7FKi1NNd8oJ80dwWbOJ13dkLH68SlhOK5bhqKFgtbzalnglL2kq8Fki1GkN4YyFnS8-chC-mlrS5bJrPSHUF7oAsG_flL_e9-KzYqYTQgGCB3GYSo_pgalsp2rUO3Oz2Pfe9IEJNlX7R9wOT1nTT0UUg-lSzQ2oOaXNvNyaPgEa76mJ1nk7ZQq7ZNix1m8snjk0Vizd8EOFCSRyOGcp4mHMn7-s00Q.tMFMCdFNQXbhEnwE6mP_XQ.E_O_ZBtJ8P0FvhKOV_W98oxIySDgdd0up0c8FAjo-3OVZ_6XMEQYFDKVG_Zc3zkbaz1Z2hmc7D7M28RbhRdya3yJN6Hcv1KuXeZ9ociI7o739Ni_bPvv8xCmGxlASS5AF7N4JR7XjrWL-SYKGNL1p0XNTlPo3B3qYqgAY6jFNvlcjWupim-pQbWKNqPbO2KmSCtUzyKE5oHjsomH0hnQs0_DXv3cgQ_ZFLFZBc1tC4AjQ8QZex5kWg5BmlJDM5F_jD7QRhb7B1u4Mi563-AKVA.0lraw3IXMM6wPqUZVYA8pg";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>\$rsaPriv) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}';
|
||||||
|
is($json, $expected, 'RSA_OAEP_256_A128CBC_HS256');
|
||||||
|
}
|
||||||
|
### RSA_OAEP_256_A192CBC_HS384
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMTkyQ0JDLUhTMzg0In0.COuKvozBVi2vkEPpFdx0HTMpU9tmpP1lLngbmGn8RVphY-vjhVaduv8D_Ay_1j8LuMz4tgP98xWtbJkTyhxY1kBwXe0CgqFUOSJ1mTEPRkKSXpdFR7rT1Pv68qug2yKaXT_qcviyBerIcUVFbXBmtiYAosYO4kaPSOE1IvLadFOrMkxdZv6QiiCROzWgJNCCMgNQZGRoPhqLe3wrcxi86DhNO7Bpqq_yeNVyHdU_qObMuMVZIWWEQIDhiU4nE8WGJLG_NtKElc_nQwbmclL_YYgTiHsIAKWZCdj0nwfLe5mwJQN4r7pjakiUVzCbNNgI1-iBH1vJD5VCPxgWldzfYA.7cDs4wzbNDt1Kq40Q5ae4w.u1bR6ChVd90QkFIp3H6IkOCIMwf5aIKsQOvqgFangRLrDjctl5qO5jTHr1o1GwBQvAkRmaGSE7fRIwWB_l-Ayx2c2WDFOkVXFSR_D23GrWaLMLbugPItQd2Mny6H4QOzO3O0EK_Qm7frqwKQI3og72SB8DUqzEaKsrz7HR2z_qMa2CEEApxai_R6NIlAdMUbYvOfZx262MWFGrITBDmma-Mnqiz9WJUv2wexfwjROaaS4wXfkGy5B6ltESifpZZk5NerExR3GA6yX7cFqJc4pQ.FKcbLyB9eP1UXmxyliTu1_GQrnS-JtAB";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>\$rsaPriv) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}';
|
||||||
|
is($json, $expected, 'RSA_OAEP_256_A192CBC_HS384');
|
||||||
|
}
|
||||||
|
### RSA_OAEP_256_A256CBC_HS512
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIn0.Pt1q6MNdaiVWhMnY7r6DVpkYQmzyIjhb0cj10LowP_FgMu1dOQVuNwhK14MO1ki1y1Pvxouct9wwmb5gE7jNJBy6vU-FrrY62WNr_hKL3Cq2030LlJwauv1XQrEE-GCw1srxOAsw6LNT14v4f0qjeW46mIHNX4CZMEO9ntwojWsHTNsh4Qk6SU1QlS3WbbVl7gjjfqTP54j2ZwZM38s7Cs4pSAChP04UbW6Uhrm65JSi0lyg25OBXIxMEt1z9WY8lnjuh3iL_WttnFn9lf5fUuuR2N70HwANz2mxH3CxjO0ygXJtV-FhFzz3HqI2-ELrve4Igj_2f2_S6OrRTWRucA.er5K9Gk0wp3wF_sq7ib7BQ.L80B9FGSjUbEblpJ6tuiaq6NAsW89YQGD0awxtE-irKN65PT8nndBd0hlel8RRThXRF0kiYYor2GpgvVVaoOzSQcwL-aDgNO7BeRsaOL5ku2NlyT1erbg_8jEVG5BFMM0-jCb4kD0jBKWYCGoB7qs_QQxZ394H5GPwG68vlizKEa8PoaNIM0at5oFT7EHPdmGmwQyQCHR43e6uN4k28PWNxjN9Ndo5lvlYnxnAyDGVDu8lCjozaA_ZTrEPS-UBb6lOEW39CXdwVk1MgvyQfswQ.yuDMf_77Wr9Er3FG1_0FwHXJTOVQPjzBwGoKEg81mQo";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>\$rsaPriv) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}';
|
||||||
|
is($json, $expected, 'RSA_OAEP_256_A256CBC_HS512');
|
||||||
|
}
|
||||||
|
### RSA_1_5_A128CBC_HS256
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.bx_4TL7gh14IeM3EClP3iVfY9pbT81pflXd1lEZOVPJR6PaewRFXWmiJcaqH9fcU9IjGGQ19BS-UPtpErenL5kw7KORFgIBm4hObCYxLoAadMy8A-qQeOWyjnxbE0mbQIdoFI4nGK5qWTEQUWZCMwosvyeHLqEZDzr9CNLAAFTujvsZJJ7NLTkA0cTUzz64b57uSvMTaOK6j7Ap9ZaAgF2uaqBdZ1NzqofLeU4XYCG8pWc5Qd-Ri_1KsksjaDHk12ZU4vKIJWJ-puEnpXBLoHuko92BnN8_LXx4sfDdK7wRiXk0LU_iwoT5zb1ro7KaM0hcfidWoz95vfhPhACIsXQ.YcVAPLJ061gvPpVB-zMm4A.PveUBLejLzMjA4tViHTRXbYnxMHFu8W2ECwj9b6sF2u2azi0TbxxMhs65j-t3qm-8EKBJM7LKIlkAtQ1XBeZl4zuTeMFxsQ0VShQfwlN2r8dPFgUzb4f_MzBuFFYfP5hBs-jugm89l2ZTj8oAOOSpAlC7uTmwha3dNaDOzlJniqAl_729q5EvSjaYXMtaET9wSTNSDfMUVFcMERbB50VOhc134JDUVPTuriD0rd4tQm8Do8obFKtFeZ5l3jT73-f1tPZwZ6CmFVxUMh6gSdY5A.tR8bNx9WErquthpWZBeMaw";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>\$rsaPriv) } or warn $@;
|
||||||
|
my $expected = '{"exp":1391196668,"sub":"alice","nbf":1391196068,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"3814fff3-db66-45d9-a29a-d2cc2407bdcf","iat":1391196068}';
|
||||||
|
is($json, $expected, 'RSA_1_5_A128CBC_HS256');
|
||||||
|
}
|
||||||
|
### RSA_1_5_A192CBC_HS384
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTkyQ0JDLUhTMzg0In0.ApUpt1SGilnXuqvFSHdTV0K9QKSf0P6wEEOTrAqWMwyEOLlyb6VR8o6fdd4wXMTkkL5Bp9BH1x0oibTrVwVa50rxbPDlRJQe0yvBm0w02nkzl3Tt4fE3sGjEXGgI8w8ZxSVAN0EkaXLqzsG1rQ631ptzqyNzg9BWfy53cHhuzh9w00ZOXZtNc7GFBQ1LRvhK1EyLS2_my8KD091KwsjvXC-_J0eOp2W8NkycP_jCIrUzAOSwz--NZyRXt9V2o609HGItKajHplbE1PJVShaXO84MdJl3X6ef8ZXz7mCP3dRlsYfK-tlnFVeEKwC1Oy_zdFsdiY4j41Mj3usvG2j7xQ.GY4Em2zkSGMZsDLNr9pnDw.GZYJSpeQHmOtx34dk4WxEPCnt7l8R5oLKd3IyoMYbjZrWRtomyTufOKfiOVT-nY9ad0Vs5w5Imr2ysy6DnkAFoOnINV_Bzq1hQU4oFfUd_9bFfHZvGuW9H-NTUVBLDhok6NHosSBaY8xLdwHL_GiztRsX_rU4I88bmWBIFiu8T_IRskrX_kSKQ_iGpIJiDy5psIxY4il9dPihLJhcI_JqysW0pIMHB9ij_JSrCnVPs4ngXBHrQoxeDv3HiHFTGXziZ8k79LZ9LywanzC0-ZC5Q.1cmUwl7MnFl__CS9Y__a8t5aVyI9IKOY";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>\$rsaPriv) } or warn $@;
|
||||||
|
my $expected = '{"exp":1391196668,"sub":"alice","nbf":1391196068,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"c9d44ff8-ff1e-4490-8454-941e45766152","iat":1391196068}';
|
||||||
|
is($json, $expected, 'RSA_1_5_A192CBC_HS384');
|
||||||
|
}
|
||||||
|
### RSA_1_5_A256CBC_HS512
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIn0.GVXwkd5rfqffr4ue26IGHXuiV6r-rQa9OQ4B1LtodsTpWfraOLyhyHYseEKpXV4aSMWWN0q2HS0myj73BuGsDMP-xiIM04QxWD7dbP2OticXzktcHHhMFUx0OK_IOmc21qshTqbb0yKWizMnCuVosQqw2tg_up2sgjqIyiwzpgvC5_l9ddxnTBV334LF_nXTnL22vqrUO92rH_3YmoJ6khHUYVSXhd0fXTKqwm9liULW43prDWkex0N8a8MfgdaFPq0rGw4gRA8HvS7aFn3xCeKAO9Q_q-g32DCDwbfqYhvGZCbS49ObwfPD-fKaFS94VFSMb_Cy-WalZwrIz-aWkQ.zh6hViRORvk4b-2io1vUSA.Us26-89QEOWb85TsOZJpH6QB5_GR3wZo49rR38X1daG_kmyfzIUQQ12wBwmxFwHluNvqStVj4YUIvPgC4oZEh1L-r3Tm81Q2PctdMrwl9fRDR6uH1Hqfx-K25vEhlk_A60s060wezUa5eSttjwEHGTY0FpoQvyOmdfmnOdtW_LLyRWoRzmGocD_N4z6BxK-cVTbbTvAYVbWaZNW_eEMLL4qAnKNAhXJzAtUTqJQIn0Fbh3EE3j827hKrtcRbrwqr1BmoOtaQdYUO4VZKIJ7SNw.Zkt6yXlSu9BdknCr32uyu7uH6HVwGFOV48xc4Z7wF9Y";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>\$rsaPriv) } or warn $@;
|
||||||
|
my $expected = '{"exp":1391196668,"sub":"alice","nbf":1391196068,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"7efcdbc6-b2b5-4480-985d-bdf741b376bb","iat":1391196068}';
|
||||||
|
is($json, $expected, 'RSA_1_5_A256CBC_HS512');
|
||||||
|
}
|
||||||
|
### RSA_OAEP_A128GCM
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhHQ00ifQ.Izae78a1L2Z0ai_aYbvVbWjiZwz3DTlD27c4Jh44SZAz7T_w7GHiWGuxa4CYPq4Ul_9i5qpdUK1WJOTxlL8C-TXbWzxgwhs-DdmkRBmI5JWozc6RIYz2ddYBIPDTpOSbg_nwVzCUkqId6PwATSPiYjLY0ZwsSung1JGuSKU5WHzdCLh8cXKFdSNo4PA6xxuIFqDWNeshSvbUhK-xPL_ySPSLGtMfzUocPi--SDnc867a92WZpnCwLbpAqlGcj1u-nrpXjlTdECbZbPH5mggnIU8Xrzi6OIRTf2RPOxk2nYcW-KkzsERSUUmoIStaTnnq6MzRLKdF-eOolVaPEB94tQ.dBju23LfGAmbhKQl.l-hxA-_Jj9X-Kbq6W_7XNSxeeDaZc_YFoHRIBclWn2ebd_1qbZ3Td8aPsxBwe4Mc0KP7JdTnDXH53ajtdo2CQaPIaxNh-ffZkUZCi7o-tM_SRyt1MkUnoxQ5ib4i5lzJNEJyklf7lHQhjUhUa2FKTS1KJvLo0uChw5Gb-Y_7S_BUfOzTDCFQR4XFbpd7ngCWww4skpHEulhBhSr66RGog4wwac_ucfSTKeKxZw0UhHBIZFIAju4zcoN8Abh23JHh0VETiA.FFFvIyv5vq_cE1xIPYn6Wg";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>\$rsaPriv) } or warn $@;
|
||||||
|
my $expected = '{"exp":1391705293,"sub":"alice","nbf":1391704693,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"2f3b5379-a851-4202-ac9a-85baae41459e","iat":1391704693}';
|
||||||
|
is($json, $expected, 'RSA_OAEP_A128GCM');
|
||||||
|
}
|
||||||
|
### RSA_OAEP_A192GCM
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExOTJHQ00ifQ.QUBq_S563qAz9KA1oQDPLQ8Upfaf5XWeLLo6w_BpZRPUUshnSsf5GYmxeakuVCGywv2mKR7pEd0EzzA4vL1l3tc8woftrA_jDSU9lQp_Icuwqg9pzBswv7ofKegK7ch7KhOuWGaeFz6mdoUESHhdEPmhVZwz7ryrKWj_TlL-Cr7UG8MpHWV_bvohdtLReTSqfbUbcT_iSY4Nid7RHca__0dmSWgEM2Sydmesv8KJzuoyI6xgGLCaw_p46GuZ4XhM88scV7doV7f3mEv7AYTDMJz4Q5_8lz_gIDDyloTx3-tC9a9KlDVSC3XkPppfQwwjSt-yWhh9SZmsPIpC_K6ubA.pUr3CK_0cTGIODJx.TBD3RZ2nJGNSns_iOOvruxC2Dr-4SsClKIwPXIt8zIjKtKub8o1lFqaRwlBfyciPNMiCqqocWR8zwyNNDFBIAUYJMBW6SPuFzJv8mrjlV_aRsfFmYjpw9U3-n0u-noYHT5U1FXy6feUY907AIqbcEKkHF0TfjEXLfuKVvJHNjaqS84-UFZqmxN0U2szRCo8-k6omS32pRDwTGgl1Co9yXSBUAXtGoi02uqOKpAFbtxfD8_6P41N7-HK86l94m5x1uNCViQ.9xj6WjYwh4OCUr-GKl7_yQ";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>\$rsaPriv) } or warn $@;
|
||||||
|
my $expected = '{"exp":1391710436,"sub":"alice","nbf":1391709836,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"6b646d08-2871-4e0d-bfa8-48a9e1bd6de5","iat":1391709836}';
|
||||||
|
is($json, $expected, 'RSA_OAEP_A192GCM');
|
||||||
|
}
|
||||||
|
### RSA_OAEP_A256GCM
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.M7PuAabTBMnrudthuZNYWfwkXlv1KVxsSYjpaRmuStqybglofWHK37wWWcF5JMYmJfRjswXlGf-iHjw2aSfGpmTJBdUYYbchMtn2TKnjU03piFaqWN3D9384nq_4NJeRkwwe7uYD3iGDxeemJpJLjqpXj5cXgK5Xd93TtJ-QB9hIpXtyDqOlLdoooMWKG8Y9cIBdbwCza57KzOm1S5and_3E4IgijvtRlqENzeLesH3jT3P2310nDEn60j7eqHCeXWR8lUKMZudVCY7f9lkGpotKQeJpxDG1Sd2EG_GiOK5DwpR_1CimkE3c4y1qUoFM10Pjzf7IqZJL1HBAMHcXxQ.9a8lpyZcMoPi2qJb.TKWSdvz395ZfzsjDV6r9mhMdU5XZ14pCcna5EkoA1wmolDAth9qqYAPJErbfZfUAptbUFDitLlsnnnIIhej-N_42XIQnu14Wz0G-sizAn78jKjf145ckDYt63qaX4SxBW6-SQqSCYV4Nz6t0DUBMLK9UcYsVQ2e3Ur5YvxcnTeFM9FqgUiEz9IiNlsJXwZ1HN-LTp0412YCELxoxUu3Bg7R_GWHx2iUliBnRN4WcvRhYMApI_o3qAoK4StTgCQJu-laPdg.Rztnz6rBQ2aSlDHKORI5AA";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>\$rsaPriv) } or warn $@;
|
||||||
|
my $expected = '{"exp":1391710647,"sub":"alice","nbf":1391710047,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"0b0f3b1b-8f36-4ee2-b463-54263b4af8b7","iat":1391710047}';
|
||||||
|
is($json, $expected, 'RSA_OAEP_A256GCM');
|
||||||
|
}
|
||||||
|
### RSA1_5_A128GCM
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4R0NNIn0.FojyyzygtFOyNBjzqTRfr9HVHPrvtqbVUt9sXSuU59ZhLlzk7FrirryFnFGtj8YC9lx-IX156Ro9rBaJTCU_dfERd05DhPMffT40rdcDiLxfCLOY0E2PfsMyGQPhI6YtNBtf_sQjXWEBC59zH_VoswFAUstkvXY9eVVecoM-W9HFlIxwUXMVpEPtS96xZX5LMksDgJ9sYDTNa6EQOA0hfzw07fD_FFJShcueqJuoJjILYbad-AHbpnLTV4oTbFTYjskRxpEYQr9plFZsT4_xKiCU89slT9EFhmuaiUI_-NGdX-kNDyQZj2Vtid4LSOVv5kGxyygThuQb6wjr1AGe1g.O92pf8iqwlBIQmXA.YdGjkN7lzeKYIv743XlPRYTd3x4VA0xwa5WVoGf1hiHlhQuXGEg4Jv3elk4JoFJzgVuMMQMex8fpFFL3t5I4H9bH18pbrEo7wLXvGOsP971cuOOaXPxhX6qClkwx5qkWhcTbO_2AuJxzIaU9qBwtwWaxJm9axofAPYgYbdaMZkU4F5sFdaFY8IOe94wUA1Ocn_gxC_DYp9IEAyZut0j5RImmthPgiRO_0pK9OvusE_Xg3iGfdxu70x0KpoItuNwlEf0LUA.uP5jOGMxtDUiT6E3ubucBw";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>\$rsaPriv) } or warn $@;
|
||||||
|
my $expected = '{"exp":1391711317,"sub":"alice","nbf":1391710717,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"cadf3d33-a109-4829-a869-94a4bfbb4cbf","iat":1391710717}';
|
||||||
|
is($json, $expected, 'RSA1_5_A128GCM');
|
||||||
|
}
|
||||||
|
### RSA1_5_A192GCM
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTkyR0NNIn0.f-g3EVuoVHRWRnhuQTa0s4V6kKWdCZrQadK27AcmjYNuBAQL26GpiZe1fBggGdREMjXejQjykDd0GGGzdk3avSLlfOuAHb6D5TJE6DB67v_Fjn29_ky-9L6fZmLUKlHOYbE5H2cnkUk9eI3mT0_VJLfhkh3uOAvs1h31NGBmVcQJOLoyH9fa6nTt1kddubsnkHLMfjS_fm4lKOBv2e1S4fosWYEVM9ylpfL-wSYJYrDtEsy_r9lTv19OmrcjtQoqoF9kZ9bMm7jOcZWiG00nw5Zbo2nze_y-bSngJcA7jIutf0zmFxa9GsIVvseQbqcLYZoiACMqEp0HgPg2xfBPmw.mzEicVwcsRKNKrHs.jW2bcx2pxSK2a8NNZSydArUd3JgRQl_dX5N8i5REBeR7WmtgL9aHXyrGqy9rl-iUb6LZMjMFG4tDqOetJjS48OUzMgvLZH3tui_oL8m9ZHWG-yl079uJZSIWU-icHuWzSjbc4ExPu1IXCcTnBGIjid5PM3HAfmWtVP5Pv0q6qeuvzMXvLG7YcZtuS5dTSu1pZTW7O5BEaxy9AvC0-xr0SlTdEEVCT_kZIprhIT7XiGnuMUztx83AxuO-FYXZeL5iXMW8hQ.H9qkfReSyqgVkiVt53fh-Q";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>\$rsaPriv) } or warn $@;
|
||||||
|
my $expected = '{"exp":1391711482,"sub":"alice","nbf":1391710882,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"7488a8fc-345a-42c2-971e-a286c14fc5af","iat":1391710882}';
|
||||||
|
is($json, $expected, 'RSA1_5_A192GCM');
|
||||||
|
}
|
||||||
|
### RSA1_5_A256GCM
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMjU2R0NNIn0.arMHtbGJv2mi7COD9WTz_FzUPJ8Jq1qUTMc5C3IKGD7RNeV1oiv1AgCPiChTuu-UGA56iGJXbFAE7x2jSFK_foKvRvZxyCKz6Siy18seHoz1iw8gU2A_mMG7IEPVcA8MmbMVawFTXoMdLBeW9CsV_102wmZFeh2S74f80XogE63Nd3VjE3LaSbatnXQxIaD0Meq9ZqrKUFZS5SY-FyKqWrdjH82MZP8lrBLDTkTXx4bkfoZForimE1oIEykanpv-tnAlQNFlqRPJsGy-HtcEoHQ7E1Xkqxg9kULmF4TeqiyQ0HBfXXBbm3pQ43GUPmbFJW-l7W6vDAc9-41BCNChQw.kryfKm1U6NobSiyI.kMQXbCKGdeh_vqj6J7wQ1qP48q4VQv5zGZIJp0FgIlk0Lrv9XP4ExlgYlPb24mr1W43d2rY0OJ9fDgPnoTk_cQ6kpXL3nSBo82yBTBA_g6UyIJ4b1PIOpJv_RANA-b8TwQwGtg0eMr_5il4QQWfB_AxnvCe9CDyTkNo7befER3706xilqm6aHdryZx3Hk6C9hbrSe0xW96uor1Js2b-UWRcCJDFQK5Ux9IAHy2Utqsqv7qDq0Ai5pVQOMjyq3iKmUuOOEg.rqSGPBypVniu58fdHswm7g";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>\$rsaPriv) } or warn $@;
|
||||||
|
my $expected = '{"exp":1391711482,"sub":"alice","nbf":1391710882,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"77a31aed-f546-4b1d-ba77-9455a2e0a3d5","iat":1391710882}';
|
||||||
|
is($json, $expected, 'RSA1_5_A256GCM');
|
||||||
|
}
|
||||||
|
### RSA1_5_A256GCM_DEFLATE
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJSU0ExXzUiLCJ6aXAiOiJERUYiLCJlbmMiOiJBMjU2R0NNIn0.imMUAOkYe54TzNknmrUkWOtjgGlbSivDyFRbvebC1rT9ixxQOTN-bCGiLwyEoPLdkroEvvR1cf_abR_afZIfWsk6Om09aar9JQkA7KMNoTRBQnn7X7BX_agpZuhRzPo_gQDXA0fll10j9OdUTcXd7oSw6FVb4non2qyO2ZvwT1UANY3SbQchlQrXnQpjQluR1tkxWXo-5p3o9MQEIqyypOQyGKIIXJlBtcUkWz0PHHsqJ3OdZus7dbwajv5GpHmLfT8Q2aPZN5QX1zv4h2y8vD6RYn6evLCc7e7Gp1z7C5WOZXDA6hyYQiL3Y92zzxVVD5E7nt94WSktxjM-y65TQw.g3FCuDmLISjam69Q.PrMnFDnuYNkLvmR8QmmEu6NB9N6ecJy6gMSR1fYEkZLz2jMtxN-OTaudX901_SWCX_dDFgpmOPziQRJ1IYOiySZ3N0FFyWxemJgHjVOZaPpu5ZSTH7JYoH5CLBpD1H9VMX5vC5SUH7hWgLZ_NCgVs0eZt_3_AyUObVAInNNTH_pNjhdjV8xuCCE.rDEvIPtM1fNjpDvD62x2PA";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>\$rsaPriv) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392994388,"sub":"alice","nbf":1392993788,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"81b338eb-346e-4b04-a618-d3cbb2d64ec6","iat":1392993788}';
|
||||||
|
is($json, $expected, 'RSA1_5_A256GCM_DEFLATE');
|
||||||
|
}
|
||||||
|
### DIR_A128GCM
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4R0NNIn0..yVi-LdQQngN0C5WS.1McwSmhZzAtmmLp9y-OdnJwaJFo1nj_4ashmzl2LhubGf0Jl1OTEVJzsHZb7bkup7cGTkuxh6Vfv10ljHsjWf_URXoxP3stQqQeViVcuPV0y2Q_WHYzTNGZpmHGe-hM6gjDhyZyvu3yeXGFSvfPQmp9pWVOgDjI4RC0MQ83rzzn-rRdnZkznWjbmOPxwPrR72Qng0BISsEwbkPn4oO8-vlHkVmPpuDTaYzCT2ZR5K9JnIU8d8QdxEAGb7-s8GEJ1yqtd_w._umbK59DAKA3O89h15VoKQ";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$aes128Key) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392548520,"sub":"alice","nbf":1392547920,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"0e659a67-1cd3-438b-8888-217e72951ec9","iat":1392547920}';
|
||||||
|
is($json, $expected, 'DIR_A128GCM');
|
||||||
|
}
|
||||||
|
### DIR_A192GCM
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJkaXIiLCJlbmMiOiJBMTkyR0NNIn0..YW2WB0afVronbgSz.tfk1VADGjBnViYD7He5mbhxpbogoT1cmhKiDKzzoBV2AxfsgJ2Eq-vtEqPi9eY9H52FLLtht26rc5fPz9ZKOUH2hYeFdaRyKYXlpEnUR2cCT9_3TYcaFhpYBH4HCa59NruKlJHMBqM2ssWZLSEblFX9srUHFtu2OQz2ydMy1fr8ABDTdVYgaqyBoYRGykTkEsgayEyfAMz9u095N2J0JTCB5Q0IiXNdBzBSxZXG-i9f5HFEb6IliaTwFTNFnhDL66O4rsg._dh02z25W7HA6b1XiFVpUw";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$aes192Key) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392552631,"sub":"alice","nbf":1392552031,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"a3fea096-2e96-4d8b-b7cd-070e08b533fb","iat":1392552031}';
|
||||||
|
is($json, $expected, 'DIR_A192GCM');
|
||||||
|
}
|
||||||
|
### DIR_A256GCM
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0..Fmz3PLVfv-ySl4IJ.LMZpXMDoBIll5yuEs81Bws2-iUUaBSpucJPL-GtDKXkPhFpJmES2T136Vd8xzvp-3JW-fvpRZtlhluqGHjywPctol71Zuz9uFQjuejIU4axA_XiAy-BadbRUm1-25FRT30WtrrxKltSkulmIS5N-Nsi_zmCz5xicB1ZnzneRXGaXY4B444_IHxGBIS_wdurPAN0OEGw4xIi2DAD1Ikc99a90L7rUZfbHNg_iTBr-OshZqDbR6C5KhmMgk5KqDJEN8Ik-Yw.Jbk8ZmO901fqECYVPKOAzg";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$aes256Key) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392552841,"sub":"alice","nbf":1392552241,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"efdfc02f-945e-4e1f-85a6-9f240f6cf153","iat":1392552241}';
|
||||||
|
is($json, $expected, 'DIR_A256GCM');
|
||||||
|
}
|
||||||
|
### DIR_A128CBC_HS256
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..3lClLoerWhxIc811QXDLbg.iFd5MNk2eWDlW3hbq7vTFLPJlC0Od_MSyWGakEn5kfYbbPk7BM_SxUMptwcvDnZ5uBKwwPAYOsHIm5IjZ79LKZul9ZnOtJONRvxWLeS9WZiX4CghOLZL7dLypKn-mB22xsmSUbtizMuNSdgJwUCxEmms7vYOpL0Che-0_YrOu3NmBCLBiZzdWVtSSvYw6Ltzbch4OAaX2ye_IIemJoU1VnrdW0y-AjPgnAUA-GY7CAKJ70leS1LyjTW8H_ecB4sDCkLpxNOUsWZs3DN0vxxSQw.bxrZkcOeBgFAo3t0585ZdQ";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$aes256Key) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}';
|
||||||
|
is($json, $expected, 'DIR_A128CBC_HS256');
|
||||||
|
}
|
||||||
|
### ECDH_ES_A128CBC_HS256
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJFQ0RILUVTIiwiZW5jIjoiQTEyOENCQy1IUzI1NiIsImVwayI6eyJrdHkiOiJFQyIsIngiOiItVk1LTG5NeW9IVHRGUlpGNnFXNndkRm5BN21KQkdiNzk4V3FVMFV3QVhZIiwieSI6ImhQQWNReTgzVS01Qjl1U21xbnNXcFZzbHVoZGJSZE1nbnZ0cGdmNVhXTjgiLCJjcnYiOiJQLTI1NiJ9fQ..UA3N2j-TbYKKD361AxlXUA.XxFur_nY1GauVp5W_KO2DEHfof5s7kUwvOgghiNNNmnB4Vxj5j8VRS8vMOb51nYy2wqmBb2gBf1IHDcKZdACkCOMqMIcpBvhyqbuKiZPLHiilwSgVV6ubIV88X0vK0C8ZPe5lEyRudbgFjdlTnf8TmsvuAsdtPn9dXwDjUR23bD2ocp8UGAV0lKqKzpAw528vTfD0gwMG8gt_op8yZAxqqLLljMuZdTnjofAfsW2Rq3Z6GyLUlxR51DAUlQKi6UpsKMJoXTrm1Jw8sXBHpsRqA.UHCYOtnqk4SfhAknCnymaQ";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$Ecc256Private) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}';
|
||||||
|
is($json, $expected, 'ECDH_ES_A128CBC_HS256');
|
||||||
|
}
|
||||||
|
### ECDH_ES_A128GCM
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJFQ0RILUVTIiwiZW5jIjoiQTEyOEdDTSIsImVwayI6eyJrdHkiOiJFQyIsIngiOiJPbDdqSWk4SDFpRTFrcnZRTmFQeGp5LXEtY3pQME40RVdPM1I3NTg0aEdVIiwieSI6Ik1kU2V1OVNudWtwOWxLZGU5clVuYmp4a3ozbV9kTWpqQXc5NFd3Q0xaa3MiLCJjcnYiOiJQLTI1NiJ9fQ..E4XwpWZ2kO-Vg0xb.lP5LWPlabtmzS-m2EPGhlPGgllLNhI5OF2nAbbV9tVvtCckKpt358IQNRk-W8-JNL9SsLdWmVUMplrw-GO-KA2qwxEeh_8-muYCw3qfdhVVhLnOF-kL4mW9a00Xls_6nIZponGrqpHCwRQM5aSr365kqTNpfOnXgJTKG2459nqv8n4oSfmwV2iRUBlXEgTO-1Tvrq9doDwZCCHj__JKvbuPfyRBp5T7d-QJio0XRF1TO4QY36GtKMXWR264lS7g-T1xxtA.vFevA9zsyOnNA5RZanKqHA";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$Ecc256Private) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}';
|
||||||
|
is($json, $expected, 'ECDH_ES_A128GCM');
|
||||||
|
}
|
||||||
|
### ECDH_ES_A192GCM
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJFQ0RILUVTIiwiZW5jIjoiQTE5MkdDTSIsImVwayI6eyJrdHkiOiJFQyIsIngiOiJQVHdUWWdjQ0s2aVBuNUQ4TmUwSGlERG16b0NpRWFpSnNIN0MycENFcHNjIiwieSI6IjdnVDJPVGstcTlFa2tqOE41OEd4LUo2X2NrcXRnWWVPMERyZ3E2SWFPWGMiLCJjcnYiOiJQLTI1NiJ9fQ..sK58aW_aYOIeXcd_.KCHYLUKgSpRSe01ACTS-C1dtc1vxSiqqw5GdWjTkdtdsrpG_GOLzDrPWv_W4C0GsI5yrfZNlsujAs6qCgeE9Ypk7Nh26pEAVFqYYHeGO8VIqB_KmA_Y00q6Ae0JrV9MhOx7Lk45iGZoVYHeTw8vXS_q8GIZMVPE8hiIwPZApCb11yAoupP6ZCCE7wDwGZUJebWagPssElcwe0bQDg-xhvDjCobGe-GxS-cSJD_pwATJDnwYnIkHhr8xQ5DG_A6hrKB1JJA.hYUguhKj7zVxpVAAO-mZ4Q";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$Ecc256Private) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}';
|
||||||
|
is($json, $expected, 'ECDH_ES_A192GCM');
|
||||||
|
}
|
||||||
|
### ECDH_ES_A256GCM
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJFQ0RILUVTIiwiZW5jIjoiQTI1NkdDTSIsImVwayI6eyJrdHkiOiJFQyIsIngiOiJtRXhiTWVyTW14X28zZkdtQ3RNNEx3UlBOc0RsRzRNREw1NXdqYzd3cEw4IiwieSI6IkMtLXZ1VlR2OFhYUzlxT1ptX1pZcU54WG4tYkRXRkxDZUwxTTZRS2pJYlkiLCJjcnYiOiJQLTI1NiJ9fQ..SmI8J0ZwK1CXwamA.VnsYpxxR9-XbS7FAPSngPNkCslTBca2otiYzZVGbDrM4fJueODgMkRSkEKXzxeYRf2zU_0cwY1sUvgU00lou2SKwcoSgT8kON0sdoxxwn-atxyUoxISd75NW_WQdaAG2WysWweYMyB5eu7XuRDUwQ4iKCLmmtD2fdQ5w3RcNOxMIC_zyr3NwrQO7zarIbdcDg0iCgc7Szflbc1EYMadtiEmU_YN5veXOvJtASEOyjRbX-U9HyQnF-Z78dTf_j_gAe-TwjQ.H10mHRYClUt8j2LulRKAog";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$Ecc256Private) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}';
|
||||||
|
is($json, $expected, 'ECDH_ES_A256GCM');
|
||||||
|
}
|
||||||
|
### ECDH_ES_A128KW_A128GCM
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJFQ0RILUVTK0ExMjhLVyIsImVuYyI6IkExMjhHQ00iLCJlcGsiOnsia3R5IjoiRUMiLCJ4IjoiNnlzVWZVd09vVWxENUpGZG9qUHFXeFd3ZkJ3b2ttWmpOVmxJRFFrcG1PMCIsInkiOiJKZVpia19QazIybWowVFUwcG5uQjNVaUwySzJJcVl6Tk0xVVRPZS1KY3dZIiwiY3J2IjoiUC0yNTYifX0.e1n3YTorJJ-H7eWby-pfGWzVx0aDScCT.VQLnlbAD3N1O-k-S.mJzcAMoxUMQxXIHFGcVjuEVKw70lC6rNbcGqverZBkycPQ2EDgZCiqMgJenHuecvG_YqShi50uZYVyYS4TTrGh1Bj4jP6iFZ8Ksww3hW_jYzKQbp9CdbmOL1f0f25RKwUq61AraXGoJ1Lrs8IM96tvTjKTGpDkNMJ8xN4kVcRcrM5fjTIx973XKo2_nbuCpn-BlAhB6wzYuw_EFsqis8-8cssPENLuGA-n-xX66akqdhycfh5RiqrTPYUnk5ss1Fo_LWWA.l0-CNccSNLTgVdGW1CZr9w";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$Ecc256Private) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}';
|
||||||
|
is($json, $expected, 'ECDH_ES_A128KW_A128GCM');
|
||||||
|
}
|
||||||
|
### ECDH_ES_A192KW_A192GCM
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJFQ0RILUVTK0ExOTJLVyIsImVuYyI6IkExOTJHQ00iLCJlcGsiOnsia3R5IjoiRUMiLCJ4IjoiWWExQlYxSVl4RW9oVWNJclhDQU9PektlMFBPTXVCUElmMmRSNmtNZVN0cyIsInkiOiJTVXVqY3NsMHZmaUpuMXVfNFk1OU1NSjV1RkdjVVpFQlRXUHU1NEFSZ0VFIiwiY3J2IjoiUC0yNTYifX0.wpPrUGVTDsthaBTuToj5D51O-bbSJCBwmDq7lK4l8dE.23LmX0dUuB4bmjx8.At6v2XSn05ew5N_mW2q4nIcHmn3unnuJkceT-cADSfHS5TGHq5_dytb8OZRDvAA_6U__MDWONdpNAAucG_2UljX8LOfRkfDIncg-KcN_8UOyTNuCSwg3wHtPfDuVR4VPgyKysxGU0L6yIvXs8as8GzLQ4vA4YbCbMjsefQQLWjJbTELON5ASVj9cwTSTydO1N0xXDWjKiPXaiwHiBAnEE-ESeTvhqc1yfS6lel1PMuoZc0teV6XX21lZfFuVJtnKWQIcTQ.AoCKtceXULOU0y74O5qJFA";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$Ecc256Private) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}';
|
||||||
|
is($json, $expected, 'ECDH_ES_A192KW_A192GCM');
|
||||||
|
}
|
||||||
|
### ECDH_ES_A256KW_A256GCM
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJFQ0RILUVTK0EyNTZLVyIsImVuYyI6IkEyNTZHQ00iLCJlcGsiOnsia3R5IjoiRUMiLCJ4IjoiQU5UZy1LOFlBVXVPazBtUW1aTERQVWlPcVZFUFBrLVBmNmtSdG42Y0IycyIsInkiOiJsSmk3UExFRGU2WndxSjQ2alpyLUZtUHp5c3dGa3BkSVU3WlUzNHQ4RURzIiwiY3J2IjoiUC0yNTYifX0.Iqp3w3xo12wCqyNV_8wNk3m2tHKpBmv66XARscHeLtZS-2FslAbfDQ.UClH3759Eeo3V8xi.Y4UQpFk-MF5Xkec035WVmMI7O_eXw5V2gF3Ov4CnnV2cac6pul598NytO_rFI-hff4dOLwz2jgD_H6nQ_fL70STi0Wrsar2s7F8TMvolcaOhOfIbzX4O0vTdrNENiM9ug7044M-lvsOX8rK3Q3usfxSfOa4g9I_7r6b6SRMbjGqz3mtp8slMZhPZraBAxsxU97qfutBNA8ohCPGHasu7INHQnE_Cf0bZtE8mSpijq4AK3FGp91ekpoowH4627l7fBnupVg.hdEFZ6RBabaq7Xzb1SOaCg";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$Ecc256Private) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}';
|
||||||
|
is($json, $expected, 'ECDH_ES_A256KW_A256GCM');
|
||||||
|
}
|
||||||
|
### PBSE2_HS256_A128KW_A128CBC_HS256
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwicDJjIjo4MTkyLCJwMnMiOiJiMFlFVmxMemtaNW9UUjBMIn0.dhPAhJ9kmaEbP-02VtEoPOF2QSEYM5085V6zYt1U1qIlVNRcHTGDgQ.4QAAq0dVQT41dQKDG7dhRA.H9MgJmesbU1ow6GCa0lEMwv8A_sHvgaWKkaMcdoj_z6O8LaMSgquxA-G85R_5hEILnHUnFllNJ48oJY7VmAJw0BQW73dMnn58u161S6Ftq7Mjxxq7bcksWvFTVtG5RsqqYSol5BZz5xm8Fcj-y5BMYMvrsCyQhYdeGEHkAvwzRdvZ8pGMsU2XPzl6GqxGjjuRh2vApAeNrj6MwKuD-k6AR0MH46EiNkVCmMkd2w8CNAXjJe9z97zky93xbxlOLozaC3NBRO2Q4bmdGdRg5y4Ew.xNqRi0ouQd7uo5UrPraedg";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>"top secret") } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}';
|
||||||
|
is($json, $expected, 'PBSE2_HS256_A128KW_A128CBC_HS256');
|
||||||
|
}
|
||||||
|
### PBSE2_HS256_A128KW_A256GCM
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJlbmMiOiJBMjU2R0NNIiwicDJjIjo4MTkyLCJwMnMiOiJqVVozY0NEX2hMZ3pQVHVfIn0.cgEZLTNOoGgDJXhRj0Ca0DL_HTY2xRKzVpoRnOf_Yuxm6IsQJgf0NA.7sAUk5_ryTMO_hLB.y7arc1aQP1--WUwlUsti4SiW6O2nrmGviTYznPjw9KD9Tu4E4QQO3RCU1uo59qNF3jJ5Mgku5OXV8bJHlouMouUfZbEb2cHgH9GLwY7hbCuYfGBIEyZw6qnHCgLGatO59akKaVDa8fqPo5--V_q0T5Z3xWm7UpK8RHaR8z3kuSBEXI1JH-dgj1EikG0yHSxVkFiInrlNLGzhI-cMTSD5xfLlmhmTzqbdpNp947AQ7pix2IvkQdvdgCo3bbSQVUsSJrLZSg.cO4fVMmdniwtEikHv55cqQ";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>"top secret") } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}';
|
||||||
|
is($json, $expected, 'PBSE2_HS256_A128KW_A256GCM');
|
||||||
|
}
|
||||||
|
### PBSE2_HS384_A192KW_A192CBC_HS384
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJQQkVTMi1IUzM4NCtBMTkyS1ciLCJlbmMiOiJBMTkyQ0JDLUhTMzg0IiwicDJjIjo4MTkyLCJwMnMiOiIxZEdaODBpQTBqb3lGTzFqIn0.iElgf12HbQWt3enumKP_j3WDxGLfbwSePHYAbYEb_w3himk0swcdiTPo1Jm8MU7le7L_Z8rU2Uk.7LoW9-g7U8c3GNAYO3Z5Jw.guSjXuYN9deq6XIsbkbxAptU9Lp1jf9k11QdhsvjfUvaZRXKrWiE9vg3jEJRJnmF7lZq07cp2Ou8PztMg6R_ygT7gadmP_IYdgQwXD6HGQs__uzvFnqtjWALiwLWuL0V0INrKxBn3CivJ5Hg26nJwLACdVuO_k-fNTaphbox-nKefndS4UXaoe3hEuCzHFPgFivMlND4aZJb8pU8sQbGA29gx5U9qNBmWYOXwV2diYQ2q2SfUEbXoMV7uZyvfQ2juTcyqZBVnEfIYGf_8esALQ.QrgRr0TIlJDFkq2YWNXcoFoMpg4yMC6r";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>"top secret") } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}';
|
||||||
|
is($json, $expected, 'PBSE2_HS384_A192KW_A192CBC_HS384');
|
||||||
|
}
|
||||||
|
### PBSE2_HS512_A256KW_A256CBC_HS512
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJQQkVTMi1IUzUxMitBMjU2S1ciLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwicDJjIjo4MTkyLCJwMnMiOiJCUlkxQ1M3VXNpaTZJNzhkIn0.ovjAL7yRnB_XdJbK8lAaUDRZ-CyVeio8f4pnqOt1FPj1PoQAdEX3S5x6DlzR8aqN_WR5LUwdqDSyUDYhSurnmq8VLfzd3AEe.YAjH6g_zekXJIlPN4Ooo5Q.tutaltxpeVyayXZ9pQovGXTWTf_GWWvtu25Jeg9jgoH0sUX9KCnL00A69e4GJR6EMxalmWsa45AItffbwjUBmwdyklC4ZbTgaovVRs-UwqsZFBO2fpEb7qLajjwra7o4OegzgXDD0jhrKrUusvRWGBvenvumb5euibUxmIfBUcVF1JbdfYxx7ztFeS-QKJpDkE00zyEkViq-QxfrMVl5p7LGmTz8hMrFL3LXLokypZSDgFBfsUzChJf3mlYzxiGaGUqhs7NksQJDoUYf6prPow.XwRVfVTTPogO74RnxZD_9Mse26fTSehna1pbWy4VHfY";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>"top secret") } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}';
|
||||||
|
is($json, $expected, 'PBSE2_HS512_A256KW_A256CBC_HS512');
|
||||||
|
}
|
||||||
|
### A128GCMKW_A128CBC_HS256
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJBMTI4R0NNS1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiaXYiOiJ1SDVxVThlN2JVZXhGYWh3IiwidGFnIjoiamdxc2czdHoyUGo0QmhEWU1xTnBrdyJ9.peAzKiVO3_w2tAlSzRZdqqQpnUSpgPDHi_xgTd6VzP4.o8bhvYO_UTkrsxQmm__nIg.MSmgetpjXHWMs0TyuGgmWd-msfbQ7oVWC4WuCJcfAsbhLU9kLDLrd0naL5f_UkWBaM04bfcc31K4FRN20IiUxcHzLnMR-lY-HkvRFWYdur-kLWw1UXjIlPOb0nqCuyd2FRpxMdSfFnYr5Us9T45cF7DdK8p4iA7KqPToMHWBsvAcET_ycMIoERqJrBuiJzh-j7UtDzH6KtUfgD4tzZAm3iM6HWT2lq25Pqsu4qf19LYXxZaMIiFwFKboeexkJ5E0hc7P-wIeknzFJaZhkb5P4g.dTQAed1znLHX4cO-VDgxeA";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$aes128Key) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}';
|
||||||
|
is($json, $expected, 'A128GCMKW_A128CBC_HS256');
|
||||||
|
}
|
||||||
|
### A128GCMKW_A256CBC_HS512
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJBMTI4R0NNS1ciLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiaXYiOiI5bUwxR1YzUUZIWGtVbEdUIiwidGFnIjoiU0xrTDVpdmhncy1HNjRBTS01bTBxdyJ9.S3_MudWEzKWCp8RRxIG5p6H2YOtMDCkOXXKM9J8J4lMX5N2CcUqsKkDQ4TE1rG7gD5qYgHsb8AiQFLbhjgDeAA.WiOHBPlws9hImQr6bZ8h5Q.jN9UbuvhTiS6uJi1jc0TsvpheXqHs8vdJzKOUVgFmVHZ_OG4vSNRLx408vSoAgSeqsRmj8C8i9Yi2R6kpgtRXZ-Rw7EQEjZ65kg2uwZuve1ObqK-uBm3UzDmcT_Jh6myp9Df1m28ng8ojfrY_JUz6oE5yEcJdlm7H8ahipJyznWOjFigOqhaiXosjW0kbGGpYE-njD5OX22vR5k0RxHlMCDAH2ONR69kaWbLQvDg7y4yMFSxi3ILUFSVz4uXo6qlb8RVCqMUWzlGho-5Cy9OPA.XQ0UmHH5btv14_km6CIlIUwzOFj-rQUYyEzF9VY0r70";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$aes128Key) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}';
|
||||||
|
is($json, $expected, 'A128GCMKW_A256CBC_HS512');
|
||||||
|
}
|
||||||
|
### A192GCMKW_A192CBC_HS384
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJBMTkyR0NNS1ciLCJlbmMiOiJBMTkyQ0JDLUhTMzg0IiwiaXYiOiJzRHRLdnRzZVk2UkFuU2twIiwidGFnIjoiZDFDS3dKWnlXSnlvcW5HTUFwbmR6dyJ9.2L9u7vV0P8bZddbkCKKe6_C5JTLf8wRZC8xzEe4gvmcGoF2K5AledhcqT6mIlaPx.1JY51r77jimrvKxts9EroQ.922BMD0HOscwZxn4pmYTRgV7oshegQ1dooU9njhonPcp46XbegdfsgeZAACVFpCc_CoY_XzOsM5trH1Z30QUDc7IGJmC0NKuPdK2KkrYQPXJAe6nuZMembGsyRkOHahtj7sew-ULZn9y0ztbntPqm5I9O716mv1Cu6_5_mBYu36c_VVd6jlzueUWun09yLDJLFuf5jRXDrqRrY4t6XIcqti8LF-QLowU_pa5DvRV_KzCtD_S8HvzJ217_TI9Y1qaApgvWr_BxDrfTXxO2xaZ2Q.0fnvCkg_ChWuf8F3KY8KUgbdIzifb_JT";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$aes192Key) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}';
|
||||||
|
is($json, $expected, 'A192GCMKW_A192CBC_HS384');
|
||||||
|
}
|
||||||
|
### A256GCMKW_A256CBC_HS512
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJBMjU2R0NNS1ciLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiaXYiOiJvUV9xbDNJUHNibEVPaDBXIiwidGFnIjoieTllMEFfY1hZMnNDZ24tamxsNl9TdyJ9.K5BxtxcV0simNM-69RvjZuNBjxaavDVnBzP7EFXSjbWZi3NjZFoTcFljcu2TuzR_F9zdjjBbohEgaf4kUMVZfg.881rEerOD33OLCHKdTWDjQ.LvrzsNicH2slBjwERYFu-Fr4Bus2lcLTdFazEpsHc_0QH4NJ2tGrJJjByli6OaFOwtdWONEu_3Ax8xvEXWHc0WMhYKxaVLZI1HQwE0NnWyqfF9mtOkUCCXn9ljvSGSDQY5VUcupVUT6WQxAkaNe6mJ6qkJOxE4pBpiMskO0luW5PkPexk2N3bJVz-GwzMp3xVT6wtFimThucZm2V71594NPCKIkA0HvtBkW0gW0M66pSTfQTHkU0Uvm7WfRvr6TXpiuKntJUe7RX5pXFXbfN2g.aW8OWGfHFI5zTGfFyKuqeLFT5o0tleSYbpCb7kAv1Bs";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$aes256Key) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}';
|
||||||
|
is($json, $expected, 'A256GCMKW_A256CBC_HS512');
|
||||||
|
}
|
||||||
|
### A128KW_A128CBC_HS256
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.DPRoUHQ3Ac8duyD32nUNH3eNUKzUIMYgEdf5GwJ8rW4MYQdl2PCIHA.B1dR6t93aUPcFC1c1aUjeA.lHPKTK0ehgzq70_Ihdh-svI2icUa9usgqP8sF5j50fsQAGizITZpTTXKOKd9-GSEVmJo07551hq9xscZj4vXsDEx-z-akxg0nlL5fFE24km7l4T3LfAeG17gmrMcJuLP55mFUg-F98j9duV2UCyKJPXP6RwOQ5X17VNw29c4k-_AxYM0EjTv3Fww1o3AGuVa07PfpLWE-GdJeJF9RLgaP_6Pua_mdVJud77bYXOsVxsweVtKIaBeLswMUUSU6PoC5oYURP_ybW76GOCjmgXpjA.avU8f5LK_tbJOyKW6-fRnw";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$aes128Key) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}';
|
||||||
|
is($json, $expected, 'A128KW_A128CBC_HS256');
|
||||||
|
}
|
||||||
|
### A192KW_A192CBC_HS384
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJBMTkyS1ciLCJlbmMiOiJBMTkyQ0JDLUhTMzg0In0.OLwgc7EaQdvsf54GfU69qH143C79H_eETvM_yGBgJzEB5367k9tbw6qW4TlQ56GMj__5QDJBvAg.BvYY_v4_dxxsK4M8A0T_TA.V0jBe7o-OahMkqGDgWW0Lxq1eTKPJYix7hjKmmqaKlhdVcnT0cdOU0ahdg82Ls-Vg_NaWKas8MhahHspz18Gx2abDSwLIKbU0jcaf0LxWZkEuMmFJs5dodq0ZqQeaEldDsHe9De_V_TQwPFkcMOPYqWhx2XEb13bmFTPtxNST18Cwm_j263Y_Ouz2YNyC4uZENZDWeOXfJLy7c8jt_ToOvXEVpXj7oZN7Ik1S9bGAenTcvUDORP-gdFdJ3stLe9FmKulOlb94Y-KvP_meyIZ7Q.XPPqS5YVJu2utJcAIRTUxlBHlECGRaM5";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$aes192Key) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}';
|
||||||
|
is($json, $expected, 'A192KW_A192CBC_HS384');
|
||||||
|
}
|
||||||
|
### A256KW_A256CBC_HS512
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJBMjU2S1ciLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIn0.91z9VM1VLIA_qyTbqeInFoit7c4PWVuQ5mHcDyNsfofDGXS1qUDdPCWRdLC8ybvJflqHej7SCjEUMxuzOtPOUOgo-8rcdeHi.rsx7FYNTunzditC8XTMJXg.k88BLb0qs8g0UnKjSq9rs2PcrhpafEaUEX2kT-wMdmviZ9UEJrECoQY7MmJgCyQYO30hnnay2psJcr_yaDhV-NpctBZ793Xf9tztLZZndIjz5omV9HjcFgheQZj4g1tbNcRLwxod5uYz-OLrKORzeROEM-wkLgHVEqs90wN98NAiyhGyVMw7CXVX5NdU2KFUacbflkJc5AcaiAZYAts1t9bo2877XLYSO1qBoI5k5QKv6ijjM8I03Uyr3H0p0tdF6EB-cdYNcxq68GvA5CTkOw.DBtOuSJTFu5AAIdcgymUR-JflpwfcXJ2AnZU8LNB3UA";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$aes256Key) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}';
|
||||||
|
is($json, $expected, 'A256KW_A256CBC_HS512');
|
||||||
|
}
|
||||||
|
### DIR_A192CBC_HS384
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJkaXIiLCJlbmMiOiJBMTkyQ0JDLUhTMzg0In0..fX42Nn8ABHClA0UfbpkX_g.ClZzxQIzg40GpTETaLejGNhCN0mqSM1BNCIU5NldeF-hGS7_u_5uFsJoWK8BLCoWRtQ3cWIeaHgOa5njCftEK1AoHvechgNCQgme-fuF3f2v5DOphU-tveYzN-uvrUthS0LIrAYrwQW0c0DKcJZ-9vQmC__EzesZgUHiDB8SnoEROPTvJcsBKI4zhFT7wOgqnFS7P7_BQZj_UnbJkzTAiE5MURBBpCYR-OS3zn--QftbdGVJ2CWmwH3HuDO9-IE2IQ5cKYHnzSwu1vyME_SpZA.qd8ZGKzmOzzPhFV-Po8KgJ5jZb5xUQtU";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$aes384Key) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553372,"sub":"alice","nbf":1392552772,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"f81648e9-e9b3-4e37-a655-fcfacace0ef0","iat":1392552772}';
|
||||||
|
is($json, $expected, 'DIR_A192CBC_HS384');
|
||||||
|
}
|
||||||
|
### DIR_A256CBC_HS512
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIn0..ZD93XtD7TOa2WMbqSuaY9g.1J5BAuxNRMWaw43s7hR82gqLiaZOHBmfD3_B9k4I2VIDKzS9oEF_NS2o7UIBa6t_fWHU7vDm9lNAN4rqq7OvtCBHJpFk31dcruQHxwYKn5xNefG7YP-o6QtpyNioNWJpaSD5VRcRO5ufRrw2bu4_nOth00yJU5jjN3O3n9f-0ewrN2UXDJIbZM-NiSuEDEgOVHImQXoOtOQd0BuaDx6xTJydw_rW5-_wtiOH2k-3YGlibfOWNu51kApGarRsAhhqKIPetYf5Mgmpv1bkUo6HJw.nVpOmg3Sxri0rh6nQXaIx5X0fBtCt7Kscg6c66NugHY";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$aes512Key) } or warn $@;
|
||||||
|
my $expected = '{"exp":1392553617,"sub":"alice","nbf":1392553017,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"029ea059-b8aa-44eb-a5ad-59458de678f8","iat":1392553017}';
|
||||||
|
is($json, $expected, 'DIR_A256CBC_HS512');
|
||||||
|
}
|
||||||
|
|
||||||
|
### RS256 - BAD scalar key
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJSUzI1NiIsImN0eSI6InRleHRcL3BsYWluIn0.eyJoZWxsbyI6ICJ3b3JsZCJ9.NL_dfVpZkhNn4bZpCyMq5TmnXbT4yiyecuB6Kax_lV8Yq2dG8wLfea-T4UKnrjLOwxlbwLwuKzffWcnWv3LVAWfeBxhGTa0c4_0TX_wzLnsgLuU6s9M2GBkAIuSMHY6UTFumJlEeRBeiqZNrlqvmAzQ9ppJHfWWkW4stcgLCLMAZbTqvRSppC1SMxnvPXnZSWn_Fk_q3oGKWw6Nf0-j-aOhK0S0Lcr0PV69ZE4xBYM9PUS1MpMe2zF5J3Tqlc1VBcJ94fjDj1F7y8twmMT3H1PI9RozO-21R0SiXZ_a93fxhE_l_dj5drgOek7jUN9uBDjkXUwJPAyp9YPehrjyLdw";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$rsaPub) };
|
||||||
|
is($json, undef, 'RS256');
|
||||||
|
}
|
||||||
|
### ES256 - BAD scalar key
|
||||||
|
{
|
||||||
|
my $token = "eyJhbGciOiJFUzI1NiIsImN0eSI6InRleHRcL3BsYWluIn0.eyJoZWxsbyI6ICJ3b3JsZCJ9.EVnmDMlz-oi05AQzts-R3aqWvaBlwVZddWkmaaHyMx5Phb2NSLgyI0kccpgjjAyo1S5KCB3LIMPfmxCX_obMKA";
|
||||||
|
my $json = eval { decode_jwt(token=>$token, decode_payload=>0, key=>$Ecc256Public_PEM) };
|
||||||
|
is($json, undef, 'ES256');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
done_testing;
|
171
t/jwt_encode_decode.t
Normal file
171
t/jwt_encode_decode.t
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Test::More;
|
||||||
|
use utf8;
|
||||||
|
|
||||||
|
use Crypt::JWT qw(encode_jwt decode_jwt);
|
||||||
|
use Crypt::PK::ECC;
|
||||||
|
use Crypt::PK::RSA;
|
||||||
|
use Crypt::Misc qw(encode_b64u);
|
||||||
|
|
||||||
|
my $Ecc256Public = {
|
||||||
|
kty => "EC",
|
||||||
|
crv => "P-256",
|
||||||
|
x => encode_b64u(join '', map { chr($_) } (4, 114, 29, 223, 58, 3, 191, 170, 67, 128, 229, 33, 242, 178, 157, 150, 133, 25, 209, 139, 166, 69, 55, 26, 84, 48, 169, 165, 67, 232, 98, 9)),
|
||||||
|
y => encode_b64u(join '', map { chr($_) } (131, 116, 8, 14, 22, 150, 18, 75, 24, 181, 159, 78, 90, 51, 71, 159, 214, 186, 250, 47, 207, 246, 142, 127, 54, 183, 72, 72, 253, 21, 88, 53)),
|
||||||
|
};
|
||||||
|
my $Ecc256Private = {
|
||||||
|
kty => "EC",
|
||||||
|
crv => "P-256",
|
||||||
|
x => encode_b64u(join '', map { chr($_) } (4, 114, 29, 223, 58, 3, 191, 170, 67, 128, 229, 33, 242, 178, 157, 150, 133, 25, 209, 139, 166, 69, 55, 26, 84, 48, 169, 165, 67, 232, 98, 9)),
|
||||||
|
y => encode_b64u(join '', map { chr($_) } (131, 116, 8, 14, 22, 150, 18, 75, 24, 181, 159, 78, 90, 51, 71, 159, 214, 186, 250, 47, 207, 246, 142, 127, 54, 183, 72, 72, 253, 21, 88, 53)),
|
||||||
|
d => encode_b64u(join '', map { chr($_) } (42, 148, 231, 48, 225, 196, 166, 201, 23, 190, 229, 199, 20, 39, 226, 70, 209, 148, 29, 70, 125, 14, 174, 66, 9, 198, 80, 251, 95, 107, 98, 206)),
|
||||||
|
};
|
||||||
|
my $Ecc384Public = {
|
||||||
|
kty => "EC",
|
||||||
|
crv => "P-384",
|
||||||
|
x => encode_b64u(join '', map { chr($_) } (70, 151, 220, 179, 62, 0, 79, 232, 114, 64, 58, 75, 91, 209, 232, 128, 7, 137, 151, 42, 13, 148, 15, 133, 93, 215, 7, 3, 136, 124, 14, 101, 242, 207, 192, 69, 212, 145, 88, 59, 222, 33, 127, 46, 30, 218, 175, 79)),
|
||||||
|
y => encode_b64u(join '', map { chr($_) } (189, 202, 196, 30, 153, 53, 22, 122, 171, 4, 188, 42, 71, 2, 9, 193, 191, 17, 111, 180, 78, 6, 110, 153, 240, 147, 203, 45, 152, 236, 181, 156, 232, 223, 227, 148, 68, 148, 221, 176, 57, 149, 44, 203, 83, 85, 75, 55)),
|
||||||
|
};
|
||||||
|
my $Ecc384Private = {
|
||||||
|
kty => "EC",
|
||||||
|
crv => "P-384",
|
||||||
|
x => encode_b64u(join '', map { chr($_) } (70, 151, 220, 179, 62, 0, 79, 232, 114, 64, 58, 75, 91, 209, 232, 128, 7, 137, 151, 42, 13, 148, 15, 133, 93, 215, 7, 3, 136, 124, 14, 101, 242, 207, 192, 69, 212, 145, 88, 59, 222, 33, 127, 46, 30, 218, 175, 79)),
|
||||||
|
y => encode_b64u(join '', map { chr($_) } (189, 202, 196, 30, 153, 53, 22, 122, 171, 4, 188, 42, 71, 2, 9, 193, 191, 17, 111, 180, 78, 6, 110, 153, 240, 147, 203, 45, 152, 236, 181, 156, 232, 223, 227, 148, 68, 148, 221, 176, 57, 149, 44, 203, 83, 85, 75, 55)),
|
||||||
|
d => encode_b64u(join '', map { chr($_) } (137, 199, 183, 105, 188, 90, 128, 82, 116, 47, 161, 100, 221, 97, 208, 64, 173, 247, 9, 42, 186, 189, 181, 110, 24, 225, 254, 136, 75, 156, 242, 209, 94, 218, 58, 14, 33, 190, 15, 82, 141, 238, 207, 214, 159, 140, 247, 139)),
|
||||||
|
};
|
||||||
|
my $Ecc512Public = {
|
||||||
|
kty => "EC",
|
||||||
|
crv => "P-521",
|
||||||
|
x => encode_b64u(join '', map { chr($_) } (0, 248, 73, 203, 53, 184, 34, 69, 111, 217, 230, 255, 108, 212, 241, 229, 95, 239, 93, 131, 100, 37, 86, 152, 87, 98, 170, 43, 25, 35, 80, 137, 62, 112, 197, 113, 138, 116, 114, 55, 165, 128, 8, 139, 148, 237, 109, 121, 40, 205, 3, 61, 127, 28, 195, 58, 43, 228, 224, 228, 82, 224, 219, 148, 204, 96)),
|
||||||
|
y => encode_b64u(join '', map { chr($_) } (0, 60, 71, 97, 112, 106, 35, 121, 80, 182, 20, 167, 143, 8, 246, 108, 234, 160, 193, 10, 3, 148, 45, 11, 58, 177, 190, 172, 26, 178, 188, 240, 91, 25, 67, 79, 64, 241, 203, 65, 223, 218, 12, 227, 82, 178, 66, 160, 19, 194, 217, 172, 61, 250, 23, 78, 218, 130, 160, 105, 216, 208, 235, 124, 46, 32)),
|
||||||
|
};
|
||||||
|
my $Ecc512Private = {
|
||||||
|
kty => "EC",
|
||||||
|
crv => "P-521",
|
||||||
|
x => encode_b64u(join '', map { chr($_) } (0, 248, 73, 203, 53, 184, 34, 69, 111, 217, 230, 255, 108, 212, 241, 229, 95, 239, 93, 131, 100, 37, 86, 152, 87, 98, 170, 43, 25, 35, 80, 137, 62, 112, 197, 113, 138, 116, 114, 55, 165, 128, 8, 139, 148, 237, 109, 121, 40, 205, 3, 61, 127, 28, 195, 58, 43, 228, 224, 228, 82, 224, 219, 148, 204, 96)),
|
||||||
|
y => encode_b64u(join '', map { chr($_) } (0, 60, 71, 97, 112, 106, 35, 121, 80, 182, 20, 167, 143, 8, 246, 108, 234, 160, 193, 10, 3, 148, 45, 11, 58, 177, 190, 172, 26, 178, 188, 240, 91, 25, 67, 79, 64, 241, 203, 65, 223, 218, 12, 227, 82, 178, 66, 160, 19, 194, 217, 172, 61, 250, 23, 78, 218, 130, 160, 105, 216, 208, 235, 124, 46, 32)),
|
||||||
|
d => encode_b64u(join '', map { chr($_) } (0, 222, 129, 9, 133, 207, 123, 116, 176, 83, 95, 169, 29, 121, 160, 137, 22, 21, 176, 59, 203, 129, 62, 111, 19, 78, 14, 174, 20, 211, 56, 160, 83, 42, 74, 219, 208, 39, 231, 33, 84, 114, 71, 106, 109, 161, 116, 243, 166, 146, 252, 231, 137, 228, 99, 149, 152, 123, 201, 157, 155, 131, 181, 106, 179, 112)),
|
||||||
|
};
|
||||||
|
|
||||||
|
my $rsaPub = <<'EOF';
|
||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqFZv0pea/jn5Mo4qEUmS
|
||||||
|
tuhlulso8n1inXbEotd/zTrQp9K0RK0hf7t0K4BjKVhaiqIam4tVVQvkmYeBeYr1
|
||||||
|
MmnO/0N97dMBz/7fmvyv0hgHaBdQ5mR5u3LTlHo8tjRE7+GzZmGs6jMcyj7HbXob
|
||||||
|
DPQJZpqNy6JjliDVXxW8nWJDetxGBlqmTj1E1fr2RCsZLreDOPSDIedG1upz9Rra
|
||||||
|
ShsIDzeefOcKibcAaKeeVI3rkAU8/mOauLSXv37hlk0h6sStJb3qZQXyOUkVkjXI
|
||||||
|
khvNu/ve0v7LiLT4G/OxYGzpOQcCnimKdojzNP6GtVDaMPh+QkSJE32UCos9R3wI
|
||||||
|
2QIDAQAB
|
||||||
|
-----END PUBLIC KEY-----
|
||||||
|
EOF
|
||||||
|
|
||||||
|
my $rsaPriv = <<'EOF';
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCoVm/Sl5r+Ofky
|
||||||
|
jioRSZK26GW6WyjyfWKddsSi13/NOtCn0rRErSF/u3QrgGMpWFqKohqbi1VVC+SZ
|
||||||
|
h4F5ivUyac7/Q33t0wHP/t+a/K/SGAdoF1DmZHm7ctOUejy2NETv4bNmYazqMxzK
|
||||||
|
PsdtehsM9Almmo3LomOWINVfFbydYkN63EYGWqZOPUTV+vZEKxkut4M49IMh50bW
|
||||||
|
6nP1GtpKGwgPN5585wqJtwBop55UjeuQBTz+Y5q4tJe/fuGWTSHqxK0lveplBfI5
|
||||||
|
SRWSNciSG827+97S/suItPgb87FgbOk5BwKeKYp2iPM0/oa1UNow+H5CRIkTfZQK
|
||||||
|
iz1HfAjZAgMBAAECggEBAJSYcG9KSpQdor8gxTurYWo6LQpazAN58SIkpCFG71a/
|
||||||
|
k06BbYWt+oMhesOnumDV0F7OB4TEctf2/p0UA5PBuP3+bq3f6vqTp+buCn5qjd18
|
||||||
|
PpWA93XYvahdDS3k1VDVRQEnj9BRamz2H3TcA/i8r8I4bU/4IDDgMN5mL1OXAX8+
|
||||||
|
vt7j3YZdwsEBQk4MDrnfwQPadjDzFBxvNsDCv7DTtSNE2KY5u058DQcIimzH/ouQ
|
||||||
|
ip7qIYKGKxA2C3jIN399ngZY5QhTWGqArU/pq9WXtDkyTQ9OL23y6LVfgQSrpSKW
|
||||||
|
zjknlaShu4CcWR5r+4p+zxOf1s2sShVaB1t8Eer/xs0CgYEA0qaOkT174vRG3E/6
|
||||||
|
7gU3lgOgoT6L3pVHuu7wfrIEoxycPa5/mZVG54SgvQUofGUYEGjR0lavUAjClw9t
|
||||||
|
OzcODHX8RAxkuDntAFntBxgRM+IzAy8QzeRl/cbhgVjBTAhBcxg+3VySv5GdxFyr
|
||||||
|
QaIo8Oy/PPI1L4EFKZHmicBd3tsCgYEAzJPqCDKqaJH9TAGfzt6b4aNt9fpirEcd
|
||||||
|
pAF1bCedFfQmUZM0LG3rMtOAIhjEXgADt5GB8ZNK3BQl8BJyMmKs57oKmbVcODER
|
||||||
|
CtPqjECXXsxH+az9nzxatPvcb7imFW8OlWslwr4IIRKdEjzEYs4syQJz7k2ktqOp
|
||||||
|
YI5/UfYnw1sCgYApNaZMaZ/T3YADV646ZFDkix8gjFDmoYOf4WCxGHhpxI4YTwvt
|
||||||
|
atOtNTgQ4nJyK4DSrP7nTEgNuzj+PmlbHUElVOueEGKf280utWj2a1HqOYVLSSjb
|
||||||
|
bqQ5SnARUuC11COhtYuO2K5oxb78jDiApY2m3FnpPWUEPxRYdo+IQVbb4wKBgCZ9
|
||||||
|
JajJL3phDRDBtXlMNHOtNcDzjKDw+Eik5Zylj05UEumCEmzReVCkrhS8KCWvRwPA
|
||||||
|
Ynw6w/jH6aNTNRz5p6IpRFlK38DKqnQpDpW4iUISmPAGdekBh+dJA14ZlVWvAUVn
|
||||||
|
VUFgU1M1l0uZFzGnrJFc3sbU4Mpj3DgIVzfqYezFAoGBALEQD4oCaZfEv77H9c4S
|
||||||
|
U6xzPe8UcLgdukek5vifLCkT2+6eccTZZjgQRb1plsXbaPHQRJTZcnUmWp9+98gS
|
||||||
|
8c1vm2YFafgdkSk9Qd1oU2Fv1aOQy4VovOFzJ3CcR+2r7cbRfcpLGnintHtp9yek
|
||||||
|
02p+d5g4OChfFNDhDtnIqjvY
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
EOF
|
||||||
|
|
||||||
|
my @enclist = (qw/A128GCM A192GCM A256GCM A128CBC-HS256 A192CBC-HS384 A256CBC-HS512/);
|
||||||
|
my %jwealg = (
|
||||||
|
'A128KW' => '1234567890123456', #128 bits/16 bytes
|
||||||
|
'A192KW' => '123456789012345678901234', #192 bits/24 bytes
|
||||||
|
'A256KW' => '12345678901234567890123456789012', #256 bits/32 bytes
|
||||||
|
'A128GCMKW' => '1234567890123456', #128 bits/16 bytes
|
||||||
|
'A192GCMKW' => '123456789012345678901234', #192 bits/24 bytes
|
||||||
|
'A256GCMKW' => '12345678901234567890123456789012', #256 bits/32 bytes
|
||||||
|
'PBES2-HS256+A128KW' => 'any length 1',
|
||||||
|
'PBES2-HS384+A192KW' => 'any length 12',
|
||||||
|
'PBES2-HS512+A256KW' => 'any length 123',
|
||||||
|
'RSA-OAEP' => [Crypt::PK::RSA->new(\$rsaPriv), Crypt::PK::RSA->new(\$rsaPub)],
|
||||||
|
'RSA-OAEP-256' => [Crypt::PK::RSA->new(\$rsaPriv), Crypt::PK::RSA->new(\$rsaPub)],
|
||||||
|
'RSA1_5' => [Crypt::PK::RSA->new(\$rsaPriv), Crypt::PK::RSA->new(\$rsaPub)],
|
||||||
|
'ECDH-ES' => [Crypt::PK::ECC->new($Ecc256Private), Crypt::PK::ECC->new($Ecc256Public)],
|
||||||
|
'ECDH-ES+A128KW' => [Crypt::PK::ECC->new($Ecc512Private), Crypt::PK::ECC->new($Ecc512Public)],
|
||||||
|
'ECDH-ES+A192KW' => [Crypt::PK::ECC->new($Ecc384Private), Crypt::PK::ECC->new($Ecc384Public)],
|
||||||
|
'ECDH-ES+A256KW' => [Crypt::PK::ECC->new($Ecc256Private), Crypt::PK::ECC->new($Ecc256Public)],
|
||||||
|
);
|
||||||
|
my %jwsalg = (
|
||||||
|
'HS256' => 'any length 1234567890123456',
|
||||||
|
'HS384' => 'any length 123456789012345678901234',
|
||||||
|
'HS512' => 'any length 12345678901234567890123456789012',
|
||||||
|
'RS256' => [Crypt::PK::RSA->new(\$rsaPriv), Crypt::PK::RSA->new(\$rsaPub)],
|
||||||
|
'RS384' => [Crypt::PK::RSA->new(\$rsaPriv), Crypt::PK::RSA->new(\$rsaPub)],
|
||||||
|
'RS512' => [Crypt::PK::RSA->new(\$rsaPriv), Crypt::PK::RSA->new(\$rsaPub)],
|
||||||
|
'PS256' => [Crypt::PK::RSA->new(\$rsaPriv), Crypt::PK::RSA->new(\$rsaPub)],
|
||||||
|
'PS384' => [Crypt::PK::RSA->new(\$rsaPriv), Crypt::PK::RSA->new(\$rsaPub)],
|
||||||
|
'PS512' => [Crypt::PK::RSA->new(\$rsaPriv), Crypt::PK::RSA->new(\$rsaPub)],
|
||||||
|
'ES256' => [Crypt::PK::ECC->new($Ecc256Private), Crypt::PK::ECC->new($Ecc256Public)],
|
||||||
|
'ES384' => [Crypt::PK::ECC->new($Ecc512Private), Crypt::PK::ECC->new($Ecc512Public)],
|
||||||
|
'ES512' => [Crypt::PK::ECC->new($Ecc384Private), Crypt::PK::ECC->new($Ecc384Public)],
|
||||||
|
);
|
||||||
|
|
||||||
|
for my $alg (sort keys %jwsalg) {
|
||||||
|
my $k = ref $jwsalg{$alg} ? $jwsalg{$alg} : [ $jwsalg{$alg}, $jwsalg{$alg} ];
|
||||||
|
my $payload = 'testik';
|
||||||
|
my $token = encode_jwt(key=>$k->[0], payload=>$payload, alg=>$alg, allow_none=>1);
|
||||||
|
ok($token, "token: alg=>$alg");
|
||||||
|
my $decoded = decode_jwt(key=>$k->[1], token=>$token, alg=>$alg, allow_none=>1);
|
||||||
|
is($decoded, 'testik', "decoded: alg=>$alg");
|
||||||
|
}
|
||||||
|
|
||||||
|
for my $alg (sort keys %jwealg) {
|
||||||
|
for my $enc (@enclist) {
|
||||||
|
my $k = ref $jwealg{$alg} ? $jwealg{$alg} : [ $jwealg{$alg}, $jwealg{$alg} ];
|
||||||
|
my $payload = 'testik';
|
||||||
|
my $token = encode_jwt(key=>$k->[1], payload=>$payload, alg=>$alg, enc=>$enc);
|
||||||
|
ok($token, "token: enc=>$enc alg=>$alg");
|
||||||
|
my $decoded = decode_jwt(key=>$k->[0], token=>$token, alg=>$alg, enc=>$enc);
|
||||||
|
is($decoded, 'testik', "decoded: enc=>$enc alg=>$alg");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for my $enc (@enclist) {
|
||||||
|
my $alg = 'dir';
|
||||||
|
my $key_size;
|
||||||
|
if ($enc =~ /^A(128|192|256)CBC-HS/) {
|
||||||
|
$key_size = 2*$1/8;
|
||||||
|
}
|
||||||
|
elsif ($enc =~ /^A(128|192|256)GCM/) {
|
||||||
|
$key_size = $1/8;
|
||||||
|
}
|
||||||
|
my $k = 'x' x $key_size;
|
||||||
|
my $payload = 'testik';
|
||||||
|
my $token = encode_jwt(key=>$k, payload=>$payload, alg=>$alg, enc=>$enc);
|
||||||
|
ok($token, "token: enc=>$enc alg=>$alg");
|
||||||
|
my $decoded = decode_jwt(key=>$k, token=>$token, alg=>$alg, enc=>$enc);
|
||||||
|
is($decoded, 'testik', "decoded: enc=>$enc alg=>$alg");
|
||||||
|
|
||||||
|
my $payload_h = {str=>'žluťoučký kůň'};
|
||||||
|
my $token_h = encode_jwt(key=>$k, payload=>$payload_h, alg=>$alg, enc=>$enc);
|
||||||
|
ok($token_h, "token_h: enc=>$enc alg=>$alg");
|
||||||
|
my $decoded_h = decode_jwt(key=>$k, token=>$token_h, alg=>$alg, enc=>$enc, decode_payload=>1);
|
||||||
|
is($decoded_h->{str}, 'žluťoučký kůň', "decoded: enc=>$enc alg=>$alg");
|
||||||
|
}
|
||||||
|
|
||||||
|
done_testing;
|
235
t/jwt_params.t
Normal file
235
t/jwt_params.t
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Test::More;
|
||||||
|
|
||||||
|
use Crypt::JWT qw(encode_jwt decode_jwt);
|
||||||
|
use Crypt::PK::ECC;
|
||||||
|
use Crypt::PK::RSA;
|
||||||
|
use Crypt::Misc qw(encode_b64u);
|
||||||
|
use JSON::MaybeXS qw(encode_json);
|
||||||
|
|
||||||
|
# key password is 'secret'
|
||||||
|
my $rsaPriv = <<'EOF';
|
||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
Proc-Type: 4,ENCRYPTED
|
||||||
|
DEK-Info: AES-128-CBC,2823DCBA91F7DBA2ED920CAEE40F0BB4
|
||||||
|
|
||||||
|
KAADjca5SzbAbdz2cF567ZO9WjZz+lA1C40gsOBvHB6LjWU32YGW6Hz9a7pwUjOh
|
||||||
|
E/gGSFkKv6pTJgXfLs/l+pIDGSohhzChw7hkmN1IgVXqDQZw3koW5Yn7bg6xeJoI
|
||||||
|
JFwIIQhnft6BHG2o/5MzUTRwHpIxRuIaz2FnZtBNbVtQInHtP8LJIAVoyoO4c0ET
|
||||||
|
IQBDj7dwOAPdxOsrKCRkjI8IBMwWtKBq7XunkE15dZFFZrZOfIaXUqNYF9DlCHBk
|
||||||
|
eGV2lZoL99pOtJzHTBzv3rtyPYqCNotTNnui2Z0Jzcq8K97XAlzKhL7BFMw5TSUF
|
||||||
|
Tf9ECgumaRELXDdlUtEiZ7uACBXAW+qTUxOCrp+EeyfUBYPLuiy9KQvJd4C+8QIs
|
||||||
|
OIYekzfqZfhbhOdb0U7ZRN3KXfuNS70vKfoMyuW4UVx75QZt3CnJL8M6dn+eijjw
|
||||||
|
mEVCT/a8SLgTgMKtl2AzFiJK4WqvnUs9iOswlaAWCIpvrMQmxltoL34aim55EZKd
|
||||||
|
gDlEW5zCcjYe8A5d5abd4cX8vVrN57j2O3Dk9Dgyr4ZHPjBMF8b6LnWqBGrgFrbQ
|
||||||
|
LpjDZRNm4W7JuROL5VtSBEwP5VAMdl56UPlgGmM6K2MgAvkZ99ycffu0vsKOxd1T
|
||||||
|
5wpY2y5SBOyoex0XPa9woz0GOLjf9ydpVlVikPHk4XX2ts0+L5VttkQ7wO9GLUj0
|
||||||
|
OltsrOxscHq3xPYsJgxmmHGmhrlTKIv1YHjzZsteqZLokH3kr1sCEX+vS3lqaQP8
|
||||||
|
rmIjf2vAWi3inteZifZ2v48V8XPTOUky/YQvTEGDstHWVd74hhrCVfx+Jk7vjipr
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
|
EOF
|
||||||
|
|
||||||
|
my $k = '68yYPz1F17s4VWIIbEOB';
|
||||||
|
my $p = 'testik RANDOM=kDSIHckuMyz1JmCyKhhx Blexx!';
|
||||||
|
my $h = { body=>"hash", number=>123456, text=>"Hello" };
|
||||||
|
my $l = [ 11, 22, 33, 44, 55 ];
|
||||||
|
my ($alg, $enc);
|
||||||
|
my ($token, $decoded, $decoded_h);
|
||||||
|
|
||||||
|
for ([qw/PBES2-HS256+A128KW A128GCM/], ['HS512', '']) {
|
||||||
|
($alg, $enc) = @$_;
|
||||||
|
|
||||||
|
$token = encode_jwt(key=>$k, payload=>$p, alg=>$alg, enc=>$enc, zip=>'deflate');
|
||||||
|
ok($token, "deflate: enc=>'$enc' alg=>'$alg'");
|
||||||
|
$decoded = decode_jwt(key=>$k, token=>$token);
|
||||||
|
is($decoded, $p, "decoded - deflate: enc=>'$enc' alg=>'$alg'");
|
||||||
|
|
||||||
|
$decoded = decode_jwt(key=>$k, token=>$token, accepted_alg=>$alg);
|
||||||
|
is($decoded, $p, "decoded - accepted_alg/1: enc=>'$enc' alg=>qr/.+/");
|
||||||
|
$decoded = decode_jwt(key=>$k, token=>$token, accepted_alg=>$alg);
|
||||||
|
is($decoded, $p, "decoded - accepted_alg/2: enc=>'$enc' alg=>'$alg'");
|
||||||
|
$decoded = decode_jwt(key=>$k, token=>$token, accepted_alg=>["XX", $alg, "YY"]);
|
||||||
|
is($decoded, $p, "decoded - accepted_alg/3: enc=>'$enc' alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, accepted_alg=>["XX", "YY"]) };
|
||||||
|
is($decoded, undef, "decoded - accepted_alg/4: enc=>'$enc' alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, accepted_alg=>"YY") };
|
||||||
|
is($decoded, undef, "decoded - accepted_alg/5: enc=>'$enc' alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, accepted_alg=>qr/NOTFOUND/) };
|
||||||
|
is($decoded, undef, "decoded - accepted_alg/6: enc=>'$enc' alg=>'$alg'");
|
||||||
|
|
||||||
|
if ($enc) {
|
||||||
|
# JWE only
|
||||||
|
$decoded = decode_jwt(key=>$k, token=>$token, accepted_enc=>$enc);
|
||||||
|
is($decoded, $p, "decoded - accepted_enc/1: enc=>'$enc' alg=>qr/.+/");
|
||||||
|
$decoded = decode_jwt(key=>$k, token=>$token, accepted_enc=>$enc);
|
||||||
|
is($decoded, $p, "decoded - accepted_enc/2: enc=>'$enc' alg=>'$alg'");
|
||||||
|
$decoded = decode_jwt(key=>$k, token=>$token, accepted_enc=>["XX", $enc, "YY"]);
|
||||||
|
is($decoded, $p, "decoded - accepted_enc/3: enc=>'$enc' alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, accepted_enc=>["XX", "YY"]) };
|
||||||
|
is($decoded, undef, "decoded - accepted_enc/4: enc=>'$enc' alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, accepted_enc=>"YY") };
|
||||||
|
is($decoded, undef, "decoded - accepted_enc/5: enc=>'$enc' alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, accepted_enc=>qr/NOTFOUND/) };
|
||||||
|
is($decoded, undef, "decoded - accepted_enc/6: enc=>'$enc' alg=>'$alg'");
|
||||||
|
}
|
||||||
|
|
||||||
|
$token = encode_jwt(key=>$k, payload=>$p, alg=>$alg, enc=>$enc, zip=>['deflate', 1]);
|
||||||
|
ok($token, "deflate+1: enc=>'$enc' alg=>'$alg'");
|
||||||
|
$decoded = decode_jwt(key=>$k, token=>$token);
|
||||||
|
is($decoded, $p, "decoded - deflate+1: enc=>'$enc' alg=>'$alg'");
|
||||||
|
|
||||||
|
$token = encode_jwt(key=>$k, payload=>$h, alg=>$alg, enc=>$enc);
|
||||||
|
ok($token, "hash: enc=>'$enc' alg=>'$alg'");
|
||||||
|
$decoded = decode_jwt(key=>$k, token=>$token, decode_payload=>0);
|
||||||
|
like($decoded, qr/"text":"Hello"/, "decoded - hash/1: enc=>'$enc' alg=>'$alg'");
|
||||||
|
$decoded = decode_jwt(key=>$k, token=>$token, decode_payload=>1);
|
||||||
|
is($decoded->{text}, "Hello", "decoded - hash/2: enc=>'$enc' alg=>'$alg'");
|
||||||
|
$decoded = decode_jwt(key=>$k, token=>$token);
|
||||||
|
is($decoded->{text}, "Hello", "decoded - hash/3: enc=>'$enc' alg=>'$alg'");
|
||||||
|
|
||||||
|
$token = encode_jwt(key=>$k, payload=>$l, alg=>$alg, enc=>$enc);
|
||||||
|
ok($token, "array: enc=>'$enc' alg=>'$alg'");
|
||||||
|
$decoded = decode_jwt(key=>$k, token=>$token, decode_payload=>0);
|
||||||
|
like($decoded, qr/\[11,22,33,44,55\]/, "decoded - array/1: enc=>'$enc' alg=>'$alg'");
|
||||||
|
$decoded = decode_jwt(key=>$k, token=>$token, decode_payload=>1);
|
||||||
|
is($decoded->[0], 11, "decoded - array/2: enc=>'$enc' alg=>'$alg'");
|
||||||
|
$decoded = decode_jwt(key=>$k, token=>$token);
|
||||||
|
is($decoded->[0], 11, "decoded - array/3: enc=>'$enc' alg=>'$alg'");
|
||||||
|
|
||||||
|
my $keylist = {
|
||||||
|
keys => [
|
||||||
|
{ kid=>"key1", kty=>"oct", k=>"GawgguFyGrWKav7AX4VKUg" },
|
||||||
|
{ kid=>"key2", kty=>"oct", k=>"ulxLGy4XqhbpkR5ObGh1gX" },
|
||||||
|
]
|
||||||
|
};
|
||||||
|
my $keylist_json = encode_json($keylist);
|
||||||
|
$token = encode_jwt(key=>$keylist->{keys}->[1], extra_headers=>{kid=>"key2"}, payload=>$p, alg=>$alg, enc=>$enc);
|
||||||
|
ok($token, "kid_keys: enc=>'$enc' alg=>'$alg'");
|
||||||
|
$decoded = decode_jwt(kid_keys=>$keylist, token=>$token);
|
||||||
|
is($decoded, $p, "decoded - kid_keys/1: enc=>'$enc' alg=>'$alg'");
|
||||||
|
$decoded = decode_jwt(kid_keys=>$keylist_json, token=>$token);
|
||||||
|
is($decoded, $p, "decoded - kid_keys/2: enc=>'$enc' alg=>'$alg'");
|
||||||
|
|
||||||
|
$token = encode_jwt(key=>$k, payload=>$p, alg=>$alg, enc=>$enc, extra_headers=>{extra1=>11, extra2=>22});
|
||||||
|
($decoded_h, $decoded) = decode_jwt(key=>$k, token=>$token, decode_header=>1);
|
||||||
|
is($decoded, $p, "decoded - decode_header/1: enc=>'$enc' alg=>'$alg'");
|
||||||
|
is($decoded_h->{extra1}, 11, "decoded - decode_header/2: enc=>'$enc' alg=>'$alg'");
|
||||||
|
|
||||||
|
if (!$enc) {
|
||||||
|
#JWS only
|
||||||
|
$token = encode_jwt(key=>$k, payload=>$p, alg=>$alg);
|
||||||
|
ok($token, "ignore_signature: alg=>'$alg'");
|
||||||
|
$decoded = decode_jwt(token=>$token, ignore_signature=>1);
|
||||||
|
is($decoded, $p, "decoded - ignore_signature: alg=>'$alg'");
|
||||||
|
|
||||||
|
my $claims = {
|
||||||
|
iss => 'iss-string',
|
||||||
|
aud => 'aud-string',
|
||||||
|
sub => 'sub-string',
|
||||||
|
jti => 'jti-string',
|
||||||
|
iat => time,
|
||||||
|
nbf => time,
|
||||||
|
exp => time + 10,
|
||||||
|
data => 'Hello',
|
||||||
|
};
|
||||||
|
$token = encode_jwt(key=>$k, payload=>$claims, alg=>$alg);
|
||||||
|
ok($token, "claims: alg=>'$alg'");
|
||||||
|
$decoded = decode_jwt(key=>$k, token=>$token);
|
||||||
|
is($decoded->{data}, 'Hello', "decoded - claims/1: alg=>'$alg'");
|
||||||
|
|
||||||
|
$decoded = decode_jwt(key=>$k, token=>$token, verify_iss=>sub { return 1 }, verify_aud=>sub { return 1 }, verify_sub=>sub { return 1 }, verify_jti=>sub { return 1 });
|
||||||
|
is($decoded->{data}, 'Hello', "decoded - claims/2: alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, verify_iss=>sub { return 0 }, verify_aud=>sub { return 1 }, verify_sub=>sub { return 1 }, verify_jti=>sub { return 1 }) };
|
||||||
|
is($decoded, undef, "decoded - claims/3: alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, verify_iss=>sub { return 1 }, verify_aud=>sub { return 0 }, verify_sub=>sub { return 1 }, verify_jti=>sub { return 1 }) };
|
||||||
|
is($decoded, undef, "decoded - claims/4: alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, verify_iss=>sub { return 1 }, verify_aud=>sub { return 1 }, verify_sub=>sub { return 0 }, verify_jti=>sub { return 1 }) };
|
||||||
|
is($decoded, undef, "decoded - claims/5: alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, verify_iss=>sub { return 1 }, verify_aud=>sub { return 1 }, verify_sub=>sub { return 1 }, verify_jti=>sub { return 0 }) };
|
||||||
|
is($decoded, undef, "decoded - claims/6: alg=>'$alg'");
|
||||||
|
|
||||||
|
$decoded = decode_jwt(key=>$k, token=>$token, verify_iss=>qr/string/, verify_aud=>qr/string/, verify_sub=>qr/string/, verify_jti=>qr/string/);
|
||||||
|
is($decoded->{data}, 'Hello', "decoded - claims/7: alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, verify_iss=>qr/BADVAL/, verify_aud=>qr/string/, verify_sub=>qr/string/, verify_jti=>qr/string/) };
|
||||||
|
is($decoded, undef, "decoded - claims/8: alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, verify_iss=>qr/string/, verify_aud=>qr/BADVAL/, verify_sub=>qr/string/, verify_jti=>qr/string/) };
|
||||||
|
is($decoded, undef, "decoded - claims/9: alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, verify_iss=>qr/string/, verify_aud=>qr/string/, verify_sub=>qr/BADVAL/, verify_jti=>qr/string/) };
|
||||||
|
is($decoded, undef, "decoded - claims/10: alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, verify_iss=>qr/string/, verify_aud=>qr/string/, verify_sub=>qr/string/, verify_jti=>qr/BADVAL/) };
|
||||||
|
is($decoded, undef, "decoded - claims/11: alg=>'$alg'");
|
||||||
|
|
||||||
|
# iat
|
||||||
|
$token = encode_jwt(key=>$k, payload=>{iat=>time+10, nbf=>time, exp=>time+10, data=>'Hello'}, alg=>$alg);
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token) };
|
||||||
|
is($decoded->{data}, 'Hello', "decoded - iat/1: alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, verify_iat=>undef) };
|
||||||
|
is($decoded, undef, "decoded - iat/2: alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, verify_iat=>1) };
|
||||||
|
is($decoded, undef, "decoded - iat/3: alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, verify_iat=>0) };
|
||||||
|
is($decoded->{data}, 'Hello', "decoded - iat/4: alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, verify_iat=>1, leeway=>20) };
|
||||||
|
is($decoded->{data}, 'Hello', "decoded - iat/5: alg=>'$alg'");
|
||||||
|
|
||||||
|
# nbf
|
||||||
|
$token = encode_jwt(key=>$k, payload=>{nbf=>time+10, exp=>time+20, data=>'Hello'}, alg=>$alg);
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token) };
|
||||||
|
is($decoded, undef, "decoded - nbf/1: alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, verify_nbf=>undef) };
|
||||||
|
is($decoded, undef, "decoded - nbf/2: alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, verify_nbf=>1) };
|
||||||
|
is($decoded, undef, "decoded - nbf/3: alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, verify_nbf=>0) };
|
||||||
|
is($decoded->{data}, 'Hello', "decoded - nbf/4: alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, leeway=>20) };
|
||||||
|
is($decoded->{data}, 'Hello', "decoded - nbf/5: alg=>'$alg'");
|
||||||
|
|
||||||
|
# exp
|
||||||
|
$token = encode_jwt(key=>$k, payload=>{exp=>time-5, data=>'Hello'}, alg=>$alg);
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token) };
|
||||||
|
is($decoded, undef, "decoded - exp/1: alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, verify_exp=>undef) };
|
||||||
|
is($decoded, undef, "decoded - exp/2: alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, verify_exp=>1) };
|
||||||
|
is($decoded, undef, "decoded - exp/3: alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, verify_exp=>0) };
|
||||||
|
is($decoded->{data}, 'Hello', "decoded - exp/4: alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, leeway=>20) };
|
||||||
|
is($decoded->{data}, 'Hello', "decoded - exp/5: alg=>'$alg'");
|
||||||
|
|
||||||
|
$token = encode_jwt(key=>$k, payload=>{nbf=>time+10, iat=>time+10, exp=>time-10, data=>'Hello'}, alg=>$alg);
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token) };
|
||||||
|
is($decoded, undef, "ignore_claims/1: alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(key=>$k, token=>$token, ignore_claims=>1) };
|
||||||
|
is($decoded->{data}, 'Hello', "ignore_claims/2: alg=>'$alg'");
|
||||||
|
|
||||||
|
$token = encode_jwt(key=>$k, auto_iat=>1, relative_exp=>14, relative_nbf=>3, payload=>{data=>'Hello'}, alg=>$alg);
|
||||||
|
($decoded_h, $decoded) = decode_jwt(key=>$k, token=>$token, decode_header=>1, leeway=>4);
|
||||||
|
my $iat = $decoded->{iat};
|
||||||
|
ok(time - $iat < 2, "auto_iat/1");
|
||||||
|
is($decoded->{nbf}, $iat+3, "relative_nbf/1: alg=>'$alg'");
|
||||||
|
is($decoded->{exp}, $iat+14, "relative_exp/1: alg=>'$alg'");
|
||||||
|
|
||||||
|
$token = encode_jwt(key=>$k, auto_iat=>1, relative_exp=>-4, relative_nbf=>-13, payload=>{data=>'Hello'}, alg=>$alg);
|
||||||
|
($decoded_h, $decoded) = decode_jwt(key=>$k, token=>$token, decode_header=>1, leeway=>14);
|
||||||
|
$iat = $decoded->{iat};
|
||||||
|
ok(time - $iat < 2, "auto_iat/2");
|
||||||
|
is($decoded->{nbf}, $iat-13, "relative_nbf/2: alg=>'$alg'");
|
||||||
|
is($decoded->{exp}, $iat-4, "relative_exp/2: alg=>'$alg'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
$token = eval { encode_jwt(payload=>$p, alg=>'none') };
|
||||||
|
ok(!defined $token, "allow_none/1: alg=>'$alg'");
|
||||||
|
$token = encode_jwt(payload=>$p, alg=>'none', allow_none=>1);
|
||||||
|
ok($token, "allow_none/2: alg=>'$alg'");
|
||||||
|
$decoded = eval { decode_jwt(token=>$token) };
|
||||||
|
is($decoded, undef, "decoded - allow_none/1: alg=>'$alg'");
|
||||||
|
$decoded = decode_jwt(token=>$token, allow_none=>1);
|
||||||
|
is($decoded, $p, "decoded - allow_none/2: alg=>'$alg'");
|
||||||
|
}
|
||||||
|
|
||||||
|
done_testing;
|
700
t/kw_aes.t
Normal file
700
t/kw_aes.t
Normal file
@ -0,0 +1,700 @@
|
|||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Test::More;
|
||||||
|
use Crypt::KeyWrap qw(aes_key_wrap aes_key_unwrap);
|
||||||
|
use Crypt::Misc qw(decode_b64u);
|
||||||
|
|
||||||
|
my @tv = (
|
||||||
|
{
|
||||||
|
C => "cbe70897e1bf88f157234415d69daf078cfa311eae362109",
|
||||||
|
D => 0,
|
||||||
|
I => 0,
|
||||||
|
K => "d95c908e74e5cb172fbb8bfd7fd3480d",
|
||||||
|
N => "AES",
|
||||||
|
P => "45fd2c9c2044984d002e525cea0c7855",
|
||||||
|
X => "AES:0:0:32:0032:0048",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "f3f176f516be33146aa632a4308547170197f6294746a4d19e2a844aeb0213ad",
|
||||||
|
D => 0,
|
||||||
|
I => 0,
|
||||||
|
K => "8d7a8d486899fe16ba9df45fab6bd7fe",
|
||||||
|
N => "AES",
|
||||||
|
P => "8a9ee446b9fe93fc091b9a250961a7ad184bf9628070ec00",
|
||||||
|
X => "AES:0:0:32:0048:0064",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "8ecfc167b2a2b6abf29e25e6f93ab01ad2f18518a3968d4efe64a8b562bb870fb7ab8b0c34b2fe6b",
|
||||||
|
D => 0,
|
||||||
|
I => 0,
|
||||||
|
K => "14483415b4cf128a61e2e2a475600a4f",
|
||||||
|
N => "AES",
|
||||||
|
P => "f81e36b0cea09672b54d2c38ed8d15352c72a6ca2ea21bd89099b0d2c883b928",
|
||||||
|
X => "AES:0:0:32:0064:0080",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "1b56f43cf33fd209424fea01e0dcd8dd88c5cdd81f13e9476bc7912a32e617962f180f382e3b356d6bd957be68722e8f",
|
||||||
|
D => 0,
|
||||||
|
I => 0,
|
||||||
|
K => "6468354d3bb868f43a6dbc12444d4724",
|
||||||
|
N => "AES",
|
||||||
|
P => "a4bab14e6b830f26d91e3f4d142cbb063b9b218ed43e3b73bb74b3bd20000f43bb6b6cbf847ac2cf",
|
||||||
|
X => "AES:0:0:32:0080:0096",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "b02c0144fb2a402af8db8681b0c98e00812ec408b6c12598bf60dfa33bb4578ca3989f67e0f0d1f3df186c870bd99f4bde411a1251a50b9a1c7e8b190626e0aae4ad4a115c38f0b5fff1309ab65017a00b38a3db7bebc409275333123a6fc9f0c1c2cf5b0a86cc8658b69e5f85d7c1e0647a6d2372d2879b33ad722baa4e15c89b9c26ada3a480fffbef3230d3c691bbf18477b1f0b3d64c4687b7f81734c340641a114ee47a5eb9e880ddff622133424b2f5d15cc4240cdfd97bbe25e638717f09b4597b44e132df4aa06ab476dc8e98a3b7df980ab5f532db9df1036a1bef4fdf84314132726353e7f524e6a0a2bdc0f755418d5840a0063fbce6f347885c385c5b7301b47088f69d1b31ff4ad55c5e92c72e230ae10933c2f606d792f2049431d5fa316ab5a8caf689fb49fd9478b91d59c35b7f41fa8dbc95d9b87fafe35a101f8066c5a35af6fdcc93c9edf34642050c6a686207f9f8f3bc7d54107da30a3673973cd7f6077da14868c0b77fc3ddd0882bba5923df9d35bb87895439abea7dff9a6dd44606245f830230879c82fa5e935b9bb8932fab68063299800c8221eccdb4dc27eebc17677e15f0471bbc97392c1ebba987f2b632ce40620e2a964a12875c74d3e5e9d89cf55e4bec3db9c66403f5b685296edcb8247ad94a262c7b4afd584b3e702e407f137ae9a56c87244400f404eb7f424a9322d9ec45ab1a83d1eced31e140e00",
|
||||||
|
D => 0,
|
||||||
|
I => 0,
|
||||||
|
K => "c6554c6e17036b09e0c4b764a772e227",
|
||||||
|
N => "AES",
|
||||||
|
P => "f2a7b464ed38c259aa9180b8b0b1b3fe7fe854088c71927339065907aab427b58fb192e7abb0427f1edafee621c8b5da132b9e70f48acf818572c172caa50bef468a043012318a94ac861e02b82eb762c9dfae4f3b1dee192fc534ee8f4291a5df982d8929c049036f6047a700e3cf9513fffe17aad829c668ae1d1588b6652296a48613cd27c58635972c144a330f5b2ab40189a572d56126752039275cc00ceffb497b984bf7e3eebf0f04c35f9b335e5e39d390161e17651c77ea798f139bdf6f6af4e77c28b4db0fac96c5a655358b67061486859ccd7ef75faa047692109fd75e667cf4b2335f7e83170334a15f7b5311e9224e99f9d667c02d63b4415b61f86e50997a074673fc69a45f4c874ff4d5bb9180bd1c69bd0faa0398104657558f0c34cda08fcf45eaf7912d69ec230718fa9b4020a0c45720ab83eda46b46784773d8c3bfe07f4727ef9ded8c5dbf8b0482172067cd15463ef74d79d2930ffdfe2ea8642f99f8fbfb9a4e51953b32ad64a0b3694c1e5672ab0a00e811eeead1b3a68d0f7f2021b6fdcb5cc42a8341e2aee90ed2bb1d0f299df97c1f5daa2b2c6638580a273540e96c93d27ca7eb5ac5a644e75c94a164343261a362e61e1f2c4a5c4498bb031f177cece0cea1583fd49092f5151b548b333c2d678e4df3ef34e8ad8311ea786f241f828d28bd208aec12a77b35a8b29542ab65cb398a96db",
|
||||||
|
X => "AES:0:0:32:1024:1040",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "a3fa5ab1e13daaee02ef935e054729125195a0dff188ccc6",
|
||||||
|
D => 0,
|
||||||
|
I => 0,
|
||||||
|
K => "cc77273466f04df87c5da005dc25c8d24f7785eadc2fcd83",
|
||||||
|
N => "AES",
|
||||||
|
P => "daaebc7b7ff1e52796e6fd83552139cf",
|
||||||
|
X => "AES:0:0:48:0032:0048",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "4d2454fa47a395ac05305bb1c125892c51aa11d55238b56ead0ab6256b686fe2",
|
||||||
|
D => 0,
|
||||||
|
I => 0,
|
||||||
|
K => "f87e4c4228031f46257ac932d934c19fbf272256877d8000",
|
||||||
|
N => "AES",
|
||||||
|
P => "086a44b36c80838a6af5e5c627e3ea6dac79ed57918df45f",
|
||||||
|
X => "AES:0:0:48:0048:0064",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "70506d87e321d908feede827ef2dfe9274b90c50918ce9c6b156814e1802891ea9246ceaebfd6a03",
|
||||||
|
D => 0,
|
||||||
|
I => 0,
|
||||||
|
K => "991af4832a4677c24b6c55d284fb7451c68eb285f2f30a90",
|
||||||
|
N => "AES",
|
||||||
|
P => "93e27005847926fe518c794d4e30c34b03720f19b2bf377d6077b2b582a14f4f",
|
||||||
|
X => "AES:0:0:48:0064:0080",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "66dd0c30315e9b6718f89ad861b502d0f159d01e20620243666236076756ee93a3c0cb2d068dc66d01c71d1e579a727a",
|
||||||
|
D => 0,
|
||||||
|
I => 0,
|
||||||
|
K => "b1753c2540659ad2e742eaa669d09dd21c1f80d15f214e3c",
|
||||||
|
N => "AES",
|
||||||
|
P => "a73a3b220299a1ee07fdc2c7a4eecce823e16b039878f729ff200e14037839fe9deb24150028ea09",
|
||||||
|
X => "AES:0:0:48:0080:0096",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "6d9c31a29748f5ccb7df3f95978a6eb6c35190cda4a4772e0cc31b84ff973bbfa44619f157bd97835904a655675efa2bb9dd98da1e76d86ecfe0aa0fd5c2ebf2cd13ece9f738c2a48b7703e15e6bd5175862087aa544b7cf8c4775b52561d398afbaff71d2a75c59640e6629fe7528da663058555b0e6064778a7329c418dd921457fd69542e0d73b628ddd8bb9c2fc76b648c3b624929b26898528e0a1cb533744cf60d5cfb2a6292a216747300e6a5a303207d882427e03be9526c395c1cfbf6f70d857203817d4ee3746aaf6044af514dfe985d4a0c84e249f39a0aa6e6a97da1eaaaa6ed2a4f084da72e48ece3521e8f9fa107130f2f9bfd6518035814e42ad491eb7925cebf7edb861654e194c304202e5bbaefaca4179fee6f1e44af60d4b8e4604cd213bafe27fbb1c1cde2b5fc2addfb2b7e01e8b3dabf269bf8d35740b1fcefb0c0e6642b49cd536b3dd3d27ac9b89471507c9fdab0de7ed43200e3145ce670cda12fb4f00046129aaca1ce966976a3c35a61ecd9481d8d4a875638c3790ec25849755fa60f943acf4a6cfd62c7f77df43c73f699d10e147b89b1c285a66820db161ae13d9075e720d8dfa00324087636920f0325f17d3800a24bc6ee0089b8bb56887db051b743cf3a3ce5a689f9f59555e1585dd2fbffa7795e5eba0c518ac29d98738b4b8efdf11f4ed42ba2286a68e294b94e167e0becadc6675ed59a4e25500cc8",
|
||||||
|
D => 0,
|
||||||
|
I => 0,
|
||||||
|
K => "e4f1cdecd977dcad04d93caf433e48269ebe13db2f929232",
|
||||||
|
N => "AES",
|
||||||
|
P => "1a01853bf2bdffde1aaa86424292907275d547bfe693a3d49f9a582fcb8eb0903e17e55a27fd92f6d6534543fad4cefcdfacb6bce5912453ff4a63cf343810f2f5f8d5cb9580a64eb849bd6e20d9be0c404710379ffa644a7e3ba1004b172768277fa56314912c537079d1fca7c47c8d5be0704b5719485ad6a9bcdcdac9de316c797bcb13861fbebe5101f23c546e5dd358f9f448f23bf08f2c08798f6c4c989d5274ee9ac13a85b8b9621bd201ca2c6cef5f209c111b2e2c3945a3774aca8b6a65f826d3f6a7473f674397fa372ba9b4d46e59a6f6c1f32049bb8cad1ddd8d7c3a2e231b874eae34c0a51dc9d564a546e26ae4b5e809236c91af304b8523176bd4dda38ea646e30e784e2330c5c3d6f282986f0c0d7002903c8f624c9f8febbeddd5360c166cfb0dbae67470dfa9ff104174e15f87d4e33d3a43a29bea0e4b024891f8e28bc89a51c505749a65f1b8561763c67b30f79e27faa7a432405add88c1239862a8fce146740cc800504ce495150dab4c761b0258302579c54e711fec31ec960316010d54120b20d5f21c554c9c81952966a1f12ec61611400c0ad09ec2213e5bd56e3b69e73ac36c1d057356856efbd68ee5b2e11e3a7baaf2494d8e1b8dcdf2a092a1066aa668d435da5db94fb7e82878d4eaa6a2960648cbf37df7a93572167713adbbbb81977e32d02ef7cb8fd64ac4782e0084f7d90c2a0010",
|
||||||
|
X => "AES:0:0:48:1024:1040",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "f1733778d27dfe1e57a8822d5f5ae62c2837612a93e21420",
|
||||||
|
D => 0,
|
||||||
|
I => 0,
|
||||||
|
K => "4f43cf947aadc06b375ae3cde537e2ac2cd4b1b499406254cd286d459249e929",
|
||||||
|
N => "AES",
|
||||||
|
P => "eee8798323b347eb2a06d1e2ae31a7a8",
|
||||||
|
X => "AES:0:0:64:0032:0048",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "dbf7b7d96d3f620df3fb2506b080456f1ef9279d9b9dcdc2c99266faa068af8d",
|
||||||
|
D => 0,
|
||||||
|
I => 0,
|
||||||
|
K => "669514545e5c321d6404d69732a3832dc322f96af8ca46ec01e0607e09bf887e",
|
||||||
|
N => "AES",
|
||||||
|
P => "5f89e8643b2b026dfb680f0f0dd45d5c24f6805d874b1931",
|
||||||
|
X => "AES:0:0:64:0048:0064",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "8cd08b63bb1efd7e2aedc28103c42712aa0c0bf00263cc52aef5d2e333822b6e0c9c715f7353d950",
|
||||||
|
D => 0,
|
||||||
|
I => 0,
|
||||||
|
K => "05b97f0fb02539f5841b2d58bff4f1d57fb2fa62821f537c1dc0d921a9475751",
|
||||||
|
N => "AES",
|
||||||
|
P => "2afe143fc9114897ce6129f2a81685130914b1927d452fe2b96c788da94f77ba",
|
||||||
|
X => "AES:0:0:64:0064:0080",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "1d056a9cd9c0ac550f1d060e2bb764b0a3e09c3e8ac35d8aa91601125035a19f7bc503cb2794cc68f16b2afc1f325c31",
|
||||||
|
D => 0,
|
||||||
|
I => 0,
|
||||||
|
K => "6e1aeec3b7cc4d7b4d038038b32f49b464f44ae3a787e53ae69c97d0b61bfd13",
|
||||||
|
N => "AES",
|
||||||
|
P => "6f8982b37a40559448223c8e31160cb9e0280670808c9b3887323b1c68da20966ee12d05832debed",
|
||||||
|
X => "AES:0:0:64:0080:0096",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "c51316caa1a0d5cb5530a28974af76370d7ef6851c04559a11dc584f0796969b1934ce398d56b0e97079b78654a8a5d03ad5eb5d5704bc0c3618c2d422ba8e5ca26e5d973350815498419f53b55f83d5447ec373e1ca8c7415f3c10e419951893aeeb840e8ae4b178a5c911d55710352c3dcc4cb7c5c846cd9e093579abdb1ec83d7c86a5e9c8573deb3f9395c612d562b377363c70bff8663b0fdb574ffb2d32cdda1e1a06af8d2b56b52ce2c2a8dc9a0ab9b16f7553d59bd4b563881e96059e735807b9a668abb8c4bfc1f0f61af25631b6552619394f03ee41dd63db72cf38174b504994395f2c15cf0654071bd3d8a90d8c58c2063fd51986655a01f1744a13f4c2ae7d4af70bb896aae23db0274d580bd358dd034608d26cf798c005282189d9c07b391b9d1a961636f18a7ddb72fabdfb14d871a04ee09bf41c3588fcce16b1f812f864e924a19d415a64b0c29e7e196805abc909db5f6f6b782b5604cb2eb2c8295600670ecd45d1261d0055fe2f468da2240ea27c8648e63dace0ba867115cc72796c4d850e8cc8a2f028e45fe3a49a31a4283638fb5b7d12bb4fa6150986c77fc79fa534f4e3cba65de257dafe8cde538c49f513b34bd20bbc2b77557ef275748dd9cf39b7b1744e9b8751a3578be9e1fe15d6e23909305a69d257cc95be633dc10279d9f4c7cb582003f58749980733f5281b6a3ac01a51f49a201a64087c74b127cc9",
|
||||||
|
D => 0,
|
||||||
|
I => 0,
|
||||||
|
K => "afc8b67cc7582833d4f42e0a74e77a8c51781929ac64cf5863aa6faeff2cf2e8",
|
||||||
|
N => "AES",
|
||||||
|
P => "3a1f50258a5c39c216183f9543402f49060ad4d4f6dc552a763f0e81527d9d19286aa23f68c5e3046e29d3c8888eceb5f51fd54e7586597d9b4e452885f34bd4d3ed002f11201ed3c7d825c9959c9e0f61302f43ec68c073a67d2850ba1ab96e520940b409489d5a0417555e28a51bb7330947944eea9b4bf03e8db68269e3968e1f7b6085265bbe0fb844e5a39575e51ba52fb8d9cfc8cc64192ccb8d2981495e10aaaa7a12fa205d4efa4601fa129c9f51d8a70acd95992f4006692b60456d067ed8dcae635f9bd123aedd7286a5d4d3fbebad838f7dfb4863ee538d82ac4a0e69ca215e37e0880a1cf35ed9fa2b20fc9b85951ab8ceeab3aaa9345751a7285b8c7b4ce3e820df79583e8822f48c9afde5d53542a9f4c13582028675dc792539a52fff5341a1bcae2bc8d519f625e76f379de922172d2019489995e510cf16e9e9639264e3a6eb0aa5dfcb2f8ce2cdd9ac1ddb0e6e42d971aad170ead96c780e7a75ab064dacc348144ef66fbc72c2326faa20344d7387356e0eb2bbabf1d9a50d69c617fd8d794e687c7c240ed8a08a5be5d2c25f5f3bfd6ed16820f61f6a48e103ef342fdd26e1d433cb3a2aed7098d84e344a1fc591e7955fe39e14b08d4f8b3f0f3003c945f51988082d00b7947fa6da377650f2ec19e4d019ea98671f5c2936762cd01b2d1e782c44f6743d28a2275e6a42c4e1b309be9895160ef9ec",
|
||||||
|
X => "AES:0:0:64:1024:1040",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "58b7cf4889a4dc3ca4f8fa63bd3d6754f9e616541db63dc1",
|
||||||
|
D => 0,
|
||||||
|
I => 1,
|
||||||
|
K => "80d7ce2475c6797556ff339d99a0912a",
|
||||||
|
N => "AES",
|
||||||
|
P => "d0f105beb850d66253b7c668d17c51c5",
|
||||||
|
X => "AES:0:1:32:0032:0048",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "91b97497a947a84d49e69e4689556cae7b0d67ed039d7adf4615af58c001d13f",
|
||||||
|
D => 0,
|
||||||
|
I => 1,
|
||||||
|
K => "13f56cc2642f8db2964f257b1a2c3054",
|
||||||
|
N => "AES",
|
||||||
|
P => "4686ddf7b8b489831692401d7f54e6509502f519060f8dd7",
|
||||||
|
X => "AES:0:1:32:0048:0064",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "f3cf8f0747e283bc33b115fe58abf828e90d3171e74f2b23f059f0fc5710ed71435202af9d3f77d9",
|
||||||
|
D => 0,
|
||||||
|
I => 1,
|
||||||
|
K => "fec8932bddb6c45e91195363616c6deb",
|
||||||
|
N => "AES",
|
||||||
|
P => "648944481258d2b2b509feec6e4526182c1bf6d7b9206412702610df204557ba",
|
||||||
|
X => "AES:0:1:32:0064:0080",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "9a79584225b518596b8c47db50399a14ff88d55d61aa586b0ff88ea9c00ed0e2629a81114787c076bf1ae9b0eb179ef6",
|
||||||
|
D => 0,
|
||||||
|
I => 1,
|
||||||
|
K => "e3aa3e958382a4b396cf038727f22b87",
|
||||||
|
N => "AES",
|
||||||
|
P => "b0b6f3342d2a11243f2e9b72551a68469a33dd0f9fed0d71ca3ab08df5ee20fadbafd65163d0028e",
|
||||||
|
X => "AES:0:1:32:0080:0096",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "fce2805f034ad6f6e91e0286577bd5ed1ba579e08c328d7de9e9013d2ddc5109ce3b06bdb7e28d992d8adace8e0a4d5bbf8a1f664bd78262c6d9b78a133a6d384709387c1ea9419b16910e219ee489d74f8cc1c733e27902e2f3f68b6f36a269b957253b042ef00fba2f342ad6a50684646291c212b27e4ede2c75ffa01a147c023d0731e7fe406988f73634947bf35080c8caa8f7c2da5e5276f6434f9e693ff646b2ea16c130097ef0745374568ec805cd04eb6e56bbfe50e1225ced3869ae2cd9bad58818f5afe65850d0b7e7b39d8365d537ac2f48c165c6daae86940665feaeae99ae944cb0ae3221f58a59a613a89395283c531ff1509b0d57223515a0ea2a78bebc4cf8a249a4850d93a87b5fa1b695db3251d2d12f569eee7e9900f629dc43878f921db811ab6319b09d26407b8df0bf981349da746ab2f712350220908d0b2d4ee62c913ddb2098af1fa1f40074a883d0bafbce87fad47c3e0e37e554af29857d79251d91ee6f5b9ffac12f543a248b757f3b99edd1030986dbed8fcec1c7131dc09a324d77e92be7e72989c27612125f0c4a1ab878c387cc7806eac130172b16c55baf43bce18190b830e5d37f9cdf7a6bfa31555f9eed1675fcaacec37341aa073949d9d69a97279646b0988d9bd3ff99162adb4056260a1724a72619e4edcd9182410aedebb31be4b61d0d02005d465f7c865bac306dd0d6f1fc14d9cb320c3615e1",
|
||||||
|
D => 0,
|
||||||
|
I => 1,
|
||||||
|
K => "a468dae7466a4605a18d957f88b29d91",
|
||||||
|
N => "AES",
|
||||||
|
P => "2301af19cf4b8e6b141d95e258ef2559226e123e75af343617af5d2a6e519e530fad4c62e02b65fe1881f97f2dd32e92bc63556324f62e322c2b19230c803d0cf9689e72daa40d8bc19b20a5986488e06047828d7ef8f94d2832b864abb20e18d661eb0645d22227321faba6bbd3ab2a7c4989613a558a5ed1a4ec70c60448a059d4e7e1149096e694dd22614e548b5da7039785530ffbfbadf650efd47f44cc57dc2af130122fe49fdf2a5ebd13021c4b7e05ea8d8bce229c2ab60b6414b8ac4f553a4662dacb256022bad4a8f72e51a5fe3e1b2de66df51b9e6e6b1b4338edaae992bf162c63c6db78ae2d892db24f812857402660002f48ef123d43063e50c602f2ff91caf4d13d7f10a4e92bb9d9e138a553869a8282f5914503ababa31bb41011f2e7dd9ce332400c4c16913edb13c92b4133204f3b4d7b16c507ec0c2559121ec1da668e485573decaa5014e227084af6eb75ada9b30d33e9420316929751cc2b2d23ce4a93ae59991dff9ac03474e1d74f89c70219e2038da1a67290633fde2f1c0fda31b86d040fc0659b2130ad4f1577a6a1a56f83a7b0eced5c2a362fa78a6875330cd0f92fbb0f6206db556454e9d6d7b89630c174747a83982cdc35dfb292379f50011ef1550d36d37c1a7967f7aa9dfc017f2b46780ac06b0cdc225a760fa99a6e6878ec894b700bd6e9c7b7aa02b4ef28dc888b4115d5fc34f",
|
||||||
|
X => "AES:0:1:32:1024:1040",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "efa5fb8f79d28a665c21ff94af6532db58903055c9f35028",
|
||||||
|
D => 0,
|
||||||
|
I => 1,
|
||||||
|
K => "602c451a52920a8b92ceda05db1238f432ea1f763535d949",
|
||||||
|
N => "AES",
|
||||||
|
P => "aa9c354b11848092201f29117be6f7a6",
|
||||||
|
X => "AES:0:1:48:0032:0048",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "8feb6db6b11c31ebb68a5b98267a33e87e02a21ba7459ee6c77de6b989d9fa74",
|
||||||
|
D => 0,
|
||||||
|
I => 1,
|
||||||
|
K => "b0a54fd8b064b68cc452d9c87d4e5b021e6749ccdff6ca3a",
|
||||||
|
N => "AES",
|
||||||
|
P => "009c7c1006ee154e2e8e5f5adcf72cd22664118b856e7fc7",
|
||||||
|
X => "AES:0:1:48:0048:0064",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "3cc1e7a52c3b7112782915ca24084e6e391e4c86482608961733caf462952fcb49f2171251d29b2c",
|
||||||
|
D => 0,
|
||||||
|
I => 1,
|
||||||
|
K => "7a1eaf2c21f6e92bbdb89fbb2cd0283ffff3e2ada6b862ce",
|
||||||
|
N => "AES",
|
||||||
|
P => "124bd817c0849c9b77a84178086e90a381db21a62fc43b313f4023792691e70a",
|
||||||
|
X => "AES:0:1:48:0064:0080",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "294294a20dcfd4f8b20b5105aedec366b776510bb30aae52bc9a00359b634248caaa4841766dd992ad477af54c4e3102",
|
||||||
|
D => 0,
|
||||||
|
I => 1,
|
||||||
|
K => "d2822cb9185ab6bafe423a7d52f66e0a25b7439d4755c0fc",
|
||||||
|
N => "AES",
|
||||||
|
P => "ef7c4998b8b4b2d75f3928c86ad3bd02704ae1255b7fa00b03356a07091d4b0af48d337d4b6bbf0b",
|
||||||
|
X => "AES:0:1:48:0080:0096",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "9948283f7b4085e2a234d013d4a6f36ec9a90445f64d29c093684e7c087c2669b44e2f6ccbebc28fbba0d57912b5e5876c27706a95671a5e15e373d69d834bed55ab835eb77c22363598ff2cd9ca8b5d8c53cb4b99b70f703ded71220b7dabc0dc4bc189a70f9e952c8eb58f631e21ac4e69fc36f5ca25c413a11f27177f94a3faf4746aac1185da3c44e8e1925d7b70fe0b250e379fa062327c52b1b828973cf7f80b45cc7d7297a8430245f44ca2f4d8a9a2a51d7d490e0864bfbf62c4661f56ba5264e702e7d7a21684bcae33e75a77e8b72bed1f0179465d76c5e9d69f9a909063455b196f395936115b72979f940ef3cce45bb2a6158368a88e11c73b1d6188fe0038a0e8665d48670b29f85a7c338ea28aaa06c1e6b7ec422bb5ccda0d90f2fbb8c21288088adf6ceabec8910f19e1b4b8855e504e23b2b03c5bb579e6a0e62396b95a28a5ad914db55c554fd19ba24bdb0d32afa82ae45723dd894bb67ec4973751e536339568bbebad2f7041186cc0ca23a406393440e9f8d499e3ff8208978cbdc55e741606aa6753dc474aa57f86d8cc06e8369401797b189abdbc5c51e23a15f1dc67323643a7b189e7c2f0ce8be3faabe3eeb23eb7720b99ffcc81f064d2fd699349b9f9a5028a956c656fc13772e52c9cd0d46517fb5f3db40f013a8460b83257250bfe7dd0fb5e460586ed4d7cac617b874948daa7f0e72e909367228a4589ac17",
|
||||||
|
D => 0,
|
||||||
|
I => 1,
|
||||||
|
K => "52a342bb23fd707a7fc37617e8f85aedc2db03ee11cdc126",
|
||||||
|
N => "AES",
|
||||||
|
P => "4b1b3189e39048e28a8b19b4aa82bd3f7f5f8c228991ffaede0e044dc8e2b0085e9f646b592b8f0fda3a188a050f4f69af74f17e37e95a3fbedbfdf98ca248a60ca014948087b0eebb3545322181b41b4add568bc0b410d33270c3e0002f6ffa6ab43c74968094cd35bb20babc3fe7c95e62e783faea8aa5c442fdd5e71b2121b329ad13be0da6f15e16558023ded7548494c679b4e3ee3978de709d85dbf5a1b18c729db83852c2e29e99a525c5e33367611200febdc77d95409fb2cdb82be4a77fe6cdaafe0a0f209aa6b494395d8dfeb5b7a7499ef22e03b8c933bf97e24775166e8cb27e1df37991a0153f252fe82c040a59c7a750c501a55d67da82147fc19036a6ac3c6ee3ed5931f800efe77e6c1d2ffe031029308e28c3d330b68e72d433baceb9b996d679070575cb851c2aadae8f51a415883f5c195c876ac16a27b658afbb86330e5967b137c9635c88fe803c953d49203d1f1e36e64ab44e7a1af76405dc3621dbd8fc11c58e94c7265fe1184a180362c50a5f2b8dc7543e260f4faac265df46ff4e9cc10abeb5396cb0eb50452ddcd848c1692ac0981ef31321bfa7e8e01c551bc39371fa2fa9326394b7d170b96628a52a3458706c453cce5aac379b8acab21842fe2af5518be6bc7e8fcb7a64e684b732422e49e703b3784ad5f73d4dadf1a3626a831b9b161082b815daae814cbb48f1ce79aeef4939c1f8",
|
||||||
|
X => "AES:0:1:48:1024:1040",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "46e5fa910879cd65c4d5f058612bf72ba5d51441024606e4",
|
||||||
|
D => 0,
|
||||||
|
I => 1,
|
||||||
|
K => "542cb39fc4238ddfe95f618c5b30a3fb188bd08c852cc979524c2451821f815c",
|
||||||
|
N => "AES",
|
||||||
|
P => "7c2b3a8e89bdaffba69367117ead7990",
|
||||||
|
X => "AES:0:1:64:0032:0048",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "a261c68c7a7469c9b3a01c6794e865a254e5c3e7e57d5056955b75dc60a06415",
|
||||||
|
D => 0,
|
||||||
|
I => 1,
|
||||||
|
K => "31a93c13a21f9a6163eac9ae15da8877a4b09edcf50d04c48516f1971cc88d04",
|
||||||
|
N => "AES",
|
||||||
|
P => "81b0f00ebcd04b3a6e88e7be76357c06a4cc391602a63d5c",
|
||||||
|
X => "AES:0:1:64:0048:0064",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "d8690b3327acda2d3029bd9a697074887476abfff5fae69e2f676aebcc5f47c39dca89fddb498044",
|
||||||
|
D => 0,
|
||||||
|
I => 1,
|
||||||
|
K => "aa595905d8006352490215d5f63ae6395fb759e1029d124099111aed6cf01e55",
|
||||||
|
N => "AES",
|
||||||
|
P => "c29717ff201f7e0af18b7e0620a9e8679e8a759effb5ffad2300897344072238",
|
||||||
|
X => "AES:0:1:64:0064:0080",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "01677010a5d047cf0a34c4f5a7ccc42126e4f7e6f47928f309857de9733d7832e85c315e4490d65c8cbc950673d06a9a",
|
||||||
|
D => 0,
|
||||||
|
I => 1,
|
||||||
|
K => "48c4119e6e34b28ec9992246821cd6ab2d3787d1c3f005e500014892895a21ef",
|
||||||
|
N => "AES",
|
||||||
|
P => "16dfa3e4d97cf599a13b8fdf9c34538d0ea8a12928dbe63044b805d68be3529d6291e4eb2251a0f5",
|
||||||
|
X => "AES:0:1:64:0080:0096",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "de8a69620e4d2eefb8287ba5fcb745630c24d65881eecb36daf1826263990bc1eba546f9f6cf1bf6ef8b73831c38fbd1e546e70c8338f5707b434ece94253a4cdeb483a5c8c533239a44bcc0d7c0e2c7a0b18027bc4f27a09f59367beb44688f95816e1bb296ae65f17578fc66939bee0e023521578e2f5ecf84198750643fd0631b5242ab47d01f5ede07212b307501722dbb2a12cc3c96c8253d1d1663ed259a45ec9bdb5c9dc261c05c25e3f06d08160a82433ab1370a3abd9a72047bbc2cc5ec3695bdef2bbf98f0b9e63bcd3e9dce12c31ece8b32516b4390e8246073b97fe6b7c34be4ac324f997074abade4f2456df63c13b50f89de6754ef543d4d11cb76e7eb6ae5c6429920d78d00b32c1839e4dfdea17e770b06e820343afd6dd8b899a5d802e4309a74ca7d7d6010d813f37e30bb3fac9c6ab985b0bc9825880d848b313714c895210c4d0107d9748bf04b599a58840b75041cb6e766fdb5f1bf1e530c31d12a4d4c5b6dab3fc26e9719381451573e791ce84da1ffc85536f0239436d0d481a9eaf27bec7d923c7f658037014d443dc8102f53bd11035d50b89c0792fa84b83f00bd87308a0fdec737c60e25768052cf4313e1fa837ebefb3ff666aa8c4bca9a9b38b911f1e364e5563689f973bcebf011d8de2d261fa419f05ed5377ab17a2ddc389fdeba85c93a3cc94af8d9de82add84030f192399049052529b8e58dabcede20",
|
||||||
|
D => 0,
|
||||||
|
I => 1,
|
||||||
|
K => "26e1ecc0c4d1ca3d757653fb2364dfe0c06b0e9e31b82cff7be190fe01627208",
|
||||||
|
N => "AES",
|
||||||
|
P => "8d2ed7a04a33b20047cf7b54927d7347d6b36823c14727e8cb12d305e1c1dc80bd42c3eadd9f6f094d6a3997eda34f9af4c8623d82d367b483886167cb4aee3e4c72854121fff6981a6516b949d21b2c944d60f133eefe3a2e53266f5bdbbb13cd92c42e7c6bd464b8f8cbfaebf23d9c7ef6c14b4041d76ae15567c68d42f732d6e87bbbc3f502e62ed512a7ebf95f57258d499fcfd87cf9ec9e9ff58ea545c3e7d241902994e666fbf1765a1633c627c29318daafb987cb57d63fde50c45b5d54c15f8da9c8baa3a2120b48667697442f8639999d2f4ea44671c06fee32828595d82bebf31da2f84aba77ed60b787a6096b53b08f9365f87a6b3a9d265a11d3cff7248e59bafdb996fb6ed64520ffc25bece8dae7e379ec3e7645ffdbde2489d09b927bdbe7da76d6b0e6b3d5b8901d0e4d534e14950382bf3e9a035143b88ad393ce2c3b0f9a668c11d40ce57651814872f0faee8ba5bc0e78f9c308452b8501ad5aef7ef9b4068837141d24a346a71a14f00063b7a3711b782d130a4cdf276134230dab1e91846602a352134a8c52be31e0da6b37b1a540f5474d4727aa99571696b092a933963f3317e302ac4a0d970d64ba3848f7eff0a082c4a6cbedb1282cbfbd46ca9d2c25f48a359fc639e675dc51973491e0a38c2150a8caf6bb9c044184a3dbbf58e89692d7e57a5afa31d65461fd93af8043647bd16a6a6b5936",
|
||||||
|
X => "AES:0:1:64:1024:1040",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "2ec966209352c959278dbfcefaf51c96",
|
||||||
|
D => 1,
|
||||||
|
I => 0,
|
||||||
|
K => "ab978bb18796ccbe45eaabefd6a13948",
|
||||||
|
N => "AES",
|
||||||
|
P => "1e",
|
||||||
|
X => "AES:1:0:32:0002:0032",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "e039ce098d8aeaf53ada5b8b634dace7",
|
||||||
|
D => 1,
|
||||||
|
I => 0,
|
||||||
|
K => "160fd350da87a5b5ec47af47a31dd39c",
|
||||||
|
N => "AES",
|
||||||
|
P => "b46952d9",
|
||||||
|
X => "AES:1:0:32:0008:0032",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "3ed08c1d1f5022ea0631ac70f29d5d5063aba7fde653d621",
|
||||||
|
D => 1,
|
||||||
|
I => 0,
|
||||||
|
K => "87e3893fa12f467e8e9a4b5ad9d98efa",
|
||||||
|
N => "AES",
|
||||||
|
P => "0fba5313c5181a46e3",
|
||||||
|
X => "AES:1:0:32:0018:0048",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "c7300d659ddb133f6cdaa600f8a0d0c1547d12b13fccf17a",
|
||||||
|
D => 1,
|
||||||
|
I => 0,
|
||||||
|
K => "7fc7a84392968735201b90eea55f57a3",
|
||||||
|
N => "AES",
|
||||||
|
P => "3addc5d1251aa009947f97cd",
|
||||||
|
X => "AES:1:0:32:0024:0048",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "d3226f55b4b4bb4644f5752aead6505b4fd3ca6e112fb2a4b0e97133ffba7fc2dcdaf6fb68966c1582623180218bee1b768488cc0754d3a7d89367273d9e355ede53e814202666b849c92b5af0f5b0fb816cfcaf3680d8c32a9c17f62224e0367a12f177b46168b282fd4eb1226985ad",
|
||||||
|
D => 1,
|
||||||
|
I => 0,
|
||||||
|
K => "92b6cc0b96b37c9830b37f94232c1c99",
|
||||||
|
N => "AES",
|
||||||
|
P => "d86a3ecd24b29196dee5de017b5ac4d7e9a15957953595035b46acf22d462730153f8b52befdcd6f5254f940bf178e3379cb460c5a5748c86cb34d963154dce269255fd95f97f01ed01bbea46834d91b0552d1537d73865e8d161f02b3ac0835fe02a31b73",
|
||||||
|
X => "AES:1:0:32:0202:0224",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "6db22bb35bd420e933a9acd713a237df",
|
||||||
|
D => 1,
|
||||||
|
I => 0,
|
||||||
|
K => "954aaa6920fd1a63f8fbfbe3b456d6d7dc97378c71b5bab3",
|
||||||
|
N => "AES",
|
||||||
|
P => "29",
|
||||||
|
X => "AES:1:0:48:0002:0032",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "2044d516bf94244b59c0eb34eb47ae9a",
|
||||||
|
D => 1,
|
||||||
|
I => 0,
|
||||||
|
K => "aca929cc3fe259c9c9383198424c4a52f90a07ecac6ac7bc",
|
||||||
|
N => "AES",
|
||||||
|
P => "8cf43d18",
|
||||||
|
X => "AES:1:0:48:0008:0032",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "01edb87ede6a4f66f7c8e3f66be199df676ac3868d0c9297",
|
||||||
|
D => 1,
|
||||||
|
I => 0,
|
||||||
|
K => "00b15609bda6bddad33128aa259044d61b0906f27e6df66d",
|
||||||
|
N => "AES",
|
||||||
|
P => "f0095af008a5433bc7",
|
||||||
|
X => "AES:1:0:48:0018:0048",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "d3cdc2a5bd9c95f30ea571b6da2ffd726bc2e3e2b963228c",
|
||||||
|
D => 1,
|
||||||
|
I => 0,
|
||||||
|
K => "c4e0a649c6cc8afd9b5bafd373da0e54012858c77519bd9e",
|
||||||
|
N => "AES",
|
||||||
|
P => "7e1414138e3701e8bbd70524",
|
||||||
|
X => "AES:1:0:48:0024:0048",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "8d138bc57b2e2b19bef1c95a91403bb791a3f2df47a5f2d45bc96aeebff9bb5d0d80be06c9b9cd7bf2c390f457ebaf8ab594177c8a696af28fb0274639c78ee5fbf74e249fffe202056c218d391e7c64034a837072986f82b110e7963a0d7f7a35e62d97b3b524b00caf723a581d497a",
|
||||||
|
D => 1,
|
||||||
|
I => 0,
|
||||||
|
K => "2c4d89e8fd17ecb20bbda47071ec798bf638a570e19c6e79",
|
||||||
|
N => "AES",
|
||||||
|
P => "4a4301be175d9d3f3a1ffa904a645e42b92bfcffe12a0260b59e4906ee8be455423647a55b953f8b8879fc5ece14e0e36487b327dabe1f26f6247205015573355bb0fc8ffabdfb3352bf6ed7f21b62c04d4ea4ffb3e35924826c64fc0ab2f43519d6d5386a",
|
||||||
|
X => "AES:1:0:48:0202:0224",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "ce1f839cdaf7a85f3a65218a4e677fe9",
|
||||||
|
D => 1,
|
||||||
|
I => 0,
|
||||||
|
K => "3fae5121c5ce495b012bf13fd6c5242c539b31e637aecc56b75957d1d11604d3",
|
||||||
|
N => "AES",
|
||||||
|
P => "43",
|
||||||
|
X => "AES:1:0:64:0002:0032",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "0a6d5b0d980d4e3c64263d611e89326b",
|
||||||
|
D => 1,
|
||||||
|
I => 0,
|
||||||
|
K => "6f7de62109e5ced236c9aa22141569787b6637048598345655b7bea7a0b940ae",
|
||||||
|
N => "AES",
|
||||||
|
P => "4289859e",
|
||||||
|
X => "AES:1:0:64:0008:0032",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "fb5df4509ccc171043358e576678c8d72744d175886d450a",
|
||||||
|
D => 1,
|
||||||
|
I => 0,
|
||||||
|
K => "f63f1d6899fe5a1f8038d0be7d39de9e7f6d25c11e94f21ed3e8cdfc1d007f8d",
|
||||||
|
N => "AES",
|
||||||
|
P => "9d30e7bf7f9e8d3f6a",
|
||||||
|
X => "AES:1:0:64:0018:0048",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "4ef13238834b1389b90888995332c2f1461d85439086770b",
|
||||||
|
D => 1,
|
||||||
|
I => 0,
|
||||||
|
K => "7134f05007d37985bc7f68f92409aef0ece671b397157307a38103a2f2ba8597",
|
||||||
|
N => "AES",
|
||||||
|
P => "083436d3dfa539900b6a7485",
|
||||||
|
X => "AES:1:0:64:0024:0048",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "45691a184ae6cd921f39bdc497383f7cea822df53e009b224e35feee61af962bfd6c63706dd7c5fca35398ffb0200127775efc35dd1dd847b3191a2b3730b7923c8d31db6422e5b0e878338ac599c2d478b99848b25defb8b3219ac3deaa3ac30390b8986ce4523f30ea4ccde080a434",
|
||||||
|
D => 1,
|
||||||
|
I => 0,
|
||||||
|
K => "ab9583bd52cec5bc0e52ecb491b3463809b44cf52bca44bb6f5e4d1003db9d17",
|
||||||
|
N => "AES",
|
||||||
|
P => "1870bf704cbde83813c1346ac787d6542ae3cfdb8f0a6fa8e3e66de6394025d42d2c2acb3f1d8b32cd28269e05aeaa227688ae0142681088d49906bd03e1d7d7233f48243bf30ae34d0e953f4ea9bac3c0fcf149089822f8c2afe885a7ec91f08374313706",
|
||||||
|
X => "AES:1:0:64:0202:0224",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "1be58ef58c742d1fc205915bbbb19152",
|
||||||
|
D => 1,
|
||||||
|
I => 1,
|
||||||
|
K => "79f85745de77103bce1c12220867791d",
|
||||||
|
N => "AES",
|
||||||
|
P => "13",
|
||||||
|
X => "AES:1:1:32:0002:0032",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "bc50b78e685ef73946e05c628da34084",
|
||||||
|
D => 1,
|
||||||
|
I => 1,
|
||||||
|
K => "e97a03ceb118e8ecd6828094f93435b5",
|
||||||
|
N => "AES",
|
||||||
|
P => "8787cdc8",
|
||||||
|
X => "AES:1:1:32:0008:0032",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "93bbe69d48c9ce29ea3bb60785d127349423f2e18a30e57f",
|
||||||
|
D => 1,
|
||||||
|
I => 1,
|
||||||
|
K => "df1c32e0c1cc317945a50910affe6183",
|
||||||
|
N => "AES",
|
||||||
|
P => "52b63a559b659b81e3",
|
||||||
|
X => "AES:1:1:32:0018:0048",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "df4b237e5cd1f91b72136dbcdcaa8c4b39778d6cbcf6832e",
|
||||||
|
D => 1,
|
||||||
|
I => 1,
|
||||||
|
K => "2a3597930117b03a9f7dfae8622486ac",
|
||||||
|
N => "AES",
|
||||||
|
P => "6d6f08585e7eea010b611b35",
|
||||||
|
X => "AES:1:1:32:0024:0048",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "9604f8ac3413b5ce23fb82622e8e60ca5ba4b90bcdf0a52acf52401ce67809dc0e26b0f2f51000be50fe284cdb1ad9fce21a2f969da2392ac7c0822d96aafa082f527149f2fb76ba2a3307d62106f8df3c071a180213b1e7483e32e1dbb00fd47d66ce8f729aad91059533f25351fa4e",
|
||||||
|
D => 1,
|
||||||
|
I => 1,
|
||||||
|
K => "eb542f7099600a16ede45a8379c7e727",
|
||||||
|
N => "AES",
|
||||||
|
P => "cae927d387c72ce134885502fc094363326f0d68df297db84fb8291cdf6892ae29814de9f45a93e8ad32c1b330869a29d660f669c0314d54a8804caf5e7d6d18e8369e3bbd21c9e40b102cfc77c2f6f79209c0e4f5a90757d067fd1aea101115c9cf0ff066",
|
||||||
|
X => "AES:1:1:32:0202:0224",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "6ab04a9159d271b1c335697d63f3a0e2",
|
||||||
|
D => 1,
|
||||||
|
I => 1,
|
||||||
|
K => "3b388df94ce8e629af07b483513609fd6affaedf62eea248",
|
||||||
|
N => "AES",
|
||||||
|
P => "38",
|
||||||
|
X => "AES:1:1:48:0002:0032",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "d70db3c10273a5c362fb3891f016010a",
|
||||||
|
D => 1,
|
||||||
|
I => 1,
|
||||||
|
K => "1e5154438b543de803de95592bc780e317d2aaed1e17ad38",
|
||||||
|
N => "AES",
|
||||||
|
P => "af04adb8",
|
||||||
|
X => "AES:1:1:48:0008:0032",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "9ac19f6f214e8589821d8f1d70a741ec00d256c985624c27",
|
||||||
|
D => 1,
|
||||||
|
I => 1,
|
||||||
|
K => "2b6bf835bd4510cdc860d95a2c1085b9a2f7900c184526f1",
|
||||||
|
N => "AES",
|
||||||
|
P => "b72935458e3b310103",
|
||||||
|
X => "AES:1:1:48:0018:0048",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "4f030ac89686a214d1fdf9258bedd8d95644730bbfca9e75",
|
||||||
|
D => 1,
|
||||||
|
I => 1,
|
||||||
|
K => "6d115bcb39d5d76bfda9ea47fd7dbb9935a0e973e647519a",
|
||||||
|
N => "AES",
|
||||||
|
P => "b7f6b214ee4f852276d59f21",
|
||||||
|
X => "AES:1:1:48:0024:0048",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "6f018113edd2b3fde7f0862bc29cdf61715aee28f60cc6a64eb8f8c69d636511fc359a7198644b2da4c0dad4939f99d2a9adf8297a358bd5403b919107e354b685d6ee96c20d9270b27e27a0acd744c5d80c42869376c7a705acb4a7ee5ced56fb0f90e45325c7df8a2527d3cc8896b1",
|
||||||
|
D => 1,
|
||||||
|
I => 1,
|
||||||
|
K => "222716cf9d410f8ece79f82ae038ee9a80ce5709bb173968",
|
||||||
|
N => "AES",
|
||||||
|
P => "bcce5c159a9e8802ced0bb50cfa788ba4dc63caa6e2ccaaf3527285bfa0a17c110c63df4691d80f6ef804e78f372be25af286139340383eb55dab74d92a72f47804891e5d5ef7395536cf9cc6bfec6c14e7294225a078f8d5b77c5495d7bcc738a91a151fe",
|
||||||
|
X => "AES:1:1:48:0202:0224",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "a205fd2c3fc63fe47b62158bab2e5e85",
|
||||||
|
D => 1,
|
||||||
|
I => 1,
|
||||||
|
K => "cd150528ff9b9c893d907f3186a3d39e7c7ddb76045ce182cebb57f3a7bd93e4",
|
||||||
|
N => "AES",
|
||||||
|
P => "e4",
|
||||||
|
X => "AES:1:1:64:0002:0032",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "efe397b6f49a26c55b3fce003effb1ac",
|
||||||
|
D => 1,
|
||||||
|
I => 1,
|
||||||
|
K => "24deb093ada160eb0730c6feb55461ffd29a5e8d149cce1a100de48bcd99c358",
|
||||||
|
N => "AES",
|
||||||
|
P => "8b2f0549",
|
||||||
|
X => "AES:1:1:64:0008:0032",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "753ff2767c4d1b6de70046fe19393fc7e0d3832fe142c92a",
|
||||||
|
D => 1,
|
||||||
|
I => 1,
|
||||||
|
K => "7d5d5d7e6358553c4e62579cde319f7281a1cf7ab0ddd75c33553bef528f0f9e",
|
||||||
|
N => "AES",
|
||||||
|
P => "efe51c572741253043",
|
||||||
|
X => "AES:1:1:64:0018:0048",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "fd5d5750fc8b9db9783645815a9c3936b0e515cc35b953c7",
|
||||||
|
D => 1,
|
||||||
|
I => 1,
|
||||||
|
K => "914cd9c46121f073064bfbcc1a98c9ab1a395e52255641cbc299632a952e15a7",
|
||||||
|
N => "AES",
|
||||||
|
P => "b78624855ceeb1ed6331a653",
|
||||||
|
X => "AES:1:1:64:0024:0048",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "24badd566fb5da237de770be86b50b9dbe72113a50b5d85708f2e0a3db42cf6d6a197654f1b87e0a73100e78b08d9ffae7fb19e6181ee82995523f00a62b41e065e98d9173d8cc467c7eacbd76350c0fcdfd293fc5ceb635b180eadc3920475271e3323b409e5fc75159c6c878310e50",
|
||||||
|
D => 1,
|
||||||
|
I => 1,
|
||||||
|
K => "174cc4d43afbf5da1f0eb43ba7fb020596bc9a72fce9c2541a9b3f81a08c95e6",
|
||||||
|
N => "AES",
|
||||||
|
P => "c4c70e1de9911430b8d77346e8114db0345638d4dca5ede2aeeaf8e830a7f02ec0ed9d675d61ef410809188de380f5673b746b2818999895a71f835d76074b550a6570896577c90027c7f5508fade8213615f5a56d02d2acac2ce7c98da371c6c94dfbf410",
|
||||||
|
X => "AES:1:1:64:0202:0224",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "d8ec69150ba3980aea57ae4a",
|
||||||
|
D => 0,
|
||||||
|
I => 0,
|
||||||
|
K => "09a638783af66b908137c4d3361c1ae152081195fee41dea",
|
||||||
|
N => "DES_EDE",
|
||||||
|
P => "965ee3269f2b0a28",
|
||||||
|
X => "DES_EDE:0:0:48:0016:0024",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "6f08140b29a5bdc7ee5cf023df19a40f",
|
||||||
|
D => 0,
|
||||||
|
I => 0,
|
||||||
|
K => "df77cfba77e3087ec8fd1b79a8ac5d41c4b7708a9a037a48",
|
||||||
|
N => "DES_EDE",
|
||||||
|
P => "2a42f3c55aa2b2a9cb6d2af3",
|
||||||
|
X => "DES_EDE:0:0:48:0024:0032",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "960d2f3e0616d00c53a082b4d1b9da833bb31d79",
|
||||||
|
D => 0,
|
||||||
|
I => 0,
|
||||||
|
K => "9ab6db4073be11e46b8c5bf4957956395ac87f98727b52d8",
|
||||||
|
N => "DES_EDE",
|
||||||
|
P => "a9cebce4d9a24720e7676eea61674d91",
|
||||||
|
X => "DES_EDE:0:0:48:0032:0040",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "d845253b5fa0a55f0f7407060dc2c2753b1e4b3132b8039e",
|
||||||
|
D => 0,
|
||||||
|
I => 0,
|
||||||
|
K => "3a41eaffde08c438aeffc755dafc59d1462c556a7737490a",
|
||||||
|
N => "DES_EDE",
|
||||||
|
P => "455c114fca3c2d06c0a717099f3141ef562a79c8",
|
||||||
|
X => "DES_EDE:0:0:48:0040:0048",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "a2e8adccaf3c860d22ebc16ab71af0777d02336feb74f46306fc9f2291100b249b250bd67fa67b6c98743a4549fd8f37a7457f50adc10f32e6b289b62bdd53dfc955e29e695a28c2ebe0a9de6176b8053e91181e31c90ac5b6da155f64f3f8712a8c780269752852d648ff1cb21137e1c919679aca0e886a40bf6454952525fc92910733f6d8ac1933f76a247a612aefb00431da8b3a72d23b4358437c9c33150ce96ae297cd403c5d8f8c70b9b84aec5789705da7027d94b23fb4d406fc428e1abab3800a499f009fae12e417f1d392b497a795034edf25c3f31cabcb16f1fa88f9bdbd50276df7ecaea3fe58268e987be02ff08307dbe8933b5942a4677b12729aaa22",
|
||||||
|
D => 0,
|
||||||
|
I => 0,
|
||||||
|
K => "eeecc916cd4f6971f43743a5d8a70e1fe74c1dd22983ddd7",
|
||||||
|
N => "DES_EDE",
|
||||||
|
P => "c6cc6ff311ba309831452f316efa53c4a4f62dc35fb7291d3dc361e76246eb9f51cc171fcfeb0579d9b77d950a3edffc756a4c4d9e3fc6eb439f29153549f377442f9d30b31ff25a0c3949dfa4da60f9c26cde4dbfe6d31f1fce1afc8da2a11b06a41807c1956c30406bd00ac4ece42077d055aa2224c73d73524da5710156aa4ec39b92a630cbee4a5d54a877598cbeaa8e6f85b75c82e5d717e013b0be25b59a0e1dfa7b6112519b00f191c95398269c23c783e1af23f7917dc84472f59e7d8626b3b49aa28b842e73603fe81eed72b6ee1c8534108163fae7810650b8f25d58e7422cbb59f168f72ad2aeb4800c39cb28d4ac654bc039a000d865693faf11",
|
||||||
|
X => "DES_EDE:0:0:48:0512:0520",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "a79c4069abc19f616412df22",
|
||||||
|
D => 0,
|
||||||
|
I => 1,
|
||||||
|
K => "73613eaaa529180cae20da0d8bdedb75712e7ffe7edbae36",
|
||||||
|
N => "DES_EDE",
|
||||||
|
P => "fd5affd829c11b4e",
|
||||||
|
X => "DES_EDE:0:1:48:0016:0024",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "dcf83900419ff3ecd23e3d93c23f7d00",
|
||||||
|
D => 0,
|
||||||
|
I => 1,
|
||||||
|
K => "c85b88faf497044b3ca8965509e656a4af5c7015cac8e0b6",
|
||||||
|
N => "DES_EDE",
|
||||||
|
P => "c1663e44cc68863b7e5d2acd",
|
||||||
|
X => "DES_EDE:0:1:48:0024:0032",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "bedcdc798bd4221c0337921d9c647c470ea03773",
|
||||||
|
D => 0,
|
||||||
|
I => 1,
|
||||||
|
K => "57bc800aca05d2716b0821f33bf90abd5935697ae923f037",
|
||||||
|
N => "DES_EDE",
|
||||||
|
P => "0b94f181769412bc82f5c4aedfb8ecc1",
|
||||||
|
X => "DES_EDE:0:1:48:0032:0040",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "38b18fbc37790e873071f8f6169e3a4feb1d15ec215fddf8",
|
||||||
|
D => 0,
|
||||||
|
I => 1,
|
||||||
|
K => "8461e5aaa4591328e2e80df6244c2f94d8c412bcd8d0b1a2",
|
||||||
|
N => "DES_EDE",
|
||||||
|
P => "10b25e11a6b393913a0ff5f6fc9d255bc196647f",
|
||||||
|
X => "DES_EDE:0:1:48:0040:0048",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
C => "1f5b622e928c595f5afb203daaf378a1735a5befb11e13d0a71343a3f1594be95e5e5e753c958f2e0c6c8f8c61cd320feb69a54a0cd1e442f992593d2d2743d0bbc0cdfd5f21b22c53e27f25ecf77639f38d9fd490c97ba37df3af8fe9656a118d7a2c69f25a75c47fe5b34883469bb43614734bfadd22610a5a297ed437d3bb9fdd50c05a04a2f1b952385dec6461f9301205c73fd5af0b3f382f4b3d283351e7f6d4b71861c788df787866df8dfa3fbf4b72e10603787011e829497c5a29726e94cd05c26edadf45e69f8073ecd9bcb04d48bfbe49f7e7c082eb510f2cdd4786f5e012276f1ec49fd45e20043b7feae815db0c14863aa3a403e1d808102e5cd45d3f55",
|
||||||
|
D => 0,
|
||||||
|
I => 1,
|
||||||
|
K => "f1ad7c02d3c4f0ea93ebb210a1817c67a3303c4bd3c368a3",
|
||||||
|
N => "DES_EDE",
|
||||||
|
P => "de1886bc77723049d735181560083b180d8358facee0c75519941ca47ccd8b41b6ea0c38fa83d34a80d291cf736beeadadafa691ae35dc6bf8eb5f5660d99ed95e769cc66be5a43ddd6c39dfe2fd4ad679955cf8e00a0f87254b89a901466e8c7da174bcfbbb7145e75e42a0a0383049e93e04c20a110b8a6cdc8f72e30133127a8195575bfcf824e713ee7b7243193330a5b3aec383ed8bf552f6e95bd3e0fe7fc48f57d46e716e61f777c87b3e59ded46f6ec3bb2f9e1e90f088a84b4a6c35855d754706255d35707f427ccfafd513455b849cdb59b90caf505eb874ff93c278acf6afd92cdaf994e9083da0873403175a7b0614982f73e38973cf05fa16f4",
|
||||||
|
X => "DES_EDE:0:1:48:0512:0520",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
{
|
||||||
|
# https://www.ietf.org/rfc/rfc3394.txt
|
||||||
|
my $kek = pack("H*", "000102030405060708090a0b0c0d0e0f1011121314151617");
|
||||||
|
my $keydata = pack("H*", "00112233445566778899aabbccddeeff");
|
||||||
|
my $wrap = aes_key_wrap($kek, $keydata);
|
||||||
|
is(unpack("H*", $wrap), "96778b25ae6ca435f92b5b97c050aed2468ab8a17ad84e5d");
|
||||||
|
my $unwrap = aes_key_unwrap($kek, $wrap);
|
||||||
|
is(unpack("H*", $unwrap), "00112233445566778899aabbccddeeff");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
# https://www.ietf.org/rfc/rfc3394.txt
|
||||||
|
my $kek = pack("H*", "000102030405060708090a0b0c0d0e0f");
|
||||||
|
my $keydata = pack("H*", "00112233445566778899aabbccddeeff");
|
||||||
|
my $wrap = aes_key_wrap($kek, $keydata);
|
||||||
|
is(unpack("H*", $wrap), "1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5");
|
||||||
|
my $unwrap = aes_key_unwrap($kek, $wrap);
|
||||||
|
is(unpack("H*", $unwrap), "00112233445566778899aabbccddeeff");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
# https://tools.ietf.org/html/rfc5649
|
||||||
|
my $kek = pack("H*", "5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8");
|
||||||
|
my $keydata = pack("H*", "c37b7e6492584340bed12207808941155068f738");
|
||||||
|
my $wrap = aes_key_wrap($kek, $keydata);
|
||||||
|
is(unpack("H*", $wrap), "138bdeaa9b8fa7fc61f97742e72248ee5ae6ae5360d1ae6a5f54f373fa543b6a");
|
||||||
|
my $unwrap = aes_key_unwrap($kek, $wrap);
|
||||||
|
is(unpack("H*", $unwrap), "c37b7e6492584340bed12207808941155068f738");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
# https://tools.ietf.org/html/rfc5649
|
||||||
|
my $kek = pack("H*", "5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8");
|
||||||
|
my $keydata = pack("H*", "466f7250617369");
|
||||||
|
my $wrap = aes_key_wrap($kek, $keydata);
|
||||||
|
is(unpack("H*", $wrap), "afbeb0f07dfbf5419200f2ccb50bb24f");
|
||||||
|
my $unwrap = aes_key_unwrap($kek, $wrap);
|
||||||
|
is(unpack("H*", $unwrap), "466f7250617369");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
# https://tools.ietf.org/html/draft-ietf-jose-json-web-encryption
|
||||||
|
my $keydata = join '', map { chr($_) } (4, 211, 31, 197, 84, 157, 252, 254, 11, 100, 157, 250, 63, 170, 106, 206, 107, 124, 212, 45, 111, 107, 9, 219, 200, 177, 0, 240, 143, 156, 44, 207);
|
||||||
|
my $kek = decode_b64u("GawgguFyGrWKav7AX4VKUg");
|
||||||
|
my $ct = decode_b64u("6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ");
|
||||||
|
my $wrap = aes_key_wrap($kek, $keydata);
|
||||||
|
is(unpack("H*", $wrap), unpack("H*",$ct));
|
||||||
|
my $unwrap = aes_key_unwrap($kek, $wrap);
|
||||||
|
is(unpack("H*", $unwrap), unpack("H*",$keydata));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (@tv) {
|
||||||
|
my $kek = pack("H*", $_->{K});
|
||||||
|
my $keydata = pack("H*", $_->{P});
|
||||||
|
my $wrap = aes_key_wrap($kek, $keydata, $_->{N}, $_->{D}, $_->{I});
|
||||||
|
is(unpack("H*", $wrap), $_->{C});
|
||||||
|
my $unwrap = aes_key_unwrap($kek, $wrap, $_->{N}, $_->{D}, $_->{I});
|
||||||
|
is(unpack("H*", $unwrap), $_->{P});
|
||||||
|
}
|
||||||
|
|
||||||
|
done_testing;
|
81
t/kw_ecdh.t
Normal file
81
t/kw_ecdh.t
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Test::More;
|
||||||
|
use Crypt::KeyWrap qw(ecdh_key_wrap ecdh_key_unwrap);
|
||||||
|
use Crypt::PK::ECC;
|
||||||
|
use Crypt::Misc qw(decode_b64u);
|
||||||
|
|
||||||
|
my $kek_private=Crypt::PK::ECC->new(\'{"kty":"EC","crv":"P-256","x":"BHId3zoDv6pDgOUh8rKdloUZ0YumRTcaVDCppUPoYgk","y":"g3QIDhaWEksYtZ9OWjNHn9a6-i_P9o5_NrdISP0VWDU","d":"KpTnMOHEpskXvuXHFCfiRtGUHUZ9Dq5CCcZQ-19rYs4"}');
|
||||||
|
|
||||||
|
{
|
||||||
|
my $header={
|
||||||
|
alg => "ECDH-ES",
|
||||||
|
enc => "A128CBC-HS256",
|
||||||
|
epk => {
|
||||||
|
crv => "P-256",
|
||||||
|
kty => "EC",
|
||||||
|
x => "-VMKLnMyoHTtFRZF6qW6wdFnA7mJBGb798WqU0UwAXY",
|
||||||
|
y => "hPAcQy83U-5B9uSmqnsWpVsluhdbRdMgnvtpgf5XWN8",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
my $expected_hex='81cbc97bcec94c11f704a10057ecde25d0c2ad56821e15816e98308bafdf8a5c';
|
||||||
|
my $unw = ecdh_key_unwrap($kek_private, $header->{enc}, $header->{epk}, $header->{apu}, $header->{apv});
|
||||||
|
is(unpack("H*", $unw), $expected_hex, "ECDH-ES + A128CBC-HS256")
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
my $header={
|
||||||
|
alg => "ECDH-ES",
|
||||||
|
enc => "A128GCM",
|
||||||
|
epk => {
|
||||||
|
crv => "P-256",
|
||||||
|
kty => "EC",
|
||||||
|
x => "Ol7jIi8H1iE1krvQNaPxjy-q-czP0N4EWO3R7584hGU",
|
||||||
|
y => "MdSeu9Snukp9lKde9rUnbjxkz3m_dMjjAw94WwCLZks",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
my $expected_hex='20fdcc92d30215765cb346805b5335c1';
|
||||||
|
my $unw = ecdh_key_unwrap($kek_private, $header->{enc}, $header->{epk}, $header->{apu}, $header->{apv});
|
||||||
|
is(unpack("H*", $unw), $expected_hex, "ECDH-ES + A128GCM")
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
my $header={
|
||||||
|
alg => "ECDH-ES",
|
||||||
|
enc => "A192GCM",
|
||||||
|
epk => {
|
||||||
|
crv => "P-256",
|
||||||
|
kty => "EC",
|
||||||
|
x => "PTwTYgcCK6iPn5D8Ne0HiDDmzoCiEaiJsH7C2pCEpsc",
|
||||||
|
y => "7gT2OTk-q9Ekkj8N58Gx-J6_ckqtgYeO0Drgq6IaOXc",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
my $expected_hex='4183d0802022bd2fc68231a7896c1846cdb022f335b68b97';
|
||||||
|
my $unw = ecdh_key_unwrap($kek_private, $header->{enc}, $header->{epk}, $header->{apu}, $header->{apv});
|
||||||
|
is(unpack("H*", $unw), $expected_hex, "ECDH-ES + A192GCM")
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
my $header={
|
||||||
|
alg => "ECDH-ES",
|
||||||
|
enc => "A256GCM",
|
||||||
|
epk => {
|
||||||
|
crv => "P-256",
|
||||||
|
kty => "EC",
|
||||||
|
x => "mExbMerMmx_o3fGmCtM4LwRPNsDlG4MDL55wjc7wpL8",
|
||||||
|
y => "C--vuVTv8XXS9qOZm_ZYqNxXn-bDWFLCeL1M6QKjIbY",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
my $expected_hex='4ddc0f6249fb5a4f1c908cc9fbf27e1a1d275e601bd23079851a0af7a8f18646';
|
||||||
|
my $unw = ecdh_key_unwrap($kek_private, $header->{enc}, $header->{epk}, $header->{apu}, $header->{apv});
|
||||||
|
is(unpack("H*", $unw), $expected_hex, "ECDH-ES + A256GCM")
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
my $kek_public=Crypt::PK::ECC->new(\$kek_private->export_key_jwk('public'));
|
||||||
|
my ($k1, $epk) = ecdh_key_wrap($kek_public, "A256GCM");
|
||||||
|
my $k2 = ecdh_key_unwrap($kek_private, "A256GCM", $epk);
|
||||||
|
is(unpack("H*", $k2), unpack("H*", $k1), "wrap+unwrap ECDH-ES");
|
||||||
|
}
|
||||||
|
|
||||||
|
done_testing;
|
68
t/kw_ecdhaes.t
Normal file
68
t/kw_ecdhaes.t
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Test::More;
|
||||||
|
use Crypt::KeyWrap qw(ecdhaes_key_wrap ecdhaes_key_unwrap);
|
||||||
|
use Crypt::PK::ECC;
|
||||||
|
use Crypt::Misc qw(decode_b64u);
|
||||||
|
|
||||||
|
my $kek_private=Crypt::PK::ECC->new(\'{"kty":"EC","crv":"P-256","x":"BHId3zoDv6pDgOUh8rKdloUZ0YumRTcaVDCppUPoYgk","y":"g3QIDhaWEksYtZ9OWjNHn9a6-i_P9o5_NrdISP0VWDU","d":"KpTnMOHEpskXvuXHFCfiRtGUHUZ9Dq5CCcZQ-19rYs4"}');
|
||||||
|
|
||||||
|
{
|
||||||
|
my $header={
|
||||||
|
alg => "ECDH-ES+A128KW",
|
||||||
|
enc => "A128GCM",
|
||||||
|
epk => {
|
||||||
|
crv => "P-256",
|
||||||
|
kty => "EC",
|
||||||
|
x => "6ysUfUwOoUlD5JFdojPqWxWwfBwokmZjNVlIDQkpmO0",
|
||||||
|
y => "JeZbk_Pk22mj0TU0pnnB3UiL2K2IqYzNM1UTOe-JcwY",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
my $ct_hex='7b59f7613a2b249f87ede59bcbea5f196cd5c7468349c093';
|
||||||
|
my $expected_hex='db216b638fb064b0f3cf64a0ac73735e';
|
||||||
|
my $unw = ecdhaes_key_unwrap($kek_private, pack("H*", $ct_hex), $header->{alg}, $header->{epk}, $header->{apu}, $header->{apv});
|
||||||
|
is(unpack("H*", $unw), $expected_hex, "ECDH-ES+A128KW");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
my $header={
|
||||||
|
alg => "ECDH-ES+A192KW",
|
||||||
|
enc => "A192GCM",
|
||||||
|
epk => {
|
||||||
|
crv => "P-256",
|
||||||
|
kty => "EC",
|
||||||
|
x => "Ya1BV1IYxEohUcIrXCAOOzKe0POMuBPIf2dR6kMeSts",
|
||||||
|
y => "SUujcsl0vfiJn1u_4Y59MMJ5uFGcUZEBTWPu54ARgEE",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
my $ct_hex='c293eb5065530ecb616814ee4e88f90f9d4ef9b6d2242070983abb94ae25f1d1';
|
||||||
|
my $expected_hex='919ef94365dd2fcca9abf69ee51258c7424e39c05e5f4ea0';
|
||||||
|
my $unw = ecdhaes_key_unwrap($kek_private, pack("H*", $ct_hex), $header->{alg}, $header->{epk}, $header->{apu}, $header->{apv});
|
||||||
|
is(unpack("H*", $unw), $expected_hex, "ECDH-ES+A192KW");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
my $header={
|
||||||
|
alg => "ECDH-ES+A256KW",
|
||||||
|
enc => "A256GCM",
|
||||||
|
epk => {
|
||||||
|
crv => "P-256",
|
||||||
|
kty => "EC",
|
||||||
|
x => "ANTg-K8YAUuOk0mQmZLDPUiOqVEPPk-Pf6kRtn6cB2s",
|
||||||
|
y => "lJi7PLEDe6ZwqJ46jZr-FmPzyswFkpdIU7ZU34t8EDs",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
my $ct_hex='22aa77c37c68d76c02ab2355ffcc0d9379b6b472a9066bfae97011b1c1de2ed652fb616c9406df0d';
|
||||||
|
my $expected_hex='bf9279a16dd7f284204387bcf9220c0ae9c6061c50ad28d7a42be6a902aedae3';
|
||||||
|
my $unw = ecdhaes_key_unwrap($kek_private, pack("H*", $ct_hex), $header->{alg}, $header->{epk}, $header->{apu}, $header->{apv});
|
||||||
|
is(unpack("H*", $unw), $expected_hex, "ECDH-ES+A256KW");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
my $kek_public=Crypt::PK::ECC->new(\$kek_private->export_key_jwk('public'));
|
||||||
|
my ($wrp, $epk) = ecdhaes_key_wrap($kek_public, 'plaintext', "ECDH-ES+A256KW");
|
||||||
|
my $unw = ecdhaes_key_unwrap($kek_private, $wrp, "ECDH-ES+A256KW", $epk);
|
||||||
|
is($unw, 'plaintext', "wrap+unwrap ECDH-ES+A256KW");
|
||||||
|
}
|
||||||
|
|
||||||
|
done_testing;
|
25
t/kw_gcm.t
Normal file
25
t/kw_gcm.t
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Test::More;
|
||||||
|
use Crypt::KeyWrap qw(gcm_key_wrap gcm_key_unwrap);
|
||||||
|
use Crypt::Misc qw(decode_b64u);
|
||||||
|
|
||||||
|
{
|
||||||
|
### test vector from https://github.com/rohe/pyjwkest/blob/5c1e321237dd2affb8b8434f0ca2a15c4da5e2b1/src/jwkest/aes_gcm.py
|
||||||
|
my $iv = pack("H*", 'cafebabefacedbaddecaf888');
|
||||||
|
my $kek = pack("H*", 'feffe9928665731c6d6a8f9467308308');
|
||||||
|
my $pt = pack("H*", 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39');
|
||||||
|
my $ct = pack("H*", '42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091');
|
||||||
|
my $aad = pack("H*", 'feedfacedeadbeeffeedfacedeadbeefabaddad2');
|
||||||
|
my $tag = pack("H*", '5bc94fbc3221a5db94fae95ae7121a47');
|
||||||
|
|
||||||
|
my $rv_pt = gcm_key_unwrap($kek, $ct, $tag, $iv, $aad, 'AES');
|
||||||
|
is(unpack("H*", $rv_pt), unpack("H*", $pt), "unwrap aes_gcm.py test vector");
|
||||||
|
|
||||||
|
my ($rv_ct, $rv_tag, $rv_iv) = gcm_key_wrap($kek, $pt, $aad, 'AES', $iv);
|
||||||
|
is(unpack("H*", $rv_ct), unpack("H*", $ct), "wrap aes_gcm.py test vector / ct");
|
||||||
|
is(unpack("H*", $rv_iv), unpack("H*", $iv), "wrap aes_gcm.py test vector / iv");
|
||||||
|
is(unpack("H*", $rv_tag), unpack("H*", $tag), "wrap aes_gcm.py test vector / tag");
|
||||||
|
}
|
||||||
|
|
||||||
|
done_testing;
|
30
t/kw_pbes2.t
Normal file
30
t/kw_pbes2.t
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Test::More;
|
||||||
|
use Crypt::KeyWrap qw(pbes2_key_wrap pbes2_key_unwrap);
|
||||||
|
use Crypt::Misc qw(decode_b64u);
|
||||||
|
|
||||||
|
{
|
||||||
|
### PBES2HS256A128KW test vector from https://github.com/Spomky-Labs/jose/blob/master/tests/PBES2_HS_AESKWKeyEncryptionTest.php
|
||||||
|
my $header = {
|
||||||
|
'alg' => 'PBES2-HS256+A128KW',
|
||||||
|
'p2s' => '2WCTcJZ1Rvd_CJuJripQ1w',
|
||||||
|
'p2c' => 4096,
|
||||||
|
'enc' => 'A128CBC-HS256',
|
||||||
|
'cty' => 'jwk+json',
|
||||||
|
};
|
||||||
|
my $b64u_wcek = 'TrqXOwuNUfDV9VPTNbyGvEJ9JMjefAVn-TR1uIxR9p6hsRQh9Tk7BA';
|
||||||
|
my $key = join '', map { chr($_) } (84, 104, 117, 115, 32, 102, 114, 111, 109, 32, 109, 121, 32, 108, 105, 112, 115, 44, 32, 98, 121, 32, 121, 111, 117, 114, 115, 44, 32, 109, 121, 32, 115, 105, 110, 32, 105, 115, 32, 112, 117, 114, 103, 101, 100, 46);
|
||||||
|
my $cek = join '', map { chr($_) } (111, 27, 25, 52, 66, 29, 20, 78, 92, 176, 56, 240, 65, 208, 82, 112, 161, 131, 36, 55, 202, 236, 185, 172, 129, 23, 153, 194, 195, 48, 253, 182);
|
||||||
|
my $wcek = decode_b64u($b64u_wcek);
|
||||||
|
my $salt = decode_b64u($header->{p2s});
|
||||||
|
my $iter = $header->{p2c};
|
||||||
|
|
||||||
|
my $unw = pbes2_key_unwrap($key, $wcek, $header->{alg}, $salt, $iter);
|
||||||
|
is(unpack("H*", $unw), unpack("H*", $cek), "pbes2_key_unwrap");
|
||||||
|
|
||||||
|
my $wrp = pbes2_key_wrap($key, $cek, $header->{alg}, $salt, $iter);
|
||||||
|
is(unpack("H*", $wrp), unpack("H*", $wcek), "pbes2_key_wrap");
|
||||||
|
}
|
||||||
|
|
||||||
|
done_testing;
|
37
t/kw_rsa.t
Normal file
37
t/kw_rsa.t
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Test::More;
|
||||||
|
use Crypt::KeyWrap qw(rsa_key_wrap rsa_key_unwrap);
|
||||||
|
use Crypt::Misc qw(decode_b64u);
|
||||||
|
use Crypt::PK::RSA;
|
||||||
|
|
||||||
|
{
|
||||||
|
### RSA key enc test vector from https://github.com/Spomky-Labs/jose/blob/master/tests/RSAKeyEncryptionTest.php
|
||||||
|
|
||||||
|
my $jwk = {
|
||||||
|
'kty' => 'RSA',
|
||||||
|
'n' => 'sXchDaQebHnPiGvyDOAT4saGEUetSyo9MKLOoWFsueri23bOdgWp4Dy1WlUzewbgBHod5pcM9H95GQRV3JDXboIRROSBigeC5yjU1hGzHHyXss8UDprecbAYxknTcQkhslANGRUZmdTOQ5qTRsLAt6BTYuyvVRdhS8exSZEy_c4gs_7svlJJQ4H9_NxsiIoLwAEk7-Q3UXERGYw_75IDrGA84-lA_-Ct4eTlXHBIY2EaV7t7LjJaynVJCpkv4LKjTTAumiGUIuQhrNhZLuF_RJLqHpM2kgWFLU7-VTdL1VbC2tejvcI2BlMkEpk1BzBZI0KQB0GaDWFLN-aEAw3vRw',
|
||||||
|
'e' => 'AQAB',
|
||||||
|
'd' => 'VFCWOqXr8nvZNyaaJLXdnNPXZKRaWCjkU5Q2egQQpTBMwhprMzWzpR8Sxq1OPThh_J6MUD8Z35wky9b8eEO0pwNS8xlh1lOFRRBoNqDIKVOku0aZb-rynq8cxjDTLZQ6Fz7jSjR1Klop-YKaUHc9GsEofQqYruPhzSA-QgajZGPbE_0ZaVDJHfyd7UUBUKunFMScbflYAAOYJqVIVwaYR5zWEEceUjNnTNo_CVSj-VvXLO5VZfCUAVLgW4dpf1SrtZjSt34YLsRarSb127reG_DUwg9Ch-KyvjT1SkHgUWRVGcyly7uvVGRSDwsXypdrNinPA4jlhoNdizK2zF2CWQ',
|
||||||
|
'p' => '9gY2w6I6S6L0juEKsbeDAwpd9WMfgqFoeA9vEyEUuk4kLwBKcoe1x4HG68ik918hdDSE9vDQSccA3xXHOAFOPJ8R9EeIAbTi1VwBYnbTp87X-xcPWlEPkrdoUKW60tgs1aNd_Nnc9LEVVPMS390zbFxt8TN_biaBgelNgbC95sM',
|
||||||
|
'q' => 'uKlCKvKv_ZJMVcdIs5vVSU_6cPtYI1ljWytExV_skstvRSNi9r66jdd9-yBhVfuG4shsp2j7rGnIio901RBeHo6TPKWVVykPu1iYhQXw1jIABfw-MVsN-3bQ76WLdt2SDxsHs7q7zPyUyHXmps7ycZ5c72wGkUwNOjYelmkiNS0',
|
||||||
|
'dp' => 'w0kZbV63cVRvVX6yk3C8cMxo2qCM4Y8nsq1lmMSYhG4EcL6FWbX5h9yuvngs4iLEFk6eALoUS4vIWEwcL4txw9LsWH_zKI-hwoReoP77cOdSL4AVcraHawlkpyd2TWjE5evgbhWtOxnZee3cXJBkAi64Ik6jZxbvk-RR3pEhnCs',
|
||||||
|
'dq' => 'o_8V14SezckO6CNLKs_btPdFiO9_kC1DsuUTd2LAfIIVeMZ7jn1Gus_Ff7B7IVx3p5KuBGOVF8L-qifLb6nQnLysgHDh132NDioZkhH7mI7hPG-PYE_odApKdnqECHWw0J-F0JWnUd6D2B_1TvF9mXA2Qx-iGYn8OVV1Bsmp6qU',
|
||||||
|
'qi' => 'eNho5yRBEBxhGBtQRww9QirZsB66TrfFReG_CcteI1aCneT0ELGhYlRlCtUkTRclIfuEPmNsNDPbLoLqqCVznFbvdB7x-Tl-m0l_eFTj2KiqwGqE9PZB9nNTwMVvH3VRRSLWACvPnSiwP8N5Usy-WRXS-V7TbpxIhvepTfE0NNo',
|
||||||
|
};
|
||||||
|
|
||||||
|
my $cek = join '', map { chr($_) } (4, 211, 31, 197, 84, 157, 252, 254, 11, 100, 157, 250, 63, 170, 106, 206, 107, 124, 212, 45, 111, 107, 9, 219, 200, 177, 0, 240, 143, 156, 44, 207);
|
||||||
|
my $wcek = decode_b64u('UGhIOguC7IuEvf_NPVaXsGMoLOmwvc1GyqlIKOK1nN94nHPoltGRhWhw7Zx0-kFm1NJn8LE9XShH59_i8J0PH5ZZyNfGy2xGdULU7sHNF6Gp2vPLgNZ__deLKxGHZ7PcHALUzoOegEI-8E66jX2E4zyJKx-YxzZIItRzC5hlRirb6Y5Cl_p-ko3YvkkysZIFNPccxRU7qve1WYPxqbb2Yw8kZqa2rMWI5ng8OtvzlV7elprCbuPhcCdZ6XDP0_F8rkXds2vE4X-ncOIM8hAYHHi29NX0mcKiRaD0-D-ljQTP-cFPgwCp6X-nZZd9OHBv-B3oWh2TbqmScqXMR4gp_A');
|
||||||
|
|
||||||
|
my $key = Crypt::PK::RSA->new($jwk);
|
||||||
|
my $unw = rsa_key_unwrap($key, $wcek, 'RSA1_5');
|
||||||
|
is(unpack("H*", $unw), unpack("H*", $cek), "rsa_key_unwrap");
|
||||||
|
|
||||||
|
for my $alg (qw/RSA1_5 RSA-OAEP-256 RSA-OAEP/) {
|
||||||
|
my $w = rsa_key_wrap($key, $cek, $alg);
|
||||||
|
my $u = rsa_key_unwrap($key, $w, $alg);
|
||||||
|
is(unpack("H*", $u), unpack("H*", $cek), "rsa_key_(un)wrap $alg");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done_testing;
|
Loading…
Reference in New Issue
Block a user