Add getRegisteredExtension()

This commit is contained in:
Bastien Miclo 2021-01-14 16:15:55 +01:00
parent 3d35690a0a
commit e69049be5e
No known key found for this signature in database
GPG Key ID: 06FB4BC7489F07BC
3 changed files with 92 additions and 72 deletions

View File

@ -1,64 +0,0 @@
<?php
/**
* Pure-PHP X.509 Parser
*
* PHP version 5
*
* Encode and decode X.509 certificates.
*
* The extensions are from {@link http://tools.ietf.org/html/rfc5280 RFC5280} and
* {@link http://web.archive.org/web/19961027104704/http://www3.netscape.com/eng/security/cert-exts.html Netscape Certificate Extensions}.
*
* Note that loading an X.509 certificate and resaving it may invalidate the signature. The reason being that the signature is based on a
* portion of the certificate that contains optional parameters with default values. ie. if the parameter isn't there the default value is
* used. Problem is, if the parameter is there and it just so happens to have the default value there are two ways that that parameter can
* be encoded. It can be encoded explicitly or left out all together. This would effect the signature value and thus may invalidate the
* the certificate all together unless the certificate is re-signed.
*
* @category File
* @package X509
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2012 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
namespace phpseclib3\File\Traits;
trait Extensions
{
/**
* @var array
* @access private
*/
private static $extensions = [];
/**
* @var array
* @access private
*/
private $extensionValues = [];
/**
* Register the mapping for a custom/unsupported extension.
*
* @param string $id
* @param array $mapping
*/
public static function registerExtension($id, array $mapping)
{
self::$extensions[$id] = $mapping;
}
/**
* Register the mapping for a custom/unsupported extension.
*
* @param string $id
* @param mixed $value
*/
public function setExtensionValue($id, $value)
{
$this->extensionValues[$id] = $value;
}
}

View File

@ -54,8 +54,6 @@ use phpseclib3\Math\BigInteger;
*/ */
class X509 class X509
{ {
use Extensions;
/** /**
* Flag to only accept signatures signed by certificate authorities * Flag to only accept signatures signed by certificate authorities
* *
@ -270,6 +268,12 @@ class X509
*/ */
private $challenge; private $challenge;
/**
* @var array
* @access private
*/
private $extensionValues = [];
/** /**
* OIDs loaded * OIDs loaded
* *
@ -294,6 +298,12 @@ class X509
*/ */
private static $disable_url_fetch = false; private static $disable_url_fetch = false;
/**
* @var array
* @access private
*/
private static $extensions = [];
/** /**
* Default Constructor. * Default Constructor.
* *
@ -4014,4 +4024,44 @@ class X509
return false; return false;
} }
/**
* Register the mapping for a custom/unsupported extension.
*
* @param string $id
* @param array $mapping
*/
public static function registerExtension($id, array $mapping)
{
if (isset(self::$extensions[$id]) && self::$extensions[$id] !== $mapping) {
throw new \RuntimeException(
'Extension ' . $id . ' has already been defined with a different mapping.'
);
}
self::$extensions[$id] = $mapping;
}
/**
* Register the mapping for a custom/unsupported extension.
*
* @param string $id
*
* @return array|null
*/
public static function getRegisteredExtension($id)
{
return isset(self::$extensions[$id]) ? self::$extensions[$id] : null;
}
/**
* Register the mapping for a custom/unsupported extension.
*
* @param string $id
* @param mixed $value
*/
public function setExtensionValue($id, $value)
{
$this->extensionValues[$id] = $value;
}
} }

View File

@ -21,12 +21,7 @@ class Unit_File_X509_X509ExtensionTest extends PhpseclibTestCase
]; ];
$customExtensionName = 'cust'; $customExtensionName = 'cust';
$customExtensionNumber = '2.16.840.1.101.3.4.2.99'; $customExtensionNumber = '2.16.840.1.101.3.4.2.99';
$customExtensionMapping = [
ASN1::loadOIDs([
$customExtensionName => $customExtensionNumber,
]);
X509::registerExtension($customExtensionName, [
'type' => ASN1::TYPE_SEQUENCE, 'type' => ASN1::TYPE_SEQUENCE,
'children' => [ 'children' => [
'toggle' => ['type' => ASN1::TYPE_BOOLEAN], 'toggle' => ['type' => ASN1::TYPE_BOOLEAN],
@ -39,8 +34,14 @@ class Unit_File_X509_X509ExtensionTest extends PhpseclibTestCase
'children' => ['type' => ASN1::TYPE_OCTET_STRING], 'children' => ['type' => ASN1::TYPE_OCTET_STRING],
], ],
], ],
];
ASN1::loadOIDs([
$customExtensionName => $customExtensionNumber,
]); ]);
X509::registerExtension($customExtensionName, $customExtensionMapping);
$privateKey = RSA::createKey(); $privateKey = RSA::createKey();
$publicKey = $privateKey->getPublicKey(); $publicKey = $privateKey->getPublicKey();
@ -79,5 +80,38 @@ class Unit_File_X509_X509ExtensionTest extends PhpseclibTestCase
$this->assertSame('3', (string) $customExtensionDecodedData['num']); $this->assertSame('3', (string) $customExtensionDecodedData['num']);
$this->assertSame('Johnny', $customExtensionDecodedData['name']); $this->assertSame('Johnny', $customExtensionDecodedData['name']);
$this->assertSame(['foo', 'bar'], $customExtensionDecodedData['list']); $this->assertSame(['foo', 'bar'], $customExtensionDecodedData['list']);
$this->assertSame($customExtensionMapping, X509::getRegisteredExtension($customExtensionName));
}
public function testCustomExtensionRegisterTwiceTheSame()
{
$customExtensionMapping = [
'type' => ASN1::TYPE_SEQUENCE,
'children' => [
'toggle' => ['type' => ASN1::TYPE_BOOLEAN],
'num' => ['type' => ASN1::TYPE_INTEGER],
'name' => ['type' => ASN1::TYPE_OCTET_STRING],
'list' => [
'type' => ASN1::TYPE_SEQUENCE,
'min' => 0,
'max' => -1,
'children' => ['type' => ASN1::TYPE_OCTET_STRING],
],
],
];
X509::registerExtension('foo', $customExtensionMapping);
X509::registerExtension('foo', $customExtensionMapping);
$this->assertSame($customExtensionMapping, X509::getRegisteredExtension('foo'));
}
public function testCustomExtensionRegisterConflict()
{
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Extension bar has already been defined with a different mapping.');
X509::registerExtension('bar', ['type' => ASN1::TYPE_OCTET_STRING]);
X509::registerExtension('bar', ['type' => ASN1::TYPE_ANY]);
} }
} }