modified file plugins

This commit is contained in:
2023-10-22 22:21:44 +00:00
committed by Gitium
parent c72a65abc1
commit 96c0ee892f
4817 changed files with 752216 additions and 0 deletions
wp-content/upgrade-temp-backup/plugins
activitypub
authldap
gp-premium
backgrounds
blog
colors
copyright
disable-elements
dist
elements
general
gp-premium.php
hooks
inc
langs
gp-premium-ar.mogp-premium-bn_BD.mogp-premium-cs_CZ.mogp-premium-da_DK.mogp-premium-de_DE-42da344ccb044413769d16ed3484307b.jsongp-premium-de_DE-53e2a1d5945b8d2b1c35e81ae1e532f3.jsongp-premium-de_DE-92fa58377f1b6f7bef9c785c31ae29ff.jsongp-premium-de_DE.mogp-premium-es_AR.mogp-premium-es_ES-42da344ccb044413769d16ed3484307b.jsongp-premium-es_ES-53e2a1d5945b8d2b1c35e81ae1e532f3.jsongp-premium-es_ES-92fa58377f1b6f7bef9c785c31ae29ff.jsongp-premium-es_ES-cbab080b0f20fd6c323029398be6c986.jsongp-premium-es_ES-ecf9f3c2af10c4f2dfbf4f42504922d1.jsongp-premium-es_ES.mogp-premium-fi-42da344ccb044413769d16ed3484307b.jsongp-premium-fi-53e2a1d5945b8d2b1c35e81ae1e532f3.jsongp-premium-fi-92fa58377f1b6f7bef9c785c31ae29ff.jsongp-premium-fi-cbab080b0f20fd6c323029398be6c986.jsongp-premium-fi-ecf9f3c2af10c4f2dfbf4f42504922d1.jsongp-premium-fi.mogp-premium-fr_FR-42da344ccb044413769d16ed3484307b.jsongp-premium-fr_FR-53e2a1d5945b8d2b1c35e81ae1e532f3.jsongp-premium-fr_FR-92fa58377f1b6f7bef9c785c31ae29ff.jsongp-premium-fr_FR.mogp-premium-hr.mogp-premium-hu_HU.mogp-premium-it_IT.mogp-premium-nb_NO.mogp-premium-nl_NL-42da344ccb044413769d16ed3484307b.jsongp-premium-nl_NL-53e2a1d5945b8d2b1c35e81ae1e532f3.jsongp-premium-nl_NL-92fa58377f1b6f7bef9c785c31ae29ff.jsongp-premium-nl_NL-cbab080b0f20fd6c323029398be6c986.jsongp-premium-nl_NL-ecf9f3c2af10c4f2dfbf4f42504922d1.jsongp-premium-nl_NL.mogp-premium-pl_PL.mogp-premium-pt_BR.mogp-premium-pt_PT-42da344ccb044413769d16ed3484307b.jsongp-premium-pt_PT-53e2a1d5945b8d2b1c35e81ae1e532f3.jsongp-premium-pt_PT-92fa58377f1b6f7bef9c785c31ae29ff.jsongp-premium-pt_PT.mogp-premium-ru_RU-42da344ccb044413769d16ed3484307b.jsongp-premium-ru_RU-53e2a1d5945b8d2b1c35e81ae1e532f3.jsongp-premium-ru_RU-92fa58377f1b6f7bef9c785c31ae29ff.jsongp-premium-ru_RU.mogp-premium-sv_SE-42da344ccb044413769d16ed3484307b.jsongp-premium-sv_SE-53e2a1d5945b8d2b1c35e81ae1e532f3.jsongp-premium-sv_SE-92fa58377f1b6f7bef9c785c31ae29ff.jsongp-premium-sv_SE-cbab080b0f20fd6c323029398be6c986.jsongp-premium-sv_SE-ecf9f3c2af10c4f2dfbf4f42504922d1.jsongp-premium-sv_SE.mogp-premium-uk.mogp-premium-vi.mogp-premium-zh_CN.mo
library
menu-plus
page-header
readme.txt
secondary-nav
sections
site-library
spacing
typography
woocommerce
wpml-config.xml
jetpack-protect
CHANGELOG.mdLICENSE.txtSECURITY.md
assets
build
composer.jsonjetpack-protect.php
jetpack_vendor
automattic
jetpack-a8c-mc-stats
jetpack-admin-ui
jetpack-assets
jetpack-config
jetpack-connection
jetpack-constants
jetpack-device-detection
jetpack-identity-crisis
jetpack-ip
jetpack-jitm
jetpack-licensing
jetpack-logo
jetpack-my-jetpack
jetpack-partner
jetpack-password-checker
jetpack-plugins-installer
jetpack-redirect
jetpack-roles
jetpack-status
jetpack-sync
jetpack-transport-helper
jetpack-waf
i18n-map.php
readme.txt
src
vendor
menu-icons
CHANGELOG.mdCONTRIBUTING.mdLICENSE
css
images
includes
js
languages
mailin.phpmenu-icons.phpreadme.mdreadme.txt
vendor
autoload.php
codeinwp
gutenberg-menu-icons
icon-picker
menu-item-custom-fields
themeisle-sdk
composer
smtp-mailer
two-factor
w3-total-cache
Base_Page_Settings.phpBrowserCache_ConfigLabels.phpBrowserCache_Core.phpBrowserCache_Environment.phpBrowserCache_Environment_Apache.phpBrowserCache_Environment_LiteSpeed.phpBrowserCache_Environment_Nginx.phpBrowserCache_Page.phpBrowserCache_Page_View_QuickReference.phpBrowserCache_Page_View_SectionSecurity.phpBrowserCache_Plugin.phpBrowserCache_Plugin_Admin.phpCache.phpCacheFlush.phpCacheFlush_Locally.phpCacheGroups_Plugin_Admin.phpCacheGroups_Plugin_Admin_View.jsCacheGroups_Plugin_Admin_View.phpCache_Apc.phpCache_Apcu.phpCache_Base.phpCache_Eaccelerator.phpCache_File.phpCache_File_Cleaner.phpCache_File_Cleaner_Generic.phpCache_File_Cleaner_Generic_HardDelete.phpCache_File_Generic.phpCache_Memcache.phpCache_Memcached.phpCache_Memcached_Stats.phpCache_Nginx_Memcached.phpCache_Redis.phpCache_Wincache.phpCache_Xcache.phpCdnEngine.phpCdnEngine_Azure.phpCdnEngine_Base.phpCdnEngine_CloudFront.phpCdnEngine_Ftp.phpCdnEngine_GoogleDrive.phpCdnEngine_Mirror.phpCdnEngine_Mirror_Akamai.phpCdnEngine_Mirror_Att.phpCdnEngine_Mirror_CloudFront.phpCdnEngine_Mirror_Cotendo.phpCdnEngine_Mirror_Edgecast.phpCdnEngine_Mirror_Highwinds.phpCdnEngine_Mirror_LimeLight.phpCdnEngine_Mirror_RackSpaceCdn.phpCdnEngine_Mirror_StackPath.phpCdnEngine_Mirror_StackPath2.phpCdnEngine_RackSpaceCloudFiles.phpCdnEngine_S3.phpCdnEngine_S3_Compatible.phpCdn_AdminActions.phpCdn_AdminNotes.phpCdn_CacheFlush.phpCdn_ConfigLabels.phpCdn_Core.phpCdn_Core_Admin.phpCdn_Environment.phpCdn_Environment_LiteSpeed.phpCdn_Environment_Nginx.phpCdn_GeneralPage_View.phpCdn_GoogleDrive_AdminActions.phpCdn_GoogleDrive_Page.phpCdn_GoogleDrive_Page_View.jsCdn_GoogleDrive_Page_View.phpCdn_GoogleDrive_Popup_AuthReturn.phpCdn_GoogleDrive_Popup_AuthReturn_View.phpCdn_Highwinds_Api.phpCdn_Highwinds_Page.phpCdn_Highwinds_Page_View.jsCdn_Highwinds_Page_View.phpCdn_Highwinds_Popup.phpCdn_Highwinds_Popup_View_ConfigureCnamesForm.phpCdn_Highwinds_Popup_View_Intro.phpCdn_Highwinds_Popup_View_SelectHost.phpCdn_Highwinds_Widget.phpCdn_Highwinds_Widget_View.cssCdn_Highwinds_Widget_View.jsCdn_Highwinds_Widget_View.phpCdn_Highwinds_Widget_View_NotConfigured.phpCdn_LimeLight_Page.phpCdn_LimeLight_Page_View.jsCdn_LimeLight_Page_View.phpCdn_LimeLight_Popup.phpCdn_LimeLight_Popup_View_Intro.phpCdn_LimeLight_Popup_View_Success.phpCdn_Page.phpCdn_Page_View_Fsd_HeaderActions.phpCdn_Page_View_Header.phpCdn_Plugin.phpCdn_Plugin_Admin.phpCdn_RackSpaceCdn_AdminActions.phpCdn_RackSpaceCdn_Page.phpCdn_RackSpaceCdn_Page_View.jsCdn_RackSpaceCdn_Page_View.phpCdn_RackSpaceCdn_Popup.phpCdn_RackSpaceCdn_Popup_View_ConfigureDomains.phpCdn_RackSpaceCdn_Popup_View_Intro.phpCdn_RackSpaceCdn_Popup_View_Regions.phpCdn_RackSpaceCdn_Popup_View_Service_Actualize.phpCdn_RackSpaceCdn_Popup_View_Service_Create.phpCdn_RackSpaceCdn_Popup_View_Service_Created.phpCdn_RackSpaceCdn_Popup_View_Services.phpCdn_RackSpaceCloudFiles_Page.phpCdn_RackSpaceCloudFiles_Page_View.jsCdn_RackSpaceCloudFiles_Page_View.phpCdn_RackSpaceCloudFiles_Popup.phpCdn_RackSpaceCloudFiles_Popup_View_Containers.phpCdn_RackSpaceCloudFiles_Popup_View_Intro.phpCdn_RackSpaceCloudFiles_Popup_View_Regions.phpCdn_RackSpace_Api_CaCert-example.pemCdn_RackSpace_Api_Cdn.phpCdn_RackSpace_Api_CloudFiles.phpCdn_RackSpace_Api_CloudFilesCdn.phpCdn_RackSpace_Api_Tokens.phpCdn_StackPath2_Api.phpCdn_StackPath2_Page.phpCdn_StackPath2_Page_View.jsCdn_StackPath2_Page_View.phpCdn_StackPath2_Popup.phpCdn_StackPath2_Popup_View_Intro.phpCdn_StackPath2_Popup_View_Sites.phpCdn_StackPath2_Popup_View_Stacks.phpCdn_StackPath2_Popup_View_Success.phpCdn_StackPath2_Widget.phpCdn_StackPath2_Widget_View.cssCdn_StackPath2_Widget_View.jsCdn_StackPath2_Widget_View_Authorized.phpCdn_StackPath2_Widget_View_Unauthorized.phpCdn_StackPath_Api.phpCdn_StackPath_Page.phpCdn_StackPath_Page_View.jsCdn_StackPath_Page_View.phpCdn_StackPath_Popup.phpCdn_StackPath_Popup_View_Intro.phpCdn_StackPath_Popup_View_Success.phpCdn_StackPath_Popup_View_Zone.phpCdn_StackPath_Popup_View_Zones.phpCdn_StackPath_Widget.phpCdn_StackPath_Widget_View.cssCdn_StackPath_Widget_View.jsCdn_StackPath_Widget_View_Authorized.phpCdn_StackPath_Widget_View_Unauthorized.phpCdn_Util.phpCdnfsd_CacheFlush.phpCdnfsd_CloudFront_Engine.phpCdnfsd_CloudFront_Page.phpCdnfsd_CloudFront_Page_View.jsCdnfsd_CloudFront_Page_View.phpCdnfsd_CloudFront_Popup.phpCdnfsd_CloudFront_Popup_View_Distribution.phpCdnfsd_CloudFront_Popup_View_Distributions.phpCdnfsd_CloudFront_Popup_View_Intro.phpCdnfsd_CloudFront_Popup_View_Success.phpCdnfsd_Core.phpCdnfsd_GeneralPage_View.phpCdnfsd_LimeLight_Api.phpCdnfsd_LimeLight_Engine.phpCdnfsd_LimeLight_Page.phpCdnfsd_LimeLight_Page_View.jsCdnfsd_LimeLight_Page_View.phpCdnfsd_LimeLight_Popup.phpCdnfsd_LimeLight_Popup_View_Intro.phpCdnfsd_LimeLight_Popup_View_Success.phpCdnfsd_Page_View_Header.phpCdnfsd_Plugin.phpCdnfsd_Plugin_Admin.phpCdnfsd_StackPath2_Engine.phpCdnfsd_StackPath2_Page.phpCdnfsd_StackPath2_Page_View.jsCdnfsd_StackPath2_Page_View.phpCdnfsd_StackPath2_Popup.phpCdnfsd_StackPath2_Popup_View_Intro.phpCdnfsd_StackPath2_Popup_View_Sites.phpCdnfsd_StackPath2_Popup_View_Stacks.phpCdnfsd_StackPath2_Popup_View_Success.phpCdnfsd_StackPath_Engine.phpCdnfsd_StackPath_Page.phpCdnfsd_StackPath_Page_View.jsCdnfsd_StackPath_Page_View.phpCdnfsd_StackPath_Popup.phpCdnfsd_StackPath_Popup_View_Intro.phpCdnfsd_StackPath_Popup_View_Success.phpCdnfsd_StackPath_Popup_View_Zone.phpCdnfsd_StackPath_Popup_View_Zones.phpCdnfsd_TransparentCDN_Engine.phpCdnfsd_TransparentCDN_Page.phpCdnfsd_TransparentCDN_Page_View.jsCdnfsd_TransparentCDN_Page_View.phpCdnfsd_Util.phpCli.phpConfig.phpConfigCache.phpConfigCompiler.phpConfigDbStorage.phpConfigKeys.phpConfigState.phpConfigStateNote.phpConfigUtil.phpDbCache_ConfigLabels.phpDbCache_Core.phpDbCache_Environment.phpDbCache_Page.phpDbCache_Plugin.phpDbCache_Plugin_Admin.phpDbCache_Wpdb.phpDbCache_WpdbBase.phpDbCache_WpdbInjection.phpDbCache_WpdbInjection_QueryCaching.phpDbCache_WpdbLegacy.phpDbCache_WpdbNew.phpDispatcher.phpEnterprise_CacheFlush_MakeSnsEvent.phpEnterprise_Dbcache_WpdbInjection_Cluster.phpEnterprise_SnsBase.phpEnterprise_SnsServer.phpExtension_Amp_Page_View.phpExtension_Amp_Plugin.phpExtension_Amp_Plugin_Admin.phpExtension_CloudFlare_AdminActions.phpExtension_CloudFlare_Api.phpExtension_CloudFlare_Cdn_Page_View.phpExtension_CloudFlare_GeneralPage_View.phpExtension_CloudFlare_Page.phpExtension_CloudFlare_Page_View.jsExtension_CloudFlare_Page_View.phpExtension_CloudFlare_Plugin.phpExtension_CloudFlare_Plugin_Admin.phpExtension_CloudFlare_Popup.phpExtension_CloudFlare_Popup_View_Intro.phpExtension_CloudFlare_Popup_View_Zones.phpExtension_CloudFlare_SettingsForUi.phpExtension_CloudFlare_View_Dashboard.jsExtension_CloudFlare_Widget.phpExtension_CloudFlare_Widget_Logo.pngExtension_CloudFlare_Widget_View.cssExtension_CloudFlare_Widget_View.phpExtension_FragmentCache_Api.phpExtension_FragmentCache_Core.phpExtension_FragmentCache_Environment.phpExtension_FragmentCache_GeneralPage.phpExtension_FragmentCache_GeneralPage_View.phpExtension_FragmentCache_Page.phpExtension_FragmentCache_Page_View.phpExtension_FragmentCache_Plugin.phpExtension_FragmentCache_Plugin_Admin.phpExtension_FragmentCache_WpObjectCache.phpExtension_Genesis_Page.phpExtension_Genesis_Page_View.phpExtension_Genesis_Plugin.phpExtension_Genesis_Plugin_Admin.phpExtension_ImageService_Api.phpExtension_ImageService_Cron.phpExtension_ImageService_Environment.phpExtension_ImageService_Page_View.phpExtension_ImageService_Plugin.phpExtension_ImageService_Plugin_Admin.cssExtension_ImageService_Plugin_Admin.jsExtension_ImageService_Plugin_Admin.phpExtension_NewRelic_AdminActions.phpExtension_NewRelic_AdminNotes.phpExtension_NewRelic_Api.phpExtension_NewRelic_Core.phpExtension_NewRelic_GeneralPage.phpExtension_NewRelic_GeneralPage_View.phpExtension_NewRelic_Page.phpExtension_NewRelic_Page_View_Apm.phpExtension_NewRelic_Plugin.phpExtension_NewRelic_Plugin_Admin.phpExtension_NewRelic_Popup.phpExtension_NewRelic_Popup_View.jsExtension_NewRelic_Popup_View_Intro.phpExtension_NewRelic_Popup_View_ListApplications.phpExtension_NewRelic_Service.phpExtension_NewRelic_Widget.phpExtension_NewRelic_Widget_View.cssExtension_NewRelic_Widget_View.jsExtension_NewRelic_Widget_View_Apm.phpExtension_NewRelic_Widget_View_Browser.phpExtension_NewRelic_Widget_View_NotConfigured.phpExtension_Swarmify_AdminActions.phpExtension_Swarmify_Core.phpExtension_Swarmify_Page.phpExtension_Swarmify_Page_View.phpExtension_Swarmify_Plugin.phpExtension_Swarmify_Plugin_Admin.phpExtension_Swarmify_Widget.phpExtension_Swarmify_Widget_View.cssExtension_Swarmify_Widget_View_NotConfigured.phpExtension_WordPressSeo_Plugin.phpExtension_WordPressSeo_Plugin_Admin.phpExtension_Wpml_Plugin.phpExtension_Wpml_Plugin_Admin.phpExtensions_AdminActions.phpExtensions_Page.phpExtensions_Plugin_Admin.phpExtensions_Util.phpFeatureShowcase_Plugin_Admin.phpFeatureShowcase_Plugin_Admin_View.phpGeneric_AdminActions_Config.phpGeneric_AdminActions_Default.phpGeneric_AdminActions_Flush.phpGeneric_AdminActions_Test.phpGeneric_AdminNotes.phpGeneric_ConfigLabels.phpGeneric_Environment.phpGeneric_Faq.phpGeneric_GeneralPage_View_ShowEdge.jsGeneric_GeneralPage_View_ShowSupportUs.jsGeneric_Page_About.phpGeneric_Page_Dashboard.phpGeneric_Page_Dashboard_View.cssGeneric_Page_General.phpGeneric_Page_Install.phpGeneric_Page_PurgeLog.phpGeneric_Page_PurgeLog_View.phpGeneric_Plugin.phpGeneric_Plugin_Admin.phpGeneric_Plugin_AdminCompatibility.phpGeneric_Plugin_AdminNotifications.phpGeneric_Plugin_AdminRowActions.phpGeneric_Plugin_Admin_View_Faq.phpGeneric_Plugin_WidgetForum.phpGeneric_Plugin_WidgetNews.phpGeneric_WidgetBoldGrid.phpGeneric_WidgetBoldGrid_AdminActions.phpGeneric_WidgetBoldGrid_Logo.svgGeneric_WidgetBoldGrid_View.jsGeneric_WidgetBoldGrid_View.phpGeneric_WidgetCommunity.phpGeneric_WidgetCommunity_View.phpGeneric_WidgetServices.phpGeneric_WidgetServices_View.phpGeneric_WidgetSpreadTheWord.jsGeneric_WidgetSpreadTheWord_Plugin.phpGeneric_WidgetSpreadTheWord_View.phpLICENSELicensing_AdminActions.phpLicensing_Core.phpLicensing_Plugin_Admin.phpMinify_AutoCss.phpMinify_AutoJs.phpMinify_ConfigLabels.phpMinify_ContentMinifier.phpMinify_Core.phpMinify_Environment.phpMinify_Environment_LiteSpeed.phpMinify_Extract.phpMinify_GeneralPage_View_ShowHelp.jsMinify_GeneralPage_View_ShowHelpForce.jsMinify_HelpPopup_View.phpMinify_MinifiedFileRequestHandler.phpMinify_Page.phpMinify_Plugin.phpMinify_Plugin_Admin.phpMobile_Base.phpMobile_Redirect.phpMobile_Referrer.phpMobile_UserAgent.phpModuleStatus.phpObjectCache_ConfigLabels.phpObjectCache_Environment.phpObjectCache_Page.phpObjectCache_Page_View_PurgeLog.phpObjectCache_Plugin.phpObjectCache_Plugin_Admin.phpObjectCache_WpObjectCache.phpObjectCache_WpObjectCache_Regular.phpPageSpeed_Api.phpPageSpeed_Data.phpPageSpeed_Instructions.phpPageSpeed_Page.phpPageSpeed_Page_View.cssPageSpeed_Page_View.jsPageSpeed_Page_View.phpPageSpeed_Page_View_FromAPI.phpPageSpeed_Widget.phpPageSpeed_Widget_View.cssPageSpeed_Widget_View.jsPageSpeed_Widget_View.phpPageSpeed_Widget_View_FromApi.phpPgCache_ConfigLabels.phpPgCache_ContentGrabber.phpPgCache_Environment.phpPgCache_Flush.phpPgCache_Page.phpPgCache_Page_View.jsPgCache_Plugin.phpPgCache_Plugin_Admin.phpPgCache_QsExempts.phpRoot_AdminActions.phpRoot_AdminActivation.phpRoot_AdminMenu.phpRoot_Environment.phpRoot_Loader.phpSetupGuide_Plugin_Admin.phpSupport_AdminActions.phpSupport_Page.phpSupport_Page_View_DoneContent.phpSupport_Page_View_PageContent.phpSystemOpCache_AdminActions.phpSystemOpCache_Core.phpSystemOpCache_GeneralPage_View.phpSystemOpCache_Plugin_Admin.phpUsageStatistics_AdminActions.phpUsageStatistics_Core.phpUsageStatistics_GeneralPage.phpUsageStatistics_GeneralPage_View.phpUsageStatistics_Page.phpUsageStatistics_Page_DbRequests_View.phpUsageStatistics_Page_ObjectCacheLog_View.phpUsageStatistics_Page_PageCacheRequests_View.phpUsageStatistics_Page_View.cssUsageStatistics_Page_View.jsUsageStatistics_Page_View.phpUsageStatistics_Page_View_Ad.phpUsageStatistics_Page_View_Disabled.phpUsageStatistics_Page_View_Free.phpUsageStatistics_Page_View_NoDebugMode.phpUsageStatistics_Plugin.phpUsageStatistics_Plugin_Admin.phpUsageStatistics_Source_AccessLog.phpUsageStatistics_Source_DbQueriesLog.phpUsageStatistics_Source_ObjectCacheLog.phpUsageStatistics_Source_PageCacheLog.phpUsageStatistics_Source_Wpdb.phpUsageStatistics_Sources.phpUsageStatistics_Sources_Apc.phpUsageStatistics_Sources_Memcached.phpUsageStatistics_Sources_Redis.phpUsageStatistics_StorageReader.phpUsageStatistics_StorageWriter.phpUsageStatistics_Widget.phpUsageStatistics_Widget_View.jsUsageStatistics_Widget_View.phpUsageStatistics_Widget_View_Disabled.phpUserExperience_Emoji_Extension.phpUserExperience_GeneralPage.phpUserExperience_GeneralPage_View.phpUserExperience_LazyLoad_GoogleMaps_GoogleMapsEasy.phpUserExperience_LazyLoad_GoogleMaps_WPGoogleMapPlugin.phpUserExperience_LazyLoad_GoogleMaps_WPGoogleMaps.phpUserExperience_LazyLoad_Mutator.phpUserExperience_LazyLoad_Mutator_Picture.phpUserExperience_LazyLoad_Mutator_Unmutable.phpUserExperience_LazyLoad_Page_View.phpUserExperience_LazyLoad_Plugin.phpUserExperience_OEmbed_Extension.phpUserExperience_Page.phpUserExperience_Page_View.phpUserExperience_Plugin_Admin.phpUserExperience_Plugin_Jquery.phpUtil_Activation.phpUtil_Admin.phpUtil_AttachToActions.phpUtil_Bus.phpUtil_ConfigLabel.phpUtil_Content.phpUtil_Debug.phpUtil_DebugPurgeLog_Reader.phpUtil_Environment.phpUtil_Environment_Exception.phpUtil_Environment_Exceptions.phpUtil_File.phpUtil_Http.phpUtil_Installed.phpUtil_Mime.phpUtil_PageSpeed.phpUtil_PageUrls.phpUtil_Request.phpUtil_Rule.phpUtil_Theme.phpUtil_Ui.phpUtil_UsageStatistics.phpUtil_Widget.phpUtil_WpFile.phpUtil_WpFile_FilesystemChmodException.phpUtil_WpFile_FilesystemCopyException.phpUtil_WpFile_FilesystemMkdirException.phpUtil_WpFile_FilesystemModifyException.phpUtil_WpFile_FilesystemOperationException.phpUtil_WpFile_FilesystemRmException.phpUtil_WpFile_FilesystemRmdirException.phpUtil_WpFile_FilesystemWriteException.phpUtil_WpmuBlogmap.phpVarnish_Flush.phpVarnish_Plugin.php
extension-example
inc
index.html
ini
languages
lib
Azure
GuzzleHttp
MicrosoftAzureStorage
Blob
Common
PsrHttpMessage
loader.php
CSSTidy
Db
Google
Minify
NetDNA
NewRelic
Nusoap
OAuth
S3Compatible.php
SNS
YuiCssMin
index.html
press.txt
pub
readme.txt
vendor
autoload.php
aws
aws-php-sns-message-validator
aws-sdk-php
CODE_OF_CONDUCT.mdLICENSE.mdNOTICE.mdcomposer.json
src
ACMPCA
AbstractConfigurationProvider.php
AccessAnalyzer
Acm
AlexaForBusiness
Amplify
AmplifyBackend
Api
ApiGateway
ApiGatewayManagementApi
ApiGatewayV2
AppConfig
AppIntegrationsService
AppMesh
AppRegistry
AppRunner
AppSync
Appflow
ApplicationAutoScaling
ApplicationCostProfiler
ApplicationDiscoveryService
ApplicationInsights
Appstream
Arn
Athena
AuditManager
AugmentedAIRuntime
AutoScaling
AutoScalingPlans
AwsClient.phpAwsClientInterface.phpAwsClientTrait.php
Backup
Batch
Braket
Budgets
CacheInterface.php
Chime
ClientResolver.php
ClientSideMonitoring
Cloud9
CloudDirectory
CloudFormation
CloudFront
CloudHSMV2
CloudHsm
CloudSearch
CloudSearchDomain
CloudTrail
CloudWatch
CloudWatchEvents
CloudWatchLogs
CodeArtifact
CodeBuild
CodeCommit
CodeDeploy
CodeGuruProfiler
CodeGuruReviewer
CodePipeline
CodeStar
CodeStarNotifications
CodeStarconnections
CognitoIdentity
CognitoIdentityProvider
CognitoSync
Command.phpCommandInterface.phpCommandPool.php
Comprehend
ComprehendMedical
ComputeOptimizer
ConfigService
ConfigurationProviderInterface.php
Connect
ConnectContactLens
ConnectParticipant
CostExplorer
CostandUsageReportService
Credentials
Crypto
CustomerProfiles
DAX
DLM
DataExchange
DataPipeline
DataSync
DatabaseMigrationService
Detective
DevOpsGuru
DeviceFarm
DirectConnect
DirectoryService
DocDB
DoctrineCacheAdapter.php
DynamoDb
DynamoDbStreams
EBS
EC2InstanceConnect
ECRPublic
EKS
EMRContainers
Ec2
Ecr
Ecs
Efs
ElastiCache
ElasticBeanstalk
ElasticInference
ElasticLoadBalancing
ElasticLoadBalancingV2
ElasticTranscoder
ElasticsearchService
Emr
Endpoint
EndpointDiscovery
EndpointParameterMiddleware.php
EventBridge
Exception
FIS
FMS
FSx
FinSpaceData
Firehose
ForecastQueryService
ForecastService
FraudDetector
GameLift
Glacier
GlobalAccelerator
Glue
GlueDataBrew
Greengrass
GreengrassV2
GroundStation
GuardDuty
Handler
HandlerList.phpHasDataTrait.phpHasMonitoringEventsTrait.phpHashInterface.phpHashingStream.php
Health
HealthLake
History.php
Honeycode
IVS
Iam
IdempotencyTokenMiddleware.php
IdentityStore
ImportExport
InputValidationMiddleware.php
Inspector
IoT1ClickDevicesService
IoT1ClickProjects
IoTAnalytics
IoTDeviceAdvisor
IoTEvents
IoTEventsData
IoTFleetHub
IoTJobsDataPlane
IoTSecureTunneling
IoTSiteWise
IoTThingsGraph
IoTWireless
Iot
IotDataPlane
JsonCompiler.php
Kafka
Kinesis
KinesisAnalytics
KinesisAnalyticsV2
KinesisVideo
KinesisVideoArchivedMedia
KinesisVideoMedia
KinesisVideoSignalingChannels
Kms
LakeFormation
Lambda
LexModelBuildingService
LexModelsV2
LexRuntimeService
LexRuntimeV2
LicenseManager
Lightsail
LocationService
LookoutEquipment
LookoutMetrics
LookoutforVision
LruArrayCache.php
MQ
MTurk
MWAA
MachineLearning
Macie
Macie2
ManagedBlockchain
MarketplaceCatalog
MarketplaceCommerceAnalytics
MarketplaceEntitlementService
MarketplaceMetering
MediaConnect
MediaConvert
MediaLive
MediaPackage
MediaPackageVod
MediaStore
MediaStoreData
MediaTailor
Middleware.php
MigrationHub
MigrationHubConfig
Mobile
MockHandler.phpMonitoringEventsInterface.phpMultiRegionClient.php
Multipart
Neptune
NetworkFirewall
NetworkManager
NimbleStudio
OpsWorks
OpsWorksCM
Organizations
Outposts
PI
Personalize
PersonalizeEvents
PersonalizeRuntime
PhpHash.php
Pinpoint
PinpointEmail
PinpointSMSVoice
Polly
PresignUrlMiddleware.php
Pricing
PrometheusService
Psr16CacheAdapter.phpPsrCacheAdapter.php
QLDB
QLDBSession
QuickSight
RAM
RDSDataService
Rds
Redshift
RedshiftDataAPIService
Rekognition
ResourceGroups
ResourceGroupsTaggingAPI
ResponseContainerInterface.phpResult.phpResultInterface.phpResultPaginator.php
Retry
RetryMiddleware.phpRetryMiddlewareV2.php
RoboMaker
Route53
Route53Domains
Route53Resolver
S3
S3Control
S3Outposts
SSMContacts
SSMIncidents
SSO
SSOAdmin
SSOOIDC
SageMaker
SageMakerFeatureStoreRuntime
SageMakerRuntime
SagemakerEdgeManager
SavingsPlans
Schemas
Sdk.php
SecretsManager
SecurityHub
ServerlessApplicationRepository
ServiceCatalog
ServiceDiscovery
ServiceQuotas
Ses
SesV2
Sfn
Shield
Signature
Sms
SnowBall
Sns
Sqs
Ssm
StorageGateway
StreamRequestPayloadMiddleware.php
Sts
Support
Swf
Synthetics
Textract
TimestreamQuery
TimestreamWrite
TraceMiddleware.php
TranscribeService
Transfer
Translate
WAFV2
Waf
WafRegional
Waiter.php
WellArchitected
WorkDocs
WorkLink
WorkMail
WorkMailMessageFlow
WorkSpaces
WrappedHttpHandler.php
XRay
data
accessanalyzer
acm-pca
acm
alexaforbusiness
aliases.json.php
amp
amplify
amplifybackend
apigateway
apigatewaymanagementapi
apigatewayv2
appconfig
appflow
appintegrations
application-autoscaling
application-insights
applicationcostprofiler
appmesh
apprunner
appstream
appsync
athena
auditmanager
autoscaling-plans
autoscaling
backup
batch
braket
budgets
ce
chime
cloud9
clouddirectory
cloudformation
cloudfront
cloudhsm
cloudhsmv2
cloudsearch
cloudsearchdomain
2013-01-01
cloudtrail
codeartifact
codebuild
codecommit
codedeploy
codeguru-reviewer
codeguruprofiler
codepipeline
codestar-connections
codestar-notifications
codestar
cognito-identity
cognito-idp
cognito-sync
comprehend
comprehendmedical
compute-optimizer
config
connect-contact-lens
connect
connectparticipant
cur
customer-profiles
data.iot
databrew
dataexchange
datapipeline
datasync
dax
detective
devicefarm
devops-guru
directconnect
discovery
dlm
dms
docdb
ds
dynamodb
ebs
ec2-instance-connect
ec2
ecr-public
ecr
ecs
eks
elastic-inference
elasticache
elasticbeanstalk
elasticfilesystem
elasticloadbalancing
elasticloadbalancingv2
elasticmapreduce
elastictranscoder
email
emr-containers
endpoints.json.phpendpoints_prefix_history.json.php
entitlement.marketplace
es
eventbridge
events
finspace-data
finspace
firehose
fis
fms
forecast
forecastquery
frauddetector
fsx
gamelift
glacier
globalaccelerator
glue
greengrass
2017-06-07
greengrassv2
groundstation
guardduty
health
healthlake
honeycode
iam
identitystore
imagebuilder
importexport
inspector
iot-jobs-data
iot
iot1click-devices
2018-05-14
iot1click-projects
iotanalytics
iotdeviceadvisor
iotevents-data
iotevents
iotfleethub
iotsecuretunneling
iotsitewise
iotthingsgraph
iotwireless
ivs
kafka
kendra
kinesis-video-archived-media
kinesis-video-media
kinesis-video-signaling
kinesis
kinesisanalytics
kinesisanalyticsv2
kinesisvideo
kms
lakeformation
lambda
lex-models
license-manager
lightsail
location
logs
lookoutequipment
lookoutmetrics
lookoutvision
machinelearning
macie
macie2
managedblockchain
manifest.json.php
marketplace-catalog
marketplacecommerceanalytics
mediaconnect
mediaconvert
medialive
mediapackage-vod
mediapackage
mediastore-data
mediastore
mediatailor
metering.marketplace
mgh
mgn
migrationhub-config
mobile
models.lex.v2
monitoring
mq
mturk-requester
mwaa
neptune
network-firewall
networkmanager
nimble
opsworks
opsworkscm
organizations
outposts
personalize-events
personalize-runtime
personalize
pi
pinpoint-email
pinpoint
2016-12-01
polly
pricing
qldb-session
qldb
quicksight
ram
rds-data
rds
redshift-data
redshift
rekognition
resource-groups
resourcegroupstaggingapi
robomaker
route53
route53domains
route53resolver
runtime.lex.v2
runtime.lex
runtime.sagemaker
s3
s3control
s3outposts
sagemaker-a2i-runtime
sagemaker-edge
sagemaker-featurestore-runtime
sagemaker
savingsplans
schemas
secretsmanager
securityhub
serverlessrepo
service-quotas
servicecatalog-appregistry
servicecatalog
servicediscovery
sesv2
shield
signer
sms-voice
2018-09-05
sms
snowball
sns
sqs
ssm-contacts
ssm-incidents
ssm
sso-admin
sso-oidc
sso
states
storagegateway
streams.dynamodb
sts
support
swf
synthetics
textract
timestream-query
timestream-write
transcribe
transfer
translate
waf-regional
waf
wafv2
wellarchitected
workdocs
worklink
workmail
workmailmessageflow
workspaces
xray
finspace
functions.php
imagebuilder
kendra
mgn
signer
bin
composer
guzzlehttp
guzzle
.editorconfig.gitattributes
.github
.php_csCHANGELOG.mdDockerfileLICENSEMakefileREADME.mdUPGRADING.md
build
composer.json
docs
phpstan-baseline.neonphpstan.neon.distphpunit.xml.dist
src
tests
promises
psr7
mtdowling
psr
ralouphie
symfony
w3-total-cache-api.phpw3-total-cache-old-php.phpw3-total-cache.php
wp-content
wp-piwik
LICENSEREADME.mdbitcoin.png
classes
config.php
css
gpl-3.0.htmlindex.php
js
languages
proxy
readme.txtscreenshot-1.gifscreenshot-2.gifscreenshot-3.gifscreenshot-4.gifscreenshot-5.gifuninstall.php
update
wp-piwik.phpwpml-config.xml
wp-webauthn
LICENSE
blocks
css
js
languages
readme.txt
vendor
autoload.php
beberlei
brick
composer
fgrosse
league
nyholm
php-http
psr
ramsey
collection
uuid
LICENSEREADME.mdcomposer.json
src
BinaryUtils.php
Builder
Codec
Converter
DegradedUuid.phpDeprecatedUuidInterface.phpDeprecatedUuidMethodsTrait.php
Exception
FeatureSet.php
Fields
Generator
Guid
Lazy
Math
Nonstandard
Provider
Rfc4122
Type
Uuid.phpUuidFactory.phpUuidFactoryInterface.phpUuidInterface.php
Validator
functions.php
spomky-labs
symfony
thecodingmachine
safe
LICENSEREADME.mdcomposer.json
deprecated
generated
Exceptions
apache.phpapcu.phparray.phpbzip2.phpcalendar.phpclassobj.phpcom.phpcubrid.phpcurl.phpdatetime.phpdir.phpeio.phperrorfunc.phpexec.phpfileinfo.phpfilesystem.phpfilter.phpfpm.phpftp.phpfunchand.phpfunctionsList.phpgmp.phpgnupg.phphash.phpibase.phpibmDb2.phpiconv.phpimage.phpimap.phpinfo.phpingres-ii.phpinotify.phpjson.phpldap.phplibxml.phplzf.phpmailparse.phpmbstring.phpmisc.phpmsql.phpmysql.phpmysqli.phpmysqlndMs.phpmysqlndQc.phpnetwork.phpoci8.phpopcache.phpopenssl.phpoutcontrol.phppassword.phppcntl.phppcre.phppdf.phppgsql.phpposix.phpps.phppspell.phpreadline.phprpminfo.phprrd.phpsem.phpsession.phpshmop.phpsimplexml.phpsockets.phpsodium.phpsolr.phpspl.phpsqlsrv.phpssdeep.phpssh2.phpstream.phpstrings.phpswoole.phpuodbc.phpuopz.phpurl.phpvar.phpxdiff.phpxml.phpxmlrpc.phpyaml.phpyaz.phpzip.phpzlib.php
lib
rector-migrate-0.7.php
web-auth
cose-lib
metadata-service
webauthn-lib
LICENSEcomposer.json
src
AttestationStatement
AttestedCredentialData.php
AuthenticationExtensions
AuthenticatorAssertionResponse.phpAuthenticatorAssertionResponseValidator.phpAuthenticatorAttestationResponse.phpAuthenticatorAttestationResponseValidator.phpAuthenticatorData.phpAuthenticatorResponse.phpAuthenticatorSelectionCriteria.php
CertificateChainChecker
CertificateToolbox.phpCollectedClientData.php
Counter
Credential.phpPublicKeyCredential.phpPublicKeyCredentialCreationOptions.phpPublicKeyCredentialDescriptor.phpPublicKeyCredentialDescriptorCollection.phpPublicKeyCredentialEntity.phpPublicKeyCredentialLoader.phpPublicKeyCredentialOptions.phpPublicKeyCredentialParameters.phpPublicKeyCredentialRequestOptions.phpPublicKeyCredentialRpEntity.phpPublicKeyCredentialSource.phpPublicKeyCredentialSourceRepository.phpPublicKeyCredentialUserEntity.phpServer.phpStringStream.php
TokenBinding
TrustPath
U2FPublicKey.php
Util
web-token
jwt-core
jwt-key-mgmt
jwt-signature-algorithm-ecdsa
jwt-signature-algorithm-eddsa
jwt-signature-algorithm-rsa
jwt-signature
wp-webauthn.phpwwa-admin-content.phpwwa-ajax.phpwwa-compatibility.phpwwa-functions.phpwwa-menus.phpwwa-profile-content.phpwwa-shortcodes.phpwwa-version.php

