Merge tag 'upstream/0.021'

Upstream version 0.021
This commit is contained in:
Mario Fetka 2018-03-22 16:07:01 +01:00
commit e52248ca67
6 changed files with 74 additions and 36 deletions

10
Changes
View File

@ -1,5 +1,15 @@
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

View File

@ -4,13 +4,13 @@
"Karel Miko"
],
"dynamic_config" : 1,
"generated_by" : "ExtUtils::MakeMaker version 7.18, CPAN::Meta::Converter version 2.150005",
"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"
"version" : 2
},
"name" : "Crypt-JWT",
"no_index" : {
@ -49,6 +49,6 @@
"url" : "https://github.com/DCIT/perl-Crypt-JWT"
}
},
"version" : "0.018",
"x_serialization_backend" : "JSON::PP version 2.27400"
"version" : "0.021",
"x_serialization_backend" : "JSON::PP version 2.94"
}

View File

@ -7,7 +7,7 @@ build_requires:
configure_requires:
ExtUtils::MakeMaker: '0'
dynamic_config: 1
generated_by: 'ExtUtils::MakeMaker version 7.18, CPAN::Meta::Converter version 2.150005'
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
@ -26,5 +26,5 @@ requires:
resources:
bugtracker: https://github.com/DCIT/perl-Crypt-JWT/issues
repository: https://github.com/DCIT/perl-Crypt-JWT
version: '0.018'
version: '0.021'
x_serialization_backend: 'CPAN::Meta::YAML version 0.018'

6
README
View File

@ -211,6 +211,12 @@ FUNCTIONS
};
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).

View File

