mirror of
https://github.com/phpseclib/phpseclib.git
synced 2024-12-26 11:37:33 +00:00
Merge branch 'oid-revamp-2.0'
This commit is contained in:
commit
b09bc1883e
@ -458,24 +458,7 @@ abstract class ASN1
|
||||
}
|
||||
break;
|
||||
case self::TYPE_OBJECT_IDENTIFIER:
|
||||
$temp = ord($content[$content_pos++]);
|
||||
$current['content'] = sprintf('%d.%d', floor($temp / 40), $temp % 40);
|
||||
$valuen = 0;
|
||||
// process septets
|
||||
$content_len = strlen($content);
|
||||
while ($content_pos < $content_len) {
|
||||
$temp = ord($content[$content_pos++]);
|
||||
$valuen <<= 7;
|
||||
$valuen |= $temp & 0x7F;
|
||||
if (~$temp & 0x80) {
|
||||
$current['content'].= ".$valuen";
|
||||
$valuen = 0;
|
||||
}
|
||||
}
|
||||
// the eighth bit of the last byte should not be 1
|
||||
//if ($temp >> 7) {
|
||||
// return false;
|
||||
//}
|
||||
$current['content'] = self::decodeOID(substr($content, $content_pos));
|
||||
break;
|
||||
/* Each character string type shall be encoded as if it had been declared:
|
||||
[UNIVERSAL x] IMPLICIT OCTET STRING
|
||||
@ -1068,30 +1051,7 @@ abstract class ASN1
|
||||
$value = $source;
|
||||
break;
|
||||
case self::TYPE_OBJECT_IDENTIFIER:
|
||||
if (!preg_match('#(?:\d+\.)+#', $source)) {
|
||||
$oid = isset(self::$reverseOIDs[$source]) ? self::$reverseOIDs[$source] : false;
|
||||
} else {
|
||||
$oid = $source;
|
||||
}
|
||||
if ($oid === false) {
|
||||
throw new \RuntimeException('Invalid OID');
|
||||
}
|
||||
$value = '';
|
||||
$parts = explode('.', $oid);
|
||||
$value = chr(40 * $parts[0] + $parts[1]);
|
||||
for ($i = 2; $i < count($parts); $i++) {
|
||||
$temp = '';
|
||||
if (!$parts[$i]) {
|
||||
$temp = "\0";
|
||||
} else {
|
||||
while ($parts[$i]) {
|
||||
$temp = chr(0x80 | ($parts[$i] & 0x7F)) . $temp;
|
||||
$parts[$i] >>= 7;
|
||||
}
|
||||
$temp[strlen($temp) - 1] = $temp[strlen($temp) - 1] & chr(0x7F);
|
||||
}
|
||||
$value.= $temp;
|
||||
}
|
||||
$value = self::encodeOID($source);
|
||||
break;
|
||||
case self::TYPE_ANY:
|
||||
$loc = self::$location;
|
||||
@ -1168,6 +1128,112 @@ abstract class ASN1
|
||||
return chr($tag) . self::encodeLength(strlen($value)) . $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* BER-decode the OID
|
||||
*
|
||||
* Called by _decode_ber()
|
||||
*
|
||||
* @access public
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
public static function decodeOID($content)
|
||||
{
|
||||
static $eighty;
|
||||
if (!$eighty) {
|
||||
$eighty = new BigInteger(80);
|
||||
}
|
||||
|
||||
$oid = array();
|
||||
$pos = 0;
|
||||
$len = strlen($content);
|
||||
$n = new BigInteger();
|
||||
while ($pos < $len) {
|
||||
$temp = ord($content[$pos++]);
|
||||
$n = $n->bitwise_leftShift(7);
|
||||
$n = $n->bitwise_or(new BigInteger($temp & 0x7F));
|
||||
if (~$temp & 0x80) {
|
||||
$oid[] = $n;
|
||||
$n = new BigInteger();
|
||||
}
|
||||
}
|
||||
$part1 = array_shift($oid);
|
||||
$first = floor(ord($content[0]) / 40);
|
||||
/*
|
||||
"This packing of the first two object identifier components recognizes that only three values are allocated from the root
|
||||
node, and at most 39 subsequent values from nodes reached by X = 0 and X = 1."
|
||||
|
||||
-- https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=22
|
||||
*/
|
||||
if ($first <= 2) { // ie. 0 <= ord($content[0]) < 120 (0x78)
|
||||
array_unshift($oid, ord($content[0]) % 40);
|
||||
array_unshift($oid, $first);
|
||||
} else {
|
||||
array_unshift($oid, $part1->subtract($eighty));
|
||||
array_unshift($oid, 2);
|
||||
}
|
||||
|
||||
return implode('.', $oid);
|
||||
}
|
||||
|
||||
/**
|
||||
* DER-encode the OID
|
||||
*
|
||||
* Called by _encode_der()
|
||||
*
|
||||
* @access public
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
public static function encodeOID($source)
|
||||
{
|
||||
static $mask, $zero, $forty;
|
||||
if (!$mask) {
|
||||
$mask = new BigInteger(0x7F);
|
||||
$zero = new BigInteger();
|
||||
$forty = new BigInteger(40);
|
||||
}
|
||||
|
||||
if (!preg_match('#(?:\d+\.)+#', $source)) {
|
||||
$oid = isset(self::$reverseOIDs[$source]) ? self::$reverseOIDs[$source] : false;
|
||||
} else {
|
||||
$oid = $source;
|
||||
}
|
||||
if ($oid === false) {
|
||||
throw new \RuntimeException('Invalid OID');
|
||||
}
|
||||
|
||||
$parts = explode('.', $oid);
|
||||
$part1 = array_shift($parts);
|
||||
$part2 = array_shift($parts);
|
||||
|
||||
$first = new BigInteger($part1);
|
||||
$first = $first->multiply($forty);
|
||||
$first = $first->add(new BigInteger($part2));
|
||||
|
||||
array_unshift($parts, $first->toString());
|
||||
|
||||
$value = '';
|
||||
foreach ($parts as $part) {
|
||||
if (!$part) {
|
||||
$temp = "\0";
|
||||
} else {
|
||||
$temp = '';
|
||||
$part = new BigInteger($part);
|
||||
while (!$part->equals($zero)) {
|
||||
$submask = $part->bitwise_and($mask);
|
||||
$submask->setPrecision(8);
|
||||
$temp = (chr(0x80) | $submask->toBytes()) . $temp;
|
||||
$part = $part->bitwise_rightShift(7);
|
||||
}
|
||||
$temp[strlen($temp) - 1] = $temp[strlen($temp) - 1] & chr(0x7F);
|
||||
}
|
||||
$value.= $temp;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* BER-decode the time
|
||||
*
|
||||
|
@ -344,4 +344,24 @@ class Unit_File_ASN1Test extends PhpseclibTestCase
|
||||
$data = 'a' . base64_decode('MD6gJQYKKwYBBAGCNxQCA6AXDBVvZmZpY2VAY2VydGRpZ2l0YWwucm+BFW9mZmljZUBjZXJ0ZGlnaXRhbC5ybw==');
|
||||
ASN1::decodeBER($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group github1367
|
||||
*/
|
||||
public function testOIDs()
|
||||
{
|
||||
// from the example in 8.19.5 in the following:
|
||||
// https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=22
|
||||
$orig = pack('H*', '813403');
|
||||
$new = ASN1::decodeOID($orig);
|
||||
$this->assertSame('2.100.3', $new);
|
||||
$this->assertSame($orig, ASN1::encodeOID($new));
|
||||
|
||||
// UUID OID from the following:
|
||||
// https://healthcaresecprivacy.blogspot.com/2011/02/creating-and-using-unique-id-uuid-oid.html
|
||||
$orig = '2.25.329800735698586629295641978511506172918';
|
||||
$new = ASN1::encodeOID($orig);
|
||||
$this->assertSame(pack('H*', '6983f09da7ebcfdee0c7a1a7b2c0948cc8f9d776'), $new);
|
||||
$this->assertSame($orig, ASN1::decodeOID($new));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user