@ -0,0 +1,4 @@
# Contributing
This repository is a sub repository of [the JWT Framework](https://github.com/web-token/jwt-framework) project and is READ ONLY.
Please do not submit any Pull Requests here. It will be automatically closed.

@ -0,0 +1,3 @@
Please do not submit any Pull Requests here. It will be automatically closed.
You should submit it here: https://github.com/web-token/jwt-framework/pulls

@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\Analyzer;
use Jose\Component\Core\JWK;
final class AlgorithmAnalyzer implements KeyAnalyzer
{
public function analyze(JWK $jwk, MessageBag $bag): void
{
if (!$jwk->has('alg')) {
$bag->add(Message::medium('The parameter "alg" should be added.'));
}
}
}

@ -0,0 +1,61 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\Analyzer;
use Base64Url\Base64Url;
use Brick\Math\BigInteger;
use Jose\Component\Core\JWK;
use Jose\Component\Core\Util\Ecc\NistCurve;
use RuntimeException;
final class ES256KeyAnalyzer implements KeyAnalyzer
{
/**
* @throws RuntimeException if the component "web-token/jwt-util-ecc" is missing
*/
public function __construct()
{
if (!class_exists(NistCurve::class)) {
throw new RuntimeException('Please install web-token/jwt-util-ecc to use this key analyzer');
}
}
public function analyze(JWK $jwk, MessageBag $bag): void
{
if ('EC' !== $jwk->get('kty')) {
return;
}
if (!$jwk->has('crv')) {
$bag->add(Message::high('Invalid key. The components "crv" is missing.'));
return;
}
if ('P-256' !== $jwk->get('crv')) {
return;
}
$x = Base64Url::decode($jwk->get('x'));
$xLength = 8 * mb_strlen($x, '8bit');
$y = Base64Url::decode($jwk->get('y'));
$yLength = 8 * mb_strlen($y, '8bit');
if ($yLength !== $xLength || 256 !== $yLength) {
$bag->add(Message::high('Invalid key. The components "x" and "y" size shall be 256 bits.'));
}
$xBI = BigInteger::fromBase(bin2hex($x), 16);
$yBI = BigInteger::fromBase(bin2hex($y), 16);
$curve = NistCurve::curve256();
if (!$curve->contains($xBI, $yBI)) {
$bag->add(Message::high('Invalid key. The point is not on the curve.'));
}
}
}

@ -0,0 +1,61 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\Analyzer;
use Base64Url\Base64Url;
use Brick\Math\BigInteger;
use Jose\Component\Core\JWK;
use Jose\Component\Core\Util\Ecc\NistCurve;
use RuntimeException;
final class ES384KeyAnalyzer implements KeyAnalyzer
{
/**
* @throws RuntimeException if the component "web-token/jwt-util-ecc" is missing
*/
public function __construct()
{
if (!class_exists(NistCurve::class)) {
throw new RuntimeException('Please install web-token/jwt-util-ecc to use this key analyzer');
}
}
public function analyze(JWK $jwk, MessageBag $bag): void
{
if ('EC' !== $jwk->get('kty')) {
return;
}
if (!$jwk->has('crv')) {
$bag->add(Message::high('Invalid key. The components "crv" is missing.'));
return;
}
if ('P-384' !== $jwk->get('crv')) {
return;
}
$x = Base64Url::decode($jwk->get('x'));
$xLength = 8 * mb_strlen($x, '8bit');
$y = Base64Url::decode($jwk->get('y'));
$yLength = 8 * mb_strlen($y, '8bit');
if ($yLength !== $xLength || 384 !== $yLength) {
$bag->add(Message::high('Invalid key. The components "x" and "y" size shall be 384 bits.'));
}
$xBI = BigInteger::fromBase(bin2hex($x), 16);
$yBI = BigInteger::fromBase(bin2hex($y), 16);
$curve = NistCurve::curve384();
if (!$curve->contains($xBI, $yBI)) {
$bag->add(Message::high('Invalid key. The point is not on the curve.'));
}
}
}

@ -0,0 +1,61 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\Analyzer;
use Base64Url\Base64Url;
use Brick\Math\BigInteger;
use Jose\Component\Core\JWK;
use Jose\Component\Core\Util\Ecc\NistCurve;
use RuntimeException;
final class ES512KeyAnalyzer implements KeyAnalyzer
{
/**
* @throws RuntimeException if the component "web-token/jwt-util-ecc" is missing
*/
public function __construct()
{
if (!class_exists(NistCurve::class)) {
throw new RuntimeException('Please install web-token/jwt-util-ecc to use this key analyzer');
}
}
public function analyze(JWK $jwk, MessageBag $bag): void
{
if ('EC' !== $jwk->get('kty')) {
return;
}
if (!$jwk->has('crv')) {
$bag->add(Message::high('Invalid key. The components "crv" is missing.'));
return;
}
if ('P-521' !== $jwk->get('crv')) {
return;
}
$x = Base64Url::decode($jwk->get('x'));
$xLength = 8 * mb_strlen($x, '8bit');
$y = Base64Url::decode($jwk->get('y'));
$yLength = 8 * mb_strlen($y, '8bit');
if ($yLength !== $xLength || 528 !== $yLength) {
$bag->add(Message::high('Invalid key. The components "x" and "y" size shall be 528 bits.'));
}
$xBI = BigInteger::fromBase(bin2hex($x), 16);
$yBI = BigInteger::fromBase(bin2hex($y), 16);
$curve = NistCurve::curve521();
if (!$curve->contains($xBI, $yBI)) {
$bag->add(Message::high('Invalid key. The point is not on the curve.'));
}
}
}

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\Analyzer;
use Base64Url\Base64Url;
use Jose\Component\Core\JWK;
final class HS256KeyAnalyzer implements KeyAnalyzer
{
public function analyze(JWK $jwk, MessageBag $bag): void
{
if ('oct' !== $jwk->get('kty')) {
return;
}
if (!$jwk->has('alg') || 'HS256' !== $jwk->get('alg')) {
return;
}
$k = Base64Url::decode($jwk->get('k'));
$kLength = 8 * mb_strlen($k, '8bit');
if ($kLength < 256) {
$bag->add(Message::high('HS256 algorithm requires at least 256 bits key length.'));
}
}
}

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\Analyzer;
use Base64Url\Base64Url;
use Jose\Component\Core\JWK;
final class HS384KeyAnalyzer implements KeyAnalyzer
{
public function analyze(JWK $jwk, MessageBag $bag): void
{
if ('oct' !== $jwk->get('kty')) {
return;
}
if (!$jwk->has('alg') || 'HS384' !== $jwk->get('alg')) {
return;
}
$k = Base64Url::decode($jwk->get('k'));
$kLength = 8 * mb_strlen($k, '8bit');
if ($kLength < 384) {
$bag->add(Message::high('HS384 algorithm requires at least 384 bits key length.'));
}
}
}

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\Analyzer;
use Base64Url\Base64Url;
use Jose\Component\Core\JWK;
final class HS512KeyAnalyzer implements KeyAnalyzer
{
public function analyze(JWK $jwk, MessageBag $bag): void
{
if ('oct' !== $jwk->get('kty')) {
return;
}
if (!$jwk->has('alg') || 'HS512' !== $jwk->get('alg')) {
return;
}
$k = Base64Url::decode($jwk->get('k'));
$kLength = 8 * mb_strlen($k, '8bit');
if ($kLength < 512) {
$bag->add(Message::high('HS512 algorithm requires at least 512 bits key length.'));
}
}
}

@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\Analyzer;
use Jose\Component\Core\JWK;
interface KeyAnalyzer
{
/**
* This method will analyse the key and add messages to the message bag if needed.
*/
public function analyze(JWK $jwk, MessageBag $bag): void;
}

@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\Analyzer;
use Jose\Component\Core\JWK;
class KeyAnalyzerManager
{
/**
* @var KeyAnalyzer[]
*/
private $analyzers = [];
/**
* Adds a Key Analyzer to the manager.
*/
public function add(KeyAnalyzer $analyzer): void
{
$this->analyzers[] = $analyzer;
}
/**
* This method will analyze the JWK object using all analyzers.
* It returns a message bag that may contains messages.
*/
public function analyze(JWK $jwk): MessageBag
{
$bag = new MessageBag();
foreach ($this->analyzers as $analyzer) {
$analyzer->analyze($jwk, $bag);
}
return $bag;
}
}

@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\Analyzer;
use Jose\Component\Core\JWK;
final class KeyIdentifierAnalyzer implements KeyAnalyzer
{
public function analyze(JWK $jwk, MessageBag $bag): void
{
if (!$jwk->has('kid')) {
$bag->add(Message::medium('The parameter "kid" should be added.'));
}
}
}

@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\Analyzer;
use Jose\Component\Core\JWKSet;
interface KeysetAnalyzer
{
/**
* This method will analyse the key set and add messages to the message bag if needed.
*/
public function analyze(JWKSet $JWKSet, MessageBag $bag): void;
}

@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\Analyzer;
use Jose\Component\Core\JWKSet;
class KeysetAnalyzerManager
{
/**
* @var KeysetAnalyzer[]
*/
private $analyzers = [];
/**
* Adds a Keyset Analyzer to the manager.
*/
public function add(KeysetAnalyzer $analyzer): void
{
$this->analyzers[] = $analyzer;
}
/**
* This method will analyze the JWKSet object using all analyzers.
* It returns a message bag that may contains messages.
*/
public function analyze(JWKSet $jwkset): MessageBag
{
$bag = new MessageBag();
foreach ($this->analyzers as $analyzer) {
$analyzer->analyze($jwkset, $bag);
}
return $bag;
}
}

@ -0,0 +1,97 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\Analyzer;
use JsonSerializable;
class Message implements JsonSerializable
{
public const SEVERITY_LOW = 'low';
public const SEVERITY_MEDIUM = 'medium';
public const SEVERITY_HIGH = 'high';
/**
* @var string
*/
private $message;
/**
* @var string
*/
private $severity;
/**
* Message constructor.
*/
private function __construct(string $message, string $severity)
{
$this->message = $message;
$this->severity = $severity;
}
/**
* Creates a message with severity=low.
*
* @return Message
*/
public static function low(string $message): self
{
return new self($message, self::SEVERITY_LOW);
}
/**
* Creates a message with severity=medium.
*
* @return Message
*/
public static function medium(string $message): self
{
return new self($message, self::SEVERITY_MEDIUM);
}
/**
* Creates a message with severity=high.
*
* @return Message
*/
public static function high(string $message): self
{
return new self($message, self::SEVERITY_HIGH);
}
/**
* Returns the message.
*/
public function getMessage(): string
{
return $this->message;
}
/**
* Returns the severity of the message.
*/
public function getSeverity(): string
{
return $this->severity;
}
public function jsonSerialize(): array
{
return [
'message' => $this->message,
'severity' => $this->severity,
];
}
}

@ -0,0 +1,71 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\Analyzer;
use ArrayIterator;
use function count;
use Countable;
use IteratorAggregate;
use JsonSerializable;
use Traversable;
class MessageBag implements JsonSerializable, IteratorAggregate, Countable
{
/**
* @var Message[]
*/
private $messages = [];
/**
* Adds a message to the message bag.
*/
public function add(Message $message): void
{
$this->messages[] = $message;
}
/**
* Returns all messages.
*
* @return Message[]
*/
public function all(): array
{
return $this->messages;
}
/**
* {@inheritdoc}
*/
public function jsonSerialize(): array
{
return array_values($this->messages);
}
/**
* {@inheritdoc}
*/
public function count(): int
{
return count($this->messages);
}
/**
* {@inheritdoc}
*/
public function getIterator(): Traversable
{
return new ArrayIterator($this->messages);
}
}

@ -0,0 +1,49 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\Analyzer;
use Jose\Component\Core\JWKSet;
final class MixedKeyTypes implements KeysetAnalyzer
{
public function analyze(JWKSet $jwkset, MessageBag $bag): void
{
if (0 === $jwkset->count()) {
return;
}
$hasSymmetricKeys = false;
$hasAsymmetricKeys = false;
foreach ($jwkset as $jwk) {
switch ($jwk->get('kty')) {
case 'oct':
$hasSymmetricKeys = true;
break;
case 'OKP':
case 'RSA':
case 'EC':
$hasAsymmetricKeys = true;
break;
}
}
if ($hasAsymmetricKeys && $hasSymmetricKeys) {
$bag->add(Message::medium('This key set mixes symmetric and assymetric keys.'));
}
}
}

@ -0,0 +1,48 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\Analyzer;
use Jose\Component\Core\JWKSet;
final class MixedPublicAndPrivateKeys implements KeysetAnalyzer
{
public function analyze(JWKSet $jwkset, MessageBag $bag): void
{
if (0 === $jwkset->count()) {
return;
}
$hasPublicKeys = false;
$hasPrivateKeys = false;
foreach ($jwkset as $jwk) {
switch ($jwk->get('kty')) {
case 'OKP':
case 'RSA':
case 'EC':
if ($jwk->has('d')) {
$hasPrivateKeys = true;
} else {
$hasPublicKeys = true;
}
break;
}
}
if ($hasPrivateKeys && $hasPublicKeys) {
$bag->add(Message::high('This key set mixes public and private keys.'));
}
}
}

@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\Analyzer;
use Jose\Component\Core\JWK;
final class NoneAnalyzer implements KeyAnalyzer
{
public function analyze(JWK $jwk, MessageBag $bag): void
{
if ('none' !== $jwk->get('kty')) {
return;
}
$bag->add(Message::high('This key is a meant to be used with the algorithm "none". This algorithm is not secured and should be used with care.'));
}
}

@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\Analyzer;
use Base64Url\Base64Url;
use Jose\Component\Core\JWK;
final class OctAnalyzer implements KeyAnalyzer
{
public function analyze(JWK $jwk, MessageBag $bag): void
{
if ('oct' !== $jwk->get('kty')) {
return;
}
$k = Base64Url::decode($jwk->get('k'));
$kLength = 8 * mb_strlen($k, '8bit');
if ($kLength < 128) {
$bag->add(Message::high('The key length is less than 128 bits.'));
}
}
}

@ -0,0 +1,54 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\Analyzer;
use Base64Url\Base64Url;
use InvalidArgumentException;
use function is_array;
use Jose\Component\Core\JWK;
final class RsaAnalyzer implements KeyAnalyzer
{
public function analyze(JWK $jwk, MessageBag $bag): void
{
if ('RSA' !== $jwk->get('kty')) {
return;
}
$this->checkExponent($jwk, $bag);
$this->checkModulus($jwk, $bag);
}
private function checkExponent(JWK $jwk, MessageBag $bag): void
{
$exponent = unpack('l', str_pad(Base64Url::decode($jwk->get('e')), 4, "\0"));
if (!is_array($exponent) || !isset($exponent[1])) {
throw new InvalidArgumentException('Unable to get the private key');
}
if ($exponent[1] < 65537) {
$bag->add(Message::high('The exponent is too low. It should be at least 65537.'));
}
}
private function checkModulus(JWK $jwk, MessageBag $bag): void
{
$n = 8 * mb_strlen(Base64Url::decode($jwk->get('n')), '8bit');
if ($n < 2048) {
$bag->add(Message::high('The key length is less than 2048 bits.'));
}
if ($jwk->has('d') && (!$jwk->has('p') || !$jwk->has('q') || !$jwk->has('dp') || !$jwk->has('dq') || !$jwk->has('p') || !$jwk->has('qi'))) {
$bag->add(Message::medium('The key is a private RSA key, but Chinese Remainder Theorem primes are missing. These primes are not mandatory, but signatures and decryption processes are faster when available.'));
}
}
}

@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\Analyzer;
use function in_array;
use Jose\Component\Core\JWK;
final class UsageAnalyzer implements KeyAnalyzer
{
public function analyze(JWK $jwk, MessageBag $bag): void
{
if (!$jwk->has('use')) {
$bag->add(Message::medium('The parameter "use" should be added.'));
} elseif (!in_array($jwk->get('use'), ['sig', 'enc'], true)) {
$bag->add(Message::high(sprintf('The parameter "use" has an unsupported value "%s". Please use "sig" (signature) or "enc" (encryption).', $jwk->get('use'))));
}
if ($jwk->has('key_ops') && !in_array($jwk->get('key_ops'), ['sign', 'verify', 'encrypt', 'decrypt', 'wrapKey', 'unwrapKey'], true)) {
$bag->add(Message::high(sprintf('The parameter "key_ops" has an unsupported value "%s". Please use one of the following values: %s.', $jwk->get('use'), implode(', ', ['verify', 'sign', 'encryp', 'decrypt', 'wrapKey', 'unwrapKey']))));
}
}
}

@ -0,0 +1,48 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\Analyzer;
use Base64Url\Base64Url;
use Jose\Component\Core\JWK;
use ZxcvbnPhp\Zxcvbn;
final class ZxcvbnKeyAnalyzer implements KeyAnalyzer
{
public function analyze(JWK $jwk, MessageBag $bag): void
{
if ('oct' !== $jwk->get('kty')) {
return;
}
$k = Base64Url::decode($jwk->get('k'));
if (class_exists(Zxcvbn::class)) {
$zxcvbn = new Zxcvbn();
$strength = $zxcvbn->passwordStrength($k);
switch (true) {
case $strength['score'] < 3:
$bag->add(Message::high('The octet string is weak and easily guessable. Please change your key as soon as possible.'));
break;
case 3 === $strength['score']:
$bag->add(Message::medium('The octet string is safe, but a longer key is preferable.'));
break;
default:
break;
}
}
}
}

@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement;
use function is_array;
use Jose\Component\Core\JWKSet;
use Jose\Component\Core\Util\JsonConverter;
use RuntimeException;
class JKUFactory extends UrlKeySetFactory
{
/**
* This method will try to fetch the url a retrieve the key set.
* Throws an exception in case of failure.
*
* @throws RuntimeException if the key cannot be reached
*/
public function loadFromUrl(string $url, array $header = []): JWKSet
{
$content = $this->getContent($url, $header);
$data = JsonConverter::decode($content);
if (!is_array($data)) {
throw new RuntimeException('Invalid content.');
}
return JWKSet::createFromKeyData($data);
}
}

@ -0,0 +1,328 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement;
use function array_key_exists;
use Base64Url\Base64Url;
use function extension_loaded;
use InvalidArgumentException;
use function is_array;
use function is_string;
use Jose\Component\Core\JWK;
use Jose\Component\Core\JWKSet;
use Jose\Component\Core\Util\ECKey;
use Jose\Component\KeyManagement\KeyConverter\KeyConverter;
use Jose\Component\KeyManagement\KeyConverter\RSAKey;
use RuntimeException;
use Throwable;
class JWKFactory
{
/**
* Creates a RSA key with the given key size and additional values.
*
* @param int $size The key size in bits
* @param array $values values to configure the key
*
* @throws InvalidArgumentException if the key has an invalid size
* @throws InvalidArgumentException if it is not possible to create the key
*/
public static function createRSAKey(int $size, array $values = []): JWK
{
if (0 !== $size % 8) {
throw new InvalidArgumentException('Invalid key size.');
}
if (512 > $size) {
throw new InvalidArgumentException('Key length is too short. It needs to be at least 512 bits.');
}
$key = openssl_pkey_new([
'private_key_bits' => $size,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
]);
if (false === $key) {
throw new InvalidArgumentException('Unable to create the key');
}
$details = openssl_pkey_get_details($key);
if (!is_array($details)) {
throw new InvalidArgumentException('Unable to create the key');
}
$rsa = RSAKey::createFromKeyDetails($details['rsa']);
$values = array_merge(
$values,
$rsa->toArray()
);
return new JWK($values);
}
/**
* Creates a EC key with the given curve and additional values.
*
* @param string $curve The curve
* @param array $values values to configure the key
*/
public static function createECKey(string $curve, array $values = []): JWK
{
return ECKey::createECKey($curve, $values);
}
/**
* Creates a octet key with the given key size and additional values.
*
* @param int $size The key size in bits
* @param array $values values to configure the key
*
* @throws InvalidArgumentException if the key has an invalid size
*/
public static function createOctKey(int $size, array $values = []): JWK
{
if (0 !== $size % 8) {
throw new InvalidArgumentException('Invalid key size.');
}
$values = array_merge(
$values,
[
'kty' => 'oct',
'k' => Base64Url::encode(random_bytes($size / 8)),
]
);
return new JWK($values);
}
/**
* Creates a OKP key with the given curve and additional values.
*
* @param string $curve The curve
* @param array $values values to configure the key
*
* @throws InvalidArgumentException if the extension "sobium" is not available
* @throws InvalidArgumentException if the curve is not supported
*/
public static function createOKPKey(string $curve, array $values = []): JWK
{
if (!extension_loaded('sodium')) {
throw new RuntimeException('The extension "sodium" is not available. Please install it to use this method');
}
switch ($curve) {
case 'X25519':
$keyPair = sodium_crypto_box_keypair();
$secret = sodium_crypto_box_secretkey($keyPair);
$x = sodium_crypto_box_publickey($keyPair);
break;
case 'Ed25519':
$keyPair = sodium_crypto_sign_keypair();
$secret = sodium_crypto_sign_secretkey($keyPair);
$x = sodium_crypto_sign_publickey($keyPair);
break;
default:
throw new InvalidArgumentException(sprintf('Unsupported "%s" curve', $curve));
}
$secretLength = mb_strlen($secret, '8bit');
$d = mb_substr($secret, 0, -$secretLength / 2, '8bit');
$values = array_merge(
$values,
[
'kty' => 'OKP',
'crv' => $curve,
'd' => Base64Url::encode($d),
'x' => Base64Url::encode($x),
]
);
return new JWK($values);
}
/**
* Creates a none key with the given additional values.
* Please note that this key type is not pat of any specification.
* It is used to prevent the use of the "none" algorithm with other key types.
*
* @param array $values values to configure the key
*/
public static function createNoneKey(array $values = []): JWK
{
$values = array_merge(
$values,
[
'kty' => 'none',
'alg' => 'none',
'use' => 'sig',
]
);
return new JWK($values);
}
/**
* Creates a key from a Json string.
*
* @throws InvalidArgumentException if the key or keyset is not valid
*
* @return JWK|JWKSet
*/
public static function createFromJsonObject(string $value)
{
$json = json_decode($value, true);
if (!is_array($json)) {
throw new InvalidArgumentException('Invalid key or key set.');
}
return self::createFromValues($json);
}
/**
* Creates a key or key set from the given input.
*
* @return JWK|JWKSet
*/
public static function createFromValues(array $values)
{
if (array_key_exists('keys', $values) && is_array($values['keys'])) {
return JWKSet::createFromKeyData($values);
}
return new JWK($values);
}
/**
* This method create a JWK object using a shared secret.
*/
public static function createFromSecret(string $secret, array $additional_values = []): JWK
{
$values = array_merge(
$additional_values,
[
'kty' => 'oct',
'k' => Base64Url::encode($secret),
]
);
return new JWK($values);
}
/**
* This method will try to load a X.509 certificate and convert it into a public key.
*/
public static function createFromCertificateFile(string $file, array $additional_values = []): JWK
{
$values = KeyConverter::loadKeyFromCertificateFile($file);
$values = array_merge($values, $additional_values);
return new JWK($values);
}
/**
* Extract a keyfrom a key set identified by the given index .
*
* @param int|string $index
*/
public static function createFromKeySet(JWKSet $jwkset, $index): JWK
{
return $jwkset->get($index);
}
/**
* This method will try to load a PKCS#12 file and convert it into a public key.
*
* @throws InvalidArgumentException if the certificate cannot be loaded
*/
public static function createFromPKCS12CertificateFile(string $file, ?string $secret = '', array $additional_values = []): JWK
{
try {
$content = file_get_contents($file);
if (!is_string($content)) {
throw new RuntimeException('Unable to read the file.');
}
openssl_pkcs12_read($content, $certs, $secret);
} catch (Throwable $throwable) {
throw new RuntimeException('Unable to load the certificates.', $throwable->getCode(), $throwable);
}
if (!is_array($certs) || !array_key_exists('pkey', $certs)) {
throw new RuntimeException('Unable to load the certificates.');
}
return self::createFromKey($certs['pkey'], null, $additional_values);
}
/**
* This method will try to convert a X.509 certificate into a public key.
*/
public static function createFromCertificate(string $certificate, array $additional_values = []): JWK
{
$values = KeyConverter::loadKeyFromCertificate($certificate);
$values = array_merge($values, $additional_values);
return new JWK($values);
}
/**
* This method will try to convert a X.509 certificate resource into a public key.
*
* @param resource $res
*/
public static function createFromX509Resource($res, array $additional_values = []): JWK
{
$values = KeyConverter::loadKeyFromX509Resource($res);
$values = array_merge($values, $additional_values);
return new JWK($values);
}
/**
* This method will try to load and convert a key file into a JWK object.
* If the key is encrypted, the password must be set.
*/
public static function createFromKeyFile(string $file, ?string $password = null, array $additional_values = []): JWK
{
$values = KeyConverter::loadFromKeyFile($file, $password);
$values = array_merge($values, $additional_values);
return new JWK($values);
}
/**
* This method will try to load and convert a key into a JWK object.
* If the key is encrypted, the password must be set.
*/
public static function createFromKey(string $key, ?string $password = null, array $additional_values = []): JWK
{
$values = KeyConverter::loadFromKey($key, $password);
$values = array_merge($values, $additional_values);
return new JWK($values);
}
/**
* This method will try to load and convert a X.509 certificate chain into a public key.
*
* Be careful! The certificate chain is loaded, but it is NOT VERIFIED by any mean!
* It is mandatory to verify the root CA or intermediate CA are trusted.
* If not done, it may lead to potential security issues.
*/
public static function createFromX5C(array $x5c, array $additional_values = []): JWK
{
$values = KeyConverter::loadFromX5C($x5c);
$values = array_merge($values, $additional_values);
return new JWK($values);
}
}

@ -0,0 +1,307 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\KeyConverter;
use function array_key_exists;
use Base64Url\Base64Url;
use function count;
use FG\ASN1\ASNObject;
use FG\ASN1\Exception\ParserException;
use FG\ASN1\ExplicitlyTaggedObject;
use FG\ASN1\Universal\BitString;
use FG\ASN1\Universal\Integer;
use FG\ASN1\Universal\ObjectIdentifier;
use FG\ASN1\Universal\OctetString;
use FG\ASN1\Universal\Sequence;
use InvalidArgumentException;
use function is_array;
use function is_string;
/**
* @internal
*/
class ECKey
{
/**
* @var array
*/
private $values = [];
private function __construct(array $data)
{
$this->loadJWK($data);
}
public static function createFromPEM(string $pem): self
{
$data = self::loadPEM($pem);
return new self($data);
}
/**
* @param ECKey $private
*
* @return ECKey
*/
public static function toPublic(self $private): self
{
$data = $private->toArray();
if (array_key_exists('d', $data)) {
unset($data['d']);
}
return new self($data);
}
/**
* @return array
*/
public function toArray()
{
return $this->values;
}
/**
* @throws InvalidArgumentException if the key cannot be loaded
* @throws ParserException if the key cannot be loaded
*/
private static function loadPEM(string $data): array
{
$data = base64_decode(preg_replace('#-.*-|\r|\n#', '', $data), true);
$asnObject = ASNObject::fromBinary($data);
if (!$asnObject instanceof Sequence) {
throw new InvalidArgumentException('Unable to load the key.');
}
$children = $asnObject->getChildren();
if (self::isPKCS8($children)) {
$children = self::loadPKCS8($children);
}
if (4 === count($children)) {
return self::loadPrivatePEM($children);
}
if (2 === count($children)) {
return self::loadPublicPEM($children);
}
throw new InvalidArgumentException('Unable to load the key.');
}
/**
* @param ASNObject[] $children
*
* @throws InvalidArgumentException if the key cannot be loaded
* @throws ParserException if the key cannot be loaded
*/
private static function loadPKCS8(array $children): array
{
$binary = hex2bin($children[2]->getContent());
$asnObject = ASNObject::fromBinary($binary);
if (!$asnObject instanceof Sequence) {
throw new InvalidArgumentException('Unable to load the key.');
}
return $asnObject->getChildren();
}
/**
* @throws InvalidArgumentException if the key cannot be loaded
*/
private static function loadPublicPEM(array $children): array
{
if (!$children[0] instanceof Sequence) {
throw new InvalidArgumentException('Unsupported key type.');
}
$sub = $children[0]->getChildren();
if (!$sub[0] instanceof ObjectIdentifier) {
throw new InvalidArgumentException('Unsupported key type.');
}
if ('1.2.840.10045.2.1' !== $sub[0]->getContent()) {
throw new InvalidArgumentException('Unsupported key type.');
}
if (!$sub[1] instanceof ObjectIdentifier) {
throw new InvalidArgumentException('Unsupported key type.');
}
if (!$children[1] instanceof BitString) {
throw new InvalidArgumentException('Unable to load the key.');
}
$bits = $children[1]->getContent();
$bits_length = mb_strlen($bits, '8bit');
if (0 !== mb_strpos($bits, '04', 0, '8bit')) {
throw new InvalidArgumentException('Unsupported key type');
}
$values = ['kty' => 'EC'];
$values['crv'] = self::getCurve($sub[1]->getContent());
$xBin = hex2bin(mb_substr($bits, 2, ($bits_length - 2) / 2, '8bit'));
$yBin = hex2bin(mb_substr($bits, (int) (($bits_length - 2) / 2 + 2), ($bits_length - 2) / 2, '8bit'));
if (!is_string($xBin) || !is_string($yBin)) {
throw new InvalidArgumentException('Unable to load the key.');
}
$values['x'] = Base64Url::encode($xBin);
$values['y'] = Base64Url::encode($yBin);
return $values;
}
/**
* @throws InvalidArgumentException if the OID is not supported
*/
private static function getCurve(string $oid): string
{
$curves = self::getSupportedCurves();
$curve = array_search($oid, $curves, true);
if (!is_string($curve)) {
throw new InvalidArgumentException('Unsupported OID.');
}
return $curve;
}
private static function getSupportedCurves(): array
{
return [
'P-256' => '1.2.840.10045.3.1.7',
'P-384' => '1.3.132.0.34',
'P-521' => '1.3.132.0.35',
];
}
/**
* @throws InvalidArgumentException if the key cannot be loaded
*/
private static function verifyVersion(ASNObject $children): void
{
if (!$children instanceof Integer || '1' !== $children->getContent()) {
throw new InvalidArgumentException('Unable to load the key.');
}
}
/**
* @throws InvalidArgumentException if the key cannot be loaded
*/
private static function getXAndY(ASNObject $children, string &$x, string &$y): void
{
if (!$children instanceof ExplicitlyTaggedObject || !is_array($children->getContent())) {
throw new InvalidArgumentException('Unable to load the key.');
}
if (!$children->getContent()[0] instanceof BitString) {
throw new InvalidArgumentException('Unable to load the key.');
}
$bits = $children->getContent()[0]->getContent();
$bits_length = mb_strlen($bits, '8bit');
if (0 !== mb_strpos($bits, '04', 0, '8bit')) {
throw new InvalidArgumentException('Unsupported key type');
}
$x = mb_substr($bits, 2, (int) (($bits_length - 2) / 2), '8bit');
$y = mb_substr($bits, (int) (($bits_length - 2) / 2 + 2), (int) (($bits_length - 2) / 2), '8bit');
}
/**
* @throws InvalidArgumentException if the key cannot be loaded
*/
private static function getD(ASNObject $children): string
{
if (!$children instanceof OctetString) {
throw new InvalidArgumentException('Unable to load the key.');
}
return $children->getContent();
}
/**
* @throws InvalidArgumentException if the key cannot be loaded
*/
private static function loadPrivatePEM(array $children): array
{
self::verifyVersion($children[0]);
$x = '';
$y = '';
$d = self::getD($children[1]);
self::getXAndY($children[3], $x, $y);
if (!$children[2] instanceof ExplicitlyTaggedObject || !is_array($children[2]->getContent())) {
throw new InvalidArgumentException('Unable to load the key.');
}
if (!$children[2]->getContent()[0] instanceof ObjectIdentifier) {
throw new InvalidArgumentException('Unable to load the key.');
}
$curve = $children[2]->getContent()[0]->getContent();
$dBin = hex2bin($d);
$xBin = hex2bin($x);
$yBin = hex2bin($y);
if (!is_string($dBin) || !is_string($xBin) || !is_string($yBin)) {
throw new InvalidArgumentException('Unable to load the key.');
}
$values = ['kty' => 'EC'];
$values['crv'] = self::getCurve($curve);
$values['d'] = Base64Url::encode($dBin);
$values['x'] = Base64Url::encode($xBin);
$values['y'] = Base64Url::encode($yBin);
return $values;
}
/**
* @param ASNObject[] $children
*/
private static function isPKCS8(array $children): bool
{
if (3 !== count($children)) {
return false;
}
$classes = [0 => Integer::class, 1 => Sequence::class, 2 => OctetString::class];
foreach ($classes as $k => $class) {
if (!$children[$k] instanceof $class) {
return false;
}
}
return true;
}
/**
* @throws InvalidArgumentException if the key is invalid
*/
private function loadJWK(array $jwk): void
{
$keys = [
'kty' => 'The key parameter "kty" is missing.',
'crv' => 'Curve parameter is missing',
'x' => 'Point parameters are missing.',
'y' => 'Point parameters are missing.',
];
foreach ($keys as $k => $v) {
if (!array_key_exists($k, $jwk)) {
throw new InvalidArgumentException($v);
}
}
if ('EC' !== $jwk['kty']) {
throw new InvalidArgumentException('JWK is not an Elliptic Curve key.');
}
$this->values = $jwk;
}
}

@ -0,0 +1,272 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\KeyConverter;
use function array_key_exists;
use Base64Url\Base64Url;
use function count;
use function extension_loaded;
use InvalidArgumentException;
use function is_array;
use function is_string;
use RuntimeException;
use Throwable;
/**
* @internal
*/
class KeyConverter
{
/**
* @throws InvalidArgumentException if the certificate file cannot be read
*/
public static function loadKeyFromCertificateFile(string $file): array
{
if (!file_exists($file)) {
throw new InvalidArgumentException(sprintf('File "%s" does not exist.', $file));
}
$content = file_get_contents($file);
if (!is_string($content)) {
throw new InvalidArgumentException(sprintf('File "%s" cannot be read.', $file));
}
return self::loadKeyFromCertificate($content);
}
/**
* @throws InvalidArgumentException if the OpenSSL extension is not available
* @throws InvalidArgumentException if the certificate is invalid or cannot be loaded
*/
public static function loadKeyFromCertificate(string $certificate): array
{
if (!extension_loaded('openssl')) {
throw new RuntimeException('Please install the OpenSSL extension');
}
try {
$res = openssl_x509_read($certificate);
if (false === $res) {
throw new InvalidArgumentException('Unable to load the certificate.');
}
} catch (Throwable $e) {
$certificate = self::convertDerToPem($certificate);
$res = openssl_x509_read($certificate);
}
if (false === $res) {
throw new InvalidArgumentException('Unable to load the certificate.');
}
return self::loadKeyFromX509Resource($res);
}
/**
* @param resource $res
*
* @throws InvalidArgumentException if the OpenSSL extension is not available
* @throws InvalidArgumentException if the certificate is invalid or cannot be loaded
*/
public static function loadKeyFromX509Resource($res): array
{
if (!extension_loaded('openssl')) {
throw new RuntimeException('Please install the OpenSSL extension');
}
$key = openssl_get_publickey($res);
if (false === $key) {
throw new InvalidArgumentException('Unable to load the certificate.');
}
$details = openssl_pkey_get_details($key);
if (!is_array($details)) {
throw new InvalidArgumentException('Unable to load the certificate');
}
if (isset($details['key'])) {
$values = self::loadKeyFromPEM($details['key']);
openssl_x509_export($res, $out);
$x5c = preg_replace('#-.*-#', '', $out);
$x5c = preg_replace('~\R~', PHP_EOL, $x5c);
if (!is_string($x5c)) {
throw new InvalidArgumentException('Unable to load the certificate');
}
$x5c = trim($x5c);
$x5tsha1 = openssl_x509_fingerprint($res, 'sha1', true);
$x5tsha256 = openssl_x509_fingerprint($res, 'sha256', true);
if (!is_string($x5tsha1) || !is_string($x5tsha256)) {
throw new InvalidArgumentException('Unable to compute the certificate fingerprint');
}
$values['x5c'] = [$x5c];
$values['x5t'] = Base64Url::encode($x5tsha1);
$values['x5t#256'] = Base64Url::encode($x5tsha256);
return $values;
}
throw new InvalidArgumentException('Unable to load the certificate');
}
public static function loadFromKeyFile(string $file, ?string $password = null): array
{
$content = file_get_contents($file);
if (!is_string($content)) {
throw new InvalidArgumentException('Unable to load the key from the file.');
}
return self::loadFromKey($content, $password);
}
public static function loadFromKey(string $key, ?string $password = null): array
{
try {
return self::loadKeyFromDER($key, $password);
} catch (Throwable $e) {
return self::loadKeyFromPEM($key, $password);
}
}
/**
* Be careful! The certificate chain is loaded, but it is NOT VERIFIED by any mean!
* It is mandatory to verify the root CA or intermediate CA are trusted.
* If not done, it may lead to potential security issues.
*
* @throws InvalidArgumentException if the certificate chain is empty
* @throws InvalidArgumentException if the OpenSSL extension is not available
*/
public static function loadFromX5C(array $x5c): array
{
if (0 === count($x5c)) {
throw new InvalidArgumentException('The certificate chain is empty');
}
foreach ($x5c as $id => $cert) {
$x5c[$id] = '-----BEGIN CERTIFICATE-----'.PHP_EOL.chunk_split($cert, 64, PHP_EOL).'-----END CERTIFICATE-----';
$x509 = openssl_x509_read($x5c[$id]);
if (false === $x509) {
throw new InvalidArgumentException('Unable to load the certificate chain');
}
$parsed = openssl_x509_parse($x509);
if (false === $parsed) {
throw new InvalidArgumentException('Unable to load the certificate chain');
}
}
return self::loadKeyFromCertificate(reset($x5c));
}
private static function loadKeyFromDER(string $der, ?string $password = null): array
{
$pem = self::convertDerToPem($der);
return self::loadKeyFromPEM($pem, $password);
}
/**
* @throws InvalidArgumentException if the OpenSSL extension is not available
* @throws InvalidArgumentException if the key cannot be loaded
*/
private static function loadKeyFromPEM(string $pem, ?string $password = null): array
{
if (1 === preg_match('#DEK-Info: (.+),(.+)#', $pem, $matches)) {
$pem = self::decodePem($pem, $matches, $password);
}
if (!extension_loaded('openssl')) {
throw new RuntimeException('Please install the OpenSSL extension');
}
self::sanitizePEM($pem);
$res = openssl_pkey_get_private($pem);
if (false === $res) {
$res = openssl_pkey_get_public($pem);
}
if (false === $res) {
throw new InvalidArgumentException('Unable to load the key.');
}
$details = openssl_pkey_get_details($res);
if (!is_array($details) || !array_key_exists('type', $details)) {
throw new InvalidArgumentException('Unable to get details of the key');
}
switch ($details['type']) {
case OPENSSL_KEYTYPE_EC:
$ec_key = ECKey::createFromPEM($pem);
return $ec_key->toArray();
case OPENSSL_KEYTYPE_RSA:
$rsa_key = RSAKey::createFromPEM($pem);
return $rsa_key->toArray();
default:
throw new InvalidArgumentException('Unsupported key type');
}
}
/**
* This method modifies the PEM to get 64 char lines and fix bug with old OpenSSL versions.
*/
private static function sanitizePEM(string &$pem): void
{
preg_match_all('#(-.*-)#', $pem, $matches, PREG_PATTERN_ORDER);
$ciphertext = preg_replace('#-.*-|\r|\n| #', '', $pem);
$pem = $matches[0][0].PHP_EOL;
$pem .= chunk_split($ciphertext, 64, PHP_EOL);
$pem .= $matches[0][1].PHP_EOL;
}
/**
* @param string[] $matches
*
* @throws InvalidArgumentException if the password to decrypt the key is not provided
* @throws InvalidArgumentException if the key cannot be loaded
*/
private static function decodePem(string $pem, array $matches, ?string $password = null): string
{
if (null === $password) {
throw new InvalidArgumentException('Password required for encrypted keys.');
}
$iv = pack('H*', trim($matches[2]));
$iv_sub = mb_substr($iv, 0, 8, '8bit');
$symkey = pack('H*', md5($password.$iv_sub));
$symkey .= pack('H*', md5($symkey.$password.$iv_sub));
$key = preg_replace('#^(?:Proc-Type|DEK-Info): .*#m', '', $pem);
$ciphertext = base64_decode(preg_replace('#-.*-|\r|\n#', '', $key), true);
if (!is_string($ciphertext)) {
throw new InvalidArgumentException('Unable to encode the data.');
}
$decoded = openssl_decrypt($ciphertext, mb_strtolower($matches[1]), $symkey, OPENSSL_RAW_DATA, $iv);
if (false === $decoded) {
throw new RuntimeException('Unable to decrypt the key');
}
$number = preg_match_all('#-{5}.*-{5}#', $pem, $result);
if (2 !== $number) {
throw new InvalidArgumentException('Unable to load the key');
}
$pem = $result[0][0].PHP_EOL;
$pem .= chunk_split(base64_encode($decoded), 64);
$pem .= $result[0][1].PHP_EOL;
return $pem;
}
private static function convertDerToPem(string $der_data): string
{
$pem = chunk_split(base64_encode($der_data), 64, PHP_EOL);
return '-----BEGIN CERTIFICATE-----'.PHP_EOL.$pem.'-----END CERTIFICATE-----'.PHP_EOL;
}
}

@ -0,0 +1,263 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement\KeyConverter;
use function array_key_exists;
use Base64Url\Base64Url;
use function extension_loaded;
use function in_array;
use InvalidArgumentException;
use function is_array;
use Jose\Component\Core\JWK;
use Jose\Component\Core\Util\BigInteger;
use RuntimeException;
/**
* @internal
*/
class RSAKey
{
/**
* @var array
*/
private $values = [];
/**
* RSAKey constructor.
*/
private function __construct(array $data)
{
$this->loadJWK($data);
}
/**
* @return RSAKey
*/
public static function createFromKeyDetails(array $details): self
{
$values = ['kty' => 'RSA'];
$keys = [
'n' => 'n',
'e' => 'e',
'd' => 'd',
'p' => 'p',
'q' => 'q',
'dp' => 'dmp1',
'dq' => 'dmq1',
'qi' => 'iqmp',
];
foreach ($details as $key => $value) {
if (in_array($key, $keys, true)) {
$value = Base64Url::encode($value);
$values[array_search($key, $keys, true)] = $value;
}
}
return new self($values);
}
/**
* @throws RuntimeException if the extension OpenSSL is not available
* @throws InvalidArgumentException if the key cannot be loaded
*
* @return RSAKey
*/
public static function createFromPEM(string $pem): self
{
if (!extension_loaded('openssl')) {
throw new RuntimeException('Please install the OpenSSL extension');
}
$res = openssl_pkey_get_private($pem);
if (false === $res) {
$res = openssl_pkey_get_public($pem);
}
if (false === $res) {
throw new InvalidArgumentException('Unable to load the key.');
}
$details = openssl_pkey_get_details($res);
if (!is_array($details) || !isset($details['rsa'])) {
throw new InvalidArgumentException('Unable to load the key.');
}
return self::createFromKeyDetails($details['rsa']);
}
/**
* @return RSAKey
*/
public static function createFromJWK(JWK $jwk): self
{
return new self($jwk->all());
}
public function isPublic(): bool
{
return !array_key_exists('d', $this->values);
}
/**
* @param RSAKey $private
*
* @return RSAKey
*/
public static function toPublic(self $private): self
{
$data = $private->toArray();
$keys = ['p', 'd', 'q', 'dp', 'dq', 'qi'];
foreach ($keys as $key) {
if (array_key_exists($key, $data)) {
unset($data[$key]);
}
}
return new self($data);
}
public function toArray(): array
{
return $this->values;
}
public function toJwk(): JWK
{
return new JWK($this->values);
}
/**
* This method will try to add Chinese Remainder Theorem (CRT) parameters.
* With those primes, the decryption process is really fast.
*/
public function optimize(): void
{
if (array_key_exists('d', $this->values)) {
$this->populateCRT();
}
}
/**
* @throws InvalidArgumentException if the key is invalid or not an RSA key
*/
private function loadJWK(array $jwk): void
{
if (!array_key_exists('kty', $jwk)) {
throw new InvalidArgumentException('The key parameter "kty" is missing.');
}
if ('RSA' !== $jwk['kty']) {
throw new InvalidArgumentException('The JWK is not a RSA key.');
}
$this->values = $jwk;
}
/**
* This method adds Chinese Remainder Theorem (CRT) parameters if primes 'p' and 'q' are available.
* If 'p' and 'q' are missing, they are computed and added to the key data.
*/
private function populateCRT(): void
{
if (!array_key_exists('p', $this->values) && !array_key_exists('q', $this->values)) {
$d = BigInteger::createFromBinaryString(Base64Url::decode($this->values['d']));
$e = BigInteger::createFromBinaryString(Base64Url::decode($this->values['e']));
$n = BigInteger::createFromBinaryString(Base64Url::decode($this->values['n']));
[$p, $q] = $this->findPrimeFactors($d, $e, $n);
$this->values['p'] = Base64Url::encode($p->toBytes());
$this->values['q'] = Base64Url::encode($q->toBytes());
}
if (array_key_exists('dp', $this->values) && array_key_exists('dq', $this->values) && array_key_exists('qi', $this->values)) {
return;
}
$one = BigInteger::createFromDecimal(1);
$d = BigInteger::createFromBinaryString(Base64Url::decode($this->values['d']));
$p = BigInteger::createFromBinaryString(Base64Url::decode($this->values['p']));
$q = BigInteger::createFromBinaryString(Base64Url::decode($this->values['q']));
$this->values['dp'] = Base64Url::encode($d->mod($p->subtract($one))->toBytes());
$this->values['dq'] = Base64Url::encode($d->mod($q->subtract($one))->toBytes());
$this->values['qi'] = Base64Url::encode($q->modInverse($p)->toBytes());
}
/**
* @throws RuntimeException if the prime factors cannot be found
*
* @return BigInteger[]
*/
private function findPrimeFactors(BigInteger $d, BigInteger $e, BigInteger $n): array
{
$zero = BigInteger::createFromDecimal(0);
$one = BigInteger::createFromDecimal(1);
$two = BigInteger::createFromDecimal(2);
$k = $d->multiply($e)->subtract($one);
if ($k->isEven()) {
$r = $k;
$t = $zero;
do {
$r = $r->divide($two);
$t = $t->add($one);
} while ($r->isEven());
$found = false;
$y = null;
for ($i = 1; $i <= 100; ++$i) {
$g = BigInteger::random($n->subtract($one));
$y = $g->modPow($r, $n);
if ($y->equals($one) || $y->equals($n->subtract($one))) {
continue;
}
for ($j = $one; $j->lowerThan($t->subtract($one)); $j = $j->add($one)) {
$x = $y->modPow($two, $n);
if ($x->equals($one)) {
$found = true;
break;
}
if ($x->equals($n->subtract($one))) {
continue;
}
$y = $x;
}
$x = $y->modPow($two, $n);
if ($x->equals($one)) {
$found = true;
break;
}
}
if (null === $y) {
throw new InvalidArgumentException('Unable to find prime factors.');
}
if (true === $found) {
$p = $y->subtract($one)->gcd($n);
$q = $n->divide($p);
return [$p, $q];
}
}
throw new InvalidArgumentException('Unable to find prime factors.');
}
}

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014-2019 Spomky-Labs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -0,0 +1,15 @@
PHP JWT Key Management Component
================================
This repository is a sub repository of [the JWT Framework](https://github.com/web-token/jwt-framework) project and is READ ONLY.
**Please do not submit any Pull Request here.**
You should go to [the main repository](https://github.com/web-token/jwt-framework) instead.
# Documentation
The official documentation is available as https://web-token.spomky-labs.com/
# Licence
This software is release under [MIT licence](LICENSE).

@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestFactoryInterface;
use RuntimeException;
abstract class UrlKeySetFactory
{
/**
* @var ClientInterface
*/
private $client;
/**
* @var RequestFactoryInterface
*/
private $requestFactory;
/**
* UrlKeySetFactory constructor.
*/
public function __construct(ClientInterface $client, RequestFactoryInterface $requestFactory)
{
$this->client = $client;
$this->requestFactory = $requestFactory;
}
/**
* @throws RuntimeException if the response content is invalid
*/
protected function getContent(string $url, array $header = []): string
{
$request = $this->requestFactory->createRequest('GET', $url);
foreach ($header as $k => $v) {
$request = $request->withHeader($k, $v);
}
$response = $this->client->sendRequest($request);
if ($response->getStatusCode() >= 400) {
throw new RuntimeException('Unable to get the key set.', $response->getStatusCode());
}
return $response->getBody()->getContents();
}
}

@ -0,0 +1,56 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Jose\Component\KeyManagement;
use function is_array;
use function is_string;
use Jose\Component\Core\JWK;
use Jose\Component\Core\JWKSet;
use Jose\Component\Core\Util\JsonConverter;
use Jose\Component\KeyManagement\KeyConverter\KeyConverter;
use RuntimeException;
class X5UFactory extends UrlKeySetFactory
{
/**
* This method will try to fetch the url a retrieve the key set.
* Throws an exception in case of failure.
*
* @throws RuntimeException if the response content is invalid
*/
public function loadFromUrl(string $url, array $header = []): JWKSet
{
$content = $this->getContent($url, $header);
$data = JsonConverter::decode($content);
if (!is_array($data)) {
throw new RuntimeException('Invalid content.');
}
$keys = [];
foreach ($data as $kid => $cert) {
if (false === mb_strpos($cert, '-----BEGIN CERTIFICATE-----')) {
$cert = '-----BEGIN CERTIFICATE-----'.PHP_EOL.$cert.PHP_EOL.'-----END CERTIFICATE-----';
}
$jwk = KeyConverter::loadKeyFromCertificate($cert);
if (is_string($kid)) {
$jwk['kid'] = $kid;
$keys[$kid] = new JWK($jwk);
} else {
$keys[] = new JWK($jwk);
}
}
return new JWKSet($keys);
}
}

@ -0,0 +1,34 @@
{
"name": "web-token/jwt-key-mgmt",
"description": "Key Management component of the JWT Framework.",
"type": "library",
"license": "MIT",
"keywords": ["JWS", "JWT", "JWE", "JWA", "JWK", "JWKSet", "Jot", "Jose", "RFC7515", "RFC7516", "RFC7517", "RFC7518", "RFC7519", "RFC7520", "Bundle", "Symfony"],
"homepage": "https://github.com/web-token",
"authors": [
{
"name": "Florent Morselli",
"homepage": "https://github.com/Spomky"
},{
"name": "All contributors",
"homepage": "https://github.com/web-token/jwt-key-mgmt/contributors"
}
],
"autoload": {
"psr-4": {
"Jose\\Component\\KeyManagement\\": ""
}
},
"require": {
"ext-openssl": "*",
"psr/http-factory": "^1.0",
"psr/http-client": "^1.0",
"web-token/jwt-core": "^2.0"
},
"suggest": {
"ext-sodium": "Sodium is required for OKP key creation, EdDSA signature algorithm and ECDH-ES key encryption with OKP keys",
"web-token/jwt-util-ecc": "To use EC key analyzers.",
"php-http/message-factory": "To enable JKU/X5U support.",
"php-http/httplug": "To enable JKU/X5U support."
}
}