@ -3,7 +3,7 @@ package Crypt::JWT;
use strict;
use warnings;
our $VERSION = '0.018';
our $VERSION = '0.021';
use Exporter 'import';
our %EXPORT_TAGS = ( all => [qw(decode_jwt encode_jwt)] );
@ -76,16 +76,23 @@ sub _prepare_oct_key {
sub _kid_lookup {
my ($kid, $kid_keys, $alg) = @_;
$kid_keys = decode_json($kid_keys) unless ref $kid_keys;
$kid_keys = eval { decode_json($kid_keys) } unless ref $kid_keys;
return undef unless ref $kid_keys eq 'HASH';
return undef unless exists $kid_keys->{keys} && ref $kid_keys->{keys} eq 'ARRAY';
my $found;
if (exists $kid_keys->{keys} && ref $kid_keys->{keys} eq 'ARRAY') {
#FORMAT: { keys => [ {kid=>'A', kty=>?, ...}, {kid=>'B', kty=>?, ...} ] }
for (@{$kid_keys->{keys}}) {
if ($_->{kid} && $_->{kty} && $_->{kid} eq $kid) {
$found = $_;
last;
}
}
}
else {
#FORMAT: { hexadec1 => "----BEGIN CERTIFICATE-----...", hexadec2 => "----BEGIN CERTIFICATE-----..." }
#e.g. https://www.googleapis.com/oauth2/v1/certs
return \$kid_keys->{$kid} if $kid_keys->{$kid} && !ref $kid_keys->{$kid};
}
return undef if !$found;
return $found if $found->{kty} eq 'oct' && $alg =~ /^(HS|dir|PBES2-HS|A)/;
return $found if $found->{kty} eq 'EC' && $alg =~ /^(ES|EC)/;
@ -98,7 +105,8 @@ sub _b64u_to_hash {
return undef unless $b64url;
my $json = decode_b64u($b64url);
return undef unless $json;
my $hash = decode_json($json);
my $hash = eval { decode_json($json) };
return undef unless ref $hash eq 'HASH';
return $hash;
}
@ -129,7 +137,7 @@ sub _verify_claims {
### exp
if(defined $payload->{exp}) {
if (!defined $args{verify_exp} || $args{verify_exp}==1) {
croak "JWT: exp claim check failed ($payload->{exp}/$leeway vs. $now)" if $payload->{exp} + $leeway < $now;
croak "JWT: exp claim check failed ($payload->{exp}/$leeway vs. $now)" if $payload->{exp} + $leeway <= $now;
}
}
elsif ($args{verify_exp} && $args{verify_exp}==1) {
@ -450,6 +458,11 @@ sub _decode_jwe {
my $ct = decode_b64u($b64u_ct);
my $iv = decode_b64u($b64u_iv);
my $tag = decode_b64u($b64u_tag);
croak "JWE: invalid header part" if $b64u_header && !$header;
croak "JWE: invalid ecek part" if $b64u_ecek && !$ecek;
croak "JWE: invalid ct part" if $b64u_ct && !$ct;
croak "JWE: invalid iv part" if $b64u_iv && !$iv;
croak "JWE: invalid tag part" if $b64u_tag && !$tag;
my $key = defined $args{keypass} ? [$args{key}, $args{keypass}] : $args{key};
if ($header->{kid} && $args{kid_keys}) {
@ -515,6 +528,7 @@ sub _sign_jws {
sub _verify_jws {
my ($b64u_header, $b64u_payload, $b64u_sig, $alg, $key) = @_;
my $sig = decode_b64u($b64u_sig);
croak "JWS: invalid sig part" if $b64u_sig && !$sig;
my $data = "$b64u_header.$b64u_payload";
if ($alg eq 'none' ) { # no integrity
@ -574,6 +588,7 @@ sub _encode_jws {
sub _decode_jws {
my ($b64u_header, $b64u_payload, $b64u_sig, $unprotected_header, %args) = @_;
my $header = _b64u_to_hash($b64u_header);
croak "JWS: invalid header part" if $b64u_header && !$header;
$unprotected_header = {} if ref $unprotected_header ne 'HASH';
if (!$args{ignore_signature}) {
@ -602,6 +617,7 @@ sub _decode_jws {
croak "JWS: decode failed" if !$valid;
}
my $payload = decode_b64u($b64u_payload);
croak "JWS: invalid payload part" if $b64u_payload && !$payload;
$payload = _payload_unzip($payload, $header->{zip}) if $header->{zip};
$payload = _payload_dec($payload, $args{decode_payload});
_verify_claims($payload, %args) if ref $payload eq 'HASH'; # croaks on error
@ -667,11 +683,11 @@ sub decode_jwt {
if (!$args{token}) {
croak "JWT: missing token";
}
elsif ($args{token} =~ /^([a-zA-Z0-9_-]+)\.([a-zA-Z0-9_-]*)\.([a-zA-Z0-9_-]+)\.([a-zA-Z0-9_-]+)\.([a-zA-Z0-9_-]+)$/) {
elsif ($args{token} =~ /^([a-zA-Z0-9_-]+)=*\.([a-zA-Z0-9_-]*)=*\.([a-zA-Z0-9_-]+)=*\.([a-zA-Z0-9_-]+)=*\.([a-zA-Z0-9_-]+)=*$/) {
# JWE token (5 segments)
($header, $payload) = _decode_jwe($1, $2, $3, $4, $5, undef, {}, {}, %args);
}
elsif ($args{token} =~ /^([a-zA-Z0-9_-]+)\.([a-zA-Z0-9_-]+)\.([a-zA-Z0-9_-]*)$/) {
elsif ($args{token} =~ /^([a-zA-Z0-9_-]+)=*\.([a-zA-Z0-9_-]+)=*\.([a-zA-Z0-9_-]*)=*$/) {
# JWS token (3 segments)
($header, $payload) = _decode_jws($1, $2, $3, {}, %args);
}
@ -927,6 +943,12 @@ This parametes can be either a JWK Set JSON string (see RFC7517) or a perl HASH
};
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 C<kid_keys> list and used for token
decoding (you do not need to pass the explicit key via C<key> parameter).

View File

@ -3,7 +3,7 @@ package Crypt::KeyWrap;
use strict;
use warnings;
our $VERSION = '0.018';
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)] );