mirror of
https://github.com/phpseclib/phpseclib.git
synced 2024-12-25 11:20:03 +00:00
ASN1: revamp how OIDs are handled
This commit is contained in:
parent
756b247446
commit
e793461543
@ -515,24 +515,7 @@ class File_ASN1
|
||||
}
|
||||
break;
|
||||
case FILE_ASN1_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'] = $this->_decodeOID(substr($content, $content_pos));
|
||||
break;
|
||||
/* Each character string type shall be encoded as if it had been declared:
|
||||
[UNIVERSAL x] IMPLICIT OCTET STRING
|
||||
@ -1111,27 +1094,7 @@ class File_ASN1
|
||||
$value = base64_decode($source);
|
||||
break;
|
||||
case FILE_ASN1_TYPE_OBJECT_IDENTIFIER:
|
||||
$oid = preg_match('#(?:\d+\.)+#', $source) ? $source : array_search($source, $this->oids);
|
||||
if ($oid === false) {
|
||||
user_error('Invalid OID');
|
||||
return false;
|
||||
}
|
||||
$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 = $this->_encodeOID($source);
|
||||
break;
|
||||
case FILE_ASN1_TYPE_ANY:
|
||||
$loc = $this->location;
|
||||
@ -1230,6 +1193,108 @@ class File_ASN1
|
||||
return pack('Ca*', 0x80 | strlen($temp), $temp);
|
||||
}
|
||||
|
||||
/**
|
||||
* BER-decode the OID
|
||||
*
|
||||
* Called by _decode_ber()
|
||||
*
|
||||
* @access private
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
function _decodeOID($content)
|
||||
{
|
||||
static $eighty;
|
||||
if (!$eighty) {
|
||||
$eighty = new Math_BigInteger(80);
|
||||
}
|
||||
|
||||
$oid = array();
|
||||
$pos = 0;
|
||||
$len = strlen($content);
|
||||
$n = new Math_BigInteger();
|
||||
while ($pos < $len) {
|
||||
$temp = ord($content[$pos++]);
|
||||
$n = $n->bitwise_leftShift(7);
|
||||
$n = $n->bitwise_or(new Math_BigInteger($temp & 0x7F));
|
||||
if (~$temp & 0x80) {
|
||||
$oid[] = $n;
|
||||
$n = new Math_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 private
|
||||
* @param string $content
|
||||
* @return string
|
||||
*/
|
||||
function _encodeOID($source)
|
||||
{
|
||||
static $mask, $zero, $forty;
|
||||
if (!$mask) {
|
||||
$mask = new Math_BigInteger(0x7F);
|
||||
$zero = new Math_BigInteger();
|
||||
$forty = new Math_BigInteger(40);
|
||||
}
|
||||
|
||||
$oid = preg_match('#(?:\d+\.)+#', $source) ? $source : array_search($source, $this->oids);
|
||||
if ($oid === false) {
|
||||
user_error('Invalid OID');
|
||||
return false;
|
||||
}
|
||||
$parts = explode('.', $oid);
|
||||
$part1 = array_shift($parts);
|
||||
$part2 = array_shift($parts);
|
||||
|
||||
$first = new Math_BigInteger($part1);
|
||||
$first = $first->multiply($forty);
|
||||
$first = $first->add(new Math_BigInteger($part2));
|
||||
|
||||
array_unshift($parts, $first->toString());
|
||||
|
||||
$value = '';
|
||||
foreach ($parts as $part) {
|
||||
if (!$part) {
|
||||
$temp = "\0";
|
||||
} else {
|
||||
$temp = '';
|
||||
$part = new Math_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 (using UNIX time)
|
||||
*
|
||||
|
@ -341,4 +341,26 @@ class Unit_File_ASN1Test extends PhpseclibTestCase
|
||||
$asn1 = new File_ASN1();
|
||||
$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');
|
||||
$asn1 = new File_ASN1();
|
||||
$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';
|
||||
$asn1 = new File_ASN1();
|
||||
$new = $asn1->_encodeOID($orig);
|
||||
$this->assertSame(pack('H*', '6983f09da7ebcfdee0c7a1a7b2c0948cc8f9d776'), $new);
|
||||
$this->assertSame($orig, $asn1->_decodeOID($new));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user