Crypt-JWT

 view release on metacpan or  search on metacpan

lib/Crypt/JWT.pm  view on Meta::CPAN

package Crypt::JWT;

use strict;
use warnings;

our $VERSION = '0.035';

use Exporter 'import';
our %EXPORT_TAGS = ( all => [qw(decode_jwt encode_jwt)] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();

use Carp;
use Crypt::Misc qw(decode_b64u encode_b64u);
use JSON qw(decode_json encode_json);
use Crypt::PK::RSA;
use Crypt::PK::ECC;
use Crypt::PK::Ed25519;
use Crypt::PK::X25519;
use Crypt::PRNG qw(random_bytes);
use Crypt::KeyWrap ':all';
use Crypt::AuthEnc::GCM qw(gcm_encrypt_authenticate gcm_decrypt_verify);
use Crypt::Mac::HMAC qw(hmac);
use Compress::Raw::Zlib;
use Scalar::Util qw(looks_like_number);

# 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
# JWT: https://tools.ietf.org/html/rfc7519
# X25519/Ed25519 https://tools.ietf.org/html/rfc8037

sub _prepare_rsa_key {
  my ($key) = @_;
  croak "JWT: undefined RSA key" unless defined $key;
  croak "JWT: invalid RSA key (cannot be scalar)" unless ref $key;
  # we need Crypt::PK::RSA object
  return $key                       if ref($key) eq 'Crypt::PK::RSA';
  return Crypt::PK::RSA->new($key)  if ref($key) eq 'HASH' || ref($key) eq 'SCALAR';
  return Crypt::PK::RSA->new(@$key) if ref($key) eq 'ARRAY';
  # handle also: Crypt::OpenSSL::RSA, Crypt::X509, Crypt::OpenSSL::X509
  my $str;
  if (ref($key) eq 'Crypt::OpenSSL::RSA') {
    # https://metacpan.org/pod/Crypt::OpenSSL::RSA
    $str = $key->is_private ? $key->get_private_key_string : $key->get_public_key_string;
  }
  elsif (ref($key) =~ /^Crypt::(X509|OpenSSL::X509)$/) {
    # https://metacpan.org/pod/Crypt::X509
    # https://metacpan.org/pod/Crypt::OpenSSL::X509
    $str = $key->pubkey;
  }
  return Crypt::PK::RSA->new(\$str) if defined $str && !ref($str);
  croak "JWT: invalid RSA key";
}

sub _prepare_ecc_key {
  my ($key) = @_;
  croak "JWT: undefined ECC key" unless defined $key;
  croak "JWT: invalid ECC key (cannot be scalar)" unless ref $key;
  # we need Crypt::PK::ECC object
  return $key                       if ref($key) eq 'Crypt::PK::ECC';
  return Crypt::PK::ECC->new($key)  if ref($key) eq 'HASH' || ref($key) eq 'SCALAR';
  return Crypt::PK::ECC->new(@$key) if ref($key) eq 'ARRAY';
  croak "JWT: invalid ECC key";
}

sub _prepare_ed25519_key {
  my ($key) = @_;
  croak "JWT: undefined Ed25519 key" unless defined $key;
  croak "JWT: invalid Ed25519 key (cannot be scalar)" unless ref $key;
  # we need Crypt::PK::Ed25519 object
  return $key                           if ref($key) eq 'Crypt::PK::Ed25519';
  return Crypt::PK::Ed25519->new($key)  if ref($key) eq 'HASH' || ref($key) eq 'SCALAR';
  return Crypt::PK::Ed25519->new(@$key) if ref($key) eq 'ARRAY';
  croak "JWT: invalid Ed25519 key";
}

sub _prepare_ecdh_key {
  my ($key) = @_;
  croak "JWT: undefined ECDH key" unless defined $key;
  croak "JWT: invalid ECDH key (cannot be scalar)" unless ref $key;

  # we need Crypt::PK::X25519 or Crypt::PK::ECC object
  return $key if ref($key) =~ /^Crypt::PK::(ECC|X25519)$/;

  if (ref($key) eq 'HASH' || ref($key) eq 'SCALAR') {
    #HACK: this is ugly
    my $rv = eval { Crypt::PK::ECC->new($key) } || eval { Crypt::PK::X25519->new($key) };
    return $rv if defined $rv;
  }
  if (ref($key) eq 'ARRAY') {
    #HACK: this is ugly
    my $rv = eval { Crypt::PK::ECC->new(@$key) } || eval { Crypt::PK::X25519->new(@$key) };
    return $rv if defined $rv;
  }
  croak "JWT: invalid ECDH key";
}

sub _prepare_oct_key {
  my ($key) = @_;
  croak "JWT: undefined oct key" unless defined $key;
  if (ref $key eq 'HASH' && $key->{k} && $key->{kty} && $key->{kty} eq 'oct') {
    return decode_b64u($key->{k});
  }
  elsif (!ref $key) {

 view all matches for this distribution
 view release on metacpan -  search on metacpan

( run in 1.285 second using v1.00-cache-2.02-grep-82fe00e-cpan-2cc899e4a130 )