Imported Upstream version 0.021

This commit is contained in:
Mario Fetka 2018-03-22 16:07:01 +01:00
parent fd8ac42b2a
commit 283818d781
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'

24
README
View File

@ -72,7 +72,7 @@ FUNCTIONS
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,
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
@ -127,9 +127,9 @@ FUNCTIONS
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);
@ -172,9 +172,9 @@ FUNCTIONS
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);
@ -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).
@ -421,7 +427,7 @@ FUNCTIONS
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,
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
@ -429,7 +435,7 @@ FUNCTIONS
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,
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
@ -447,12 +453,12 @@ FUNCTIONS
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,
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,
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

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;
for (@{$kid_keys->{keys}}) {
if ($_->{kid} && $_->{kty} && $_->{kid} eq $kid) {
$found = $_;
last;
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);
}
@ -789,7 +805,7 @@ The value depends on the C<alg> token header value.
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,
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
@ -844,9 +860,9 @@ Examples with RSA keys:
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);
@ -889,9 +905,9 @@ Examples with ECC keys:
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);
@ -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).
@ -1143,7 +1165,7 @@ A key used for token encryption (JWE) or token signing (JWS). The value depends
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,
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
@ -1151,7 +1173,7 @@ A key used for token encryption (JWE) or token signing (JWS). The value depends
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,
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
@ -1169,12 +1191,12 @@ A key used for token encryption (JWE) or token signing (JWS). The value depends
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,
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,
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

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)] );