Compare commits

..

No commits in common. "pristine-tar" and "master" have entirely different histories.

31 changed files with 4676 additions and 1 deletions

64
Changes Normal file
View File

@ -0,0 +1,64 @@
Changes for Crypt-JWT distribution
0.021 2018/03/15
- fix #13 off-by-one in exp verification
0.020 2018/02/02
- improved diagnostics
0.019 2018/01/26
- fix #11 kid keys
- fix #9 Support for Java lib that pads base64 encoding
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
View 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
View 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
View File

@ -0,0 +1,54 @@
{
"abstract" : "JSON Web Token",
"author" : [
"Karel Miko"
],
"dynamic_config" : 1,
"generated_by" : "ExtUtils::MakeMaker version 7.3, CPAN::Meta::Converter version 2.150010",
"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.021",
"x_serialization_backend" : "JSON::PP version 2.94"
}

30
META.yml Normal file
View 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.3, CPAN::Meta::Converter version 2.150010'
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.021'
x_serialization_backend: 'CPAN::Meta::YAML version 0.018'

31
Makefile.PL Normal file
View 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',
},
);

549
README Normal file
View File

@ -0,0 +1,549 @@
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);
Since 0.19 we also support:
use LWP::Simple;
my $google_certs = get('https://www.googleapis.com/oauth2/v1/certs');
my $payload = decode_jwt(token => $t, kid_keys => $google_certs);
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

17
debian/changelog vendored Normal file
View File

@ -0,0 +1,17 @@
libcrypt-jwt-perl (0.021-1) UNRELEASED; urgency=medium
* Bump to new version
-- Mario Fetka <mario.fetka@gmail.com> Thu, 22 Mar 2018 16:07:20 +0100
libcrypt-jwt-perl (0.018-0.1~bpo9+1) stretch-backports; urgency=medium
* Rebuild for stretch-backports.
-- Michael Prokop <mprokop@sipwise.com> Tue, 13 Jun 2017 15:22:49 +0200
libcrypt-jwt-perl (0.018-0.1) unstable; urgency=low
* Initial Release.
-- Michael Prokop <mprokop@sipwise.com> Tue, 13 Jun 2017 15:14:59 +0200

1
debian/compat vendored Normal file
View File

@ -0,0 +1 @@
9

22
debian/control vendored Normal file
View File

@ -0,0 +1,22 @@
Source: libcrypt-jwt-perl
Section: perl
Priority: optional
Maintainer: Sipwise Development Team <support@sipwise.com>
Build-Depends:
libcryptx-perl (>= 0.034~),
debhelper,
libjson-maybexs-perl,
Build-Depends-Indep:
perl,
Standards-Version: 3.9.8
Homepage: https://metacpan.org/release/Crypt-JWT
Package: libcrypt-jwt-perl
Architecture: all
Depends:
libcryptx-perl (>= 0.034~),
${misc:Depends},
${perl:Depends},
Description: JSON Web Token
Implements key management algorithms defined in
https://tools.ietf.org/html/rfc7518

28
debian/copyright vendored Normal file
View File

@ -0,0 +1,28 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Source: https://metacpan.org/release/Crypt-JWT
Upstream-Contact: Karel Miko
Upstream-Name: Crypt-JWT
Files: *
Copyright: Karel Miko
License: Artistic or GPL-1+
Files: debian/*
Copyright: 2017, Sipwise GmbH, Austria
License: Artistic or GPL-1+
License: Artistic
This program is free software; you can redistribute it and/or modify
it under the terms of the Artistic License, which comes with Perl.
.
On Debian systems, the complete text of the Artistic License can be
found in `/usr/share/common-licenses/Artistic'.
License: GPL-1+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
.
On Debian systems, the complete text of version 1 of the GNU General
Public License can be found in `/usr/share/common-licenses/GPL-1'.

4
debian/rules vendored Executable file
View File

@ -0,0 +1,4 @@
#!/usr/bin/make -f
%:
dh $@

1
debian/source/format vendored Normal file
View File

@ -0,0 +1 @@
3.0 (quilt)

6
debian/upstream/metadata vendored Normal file
View File

@ -0,0 +1,6 @@
---
Archive: CPAN
Bug-Database: https://github.com/DCIT/perl-Crypt-JWT/issues
Contact: Karel Miko
Name: Crypt-JWT
Repository: https://github.com/DCIT/perl-Crypt-JWT

2
debian/watch vendored Normal file
View File

@ -0,0 +1,2 @@
version=3
https://metacpan.org/release/Crypt-JWT .*/Crypt-JWT-v?(\d[\d.-]*)\.(?:tar(?:\.gz|\.bz2)?|tgz|zip)$

1284
lib/Crypt/JWT.pm Normal file

File diff suppressed because it is too large Load Diff

603
lib/Crypt/KeyWrap.pm Normal file
View File

@ -0,0 +1,603 @@
package Crypt::KeyWrap;
use strict;
use warnings;
our $VERSION = '0.021';
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

View File

@ -1 +0,0 @@
697fd50dae7c40fb95fad1f1dd53c52f7c7c1840

7
t/compile.t Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;