155        self::TYPE_BOOLEAN              => 
true,
 
  156        self::TYPE_INTEGER              => 
true,
 
  157        self::TYPE_BIT_STRING           => 
'bitString',
 
  158        self::TYPE_OCTET_STRING         => 
'octetString',
 
  159        self::TYPE_NULL                 => 
'null',
 
  160        self::TYPE_OBJECT_IDENTIFIER    => 
'objectIdentifier',
 
  161        self::TYPE_REAL                 => 
true,
 
  162        self::TYPE_ENUMERATED           => 
'enumerated',
 
  163        self::TYPE_UTF8_STRING          => 
'utf8String',
 
  164        self::TYPE_NUMERIC_STRING       => 
'numericString',
 
  165        self::TYPE_PRINTABLE_STRING     => 
'printableString',
 
  166        self::TYPE_TELETEX_STRING       => 
'teletexString',
 
  167        self::TYPE_VIDEOTEX_STRING      => 
'videotexString',
 
  168        self::TYPE_IA5_STRING           => 
'ia5String',
 
  169        self::TYPE_UTC_TIME             => 
'utcTime',
 
  170        self::TYPE_GENERALIZED_TIME     => 
'generalTime',
 
  171        self::TYPE_GRAPHIC_STRING       => 
'graphicString',
 
  172        self::TYPE_VISIBLE_STRING       => 
'visibleString',
 
  173        self::TYPE_GENERAL_STRING       => 
'generalString',
 
  174        self::TYPE_UNIVERSAL_STRING     => 
'universalString',
 
  176        self::TYPE_BMP_STRING           => 
'bmpString' 
  189        self::TYPE_UTF8_STRING      => 0,
 
  190        self::TYPE_BMP_STRING       => 2,
 
  191        self::TYPE_UNIVERSAL_STRING => 4,
 
  192        self::TYPE_PRINTABLE_STRING => 1,
 
  193        self::TYPE_TELETEX_STRING   => 1,
 
  194        self::TYPE_IA5_STRING       => 1,
 
  195        self::TYPE_VISIBLE_STRING   => 1,
 
  237        $constructed = (
$type >> 5) & 1;
 
  254        if ($length == 0x80) { 
 
  258        } elseif ($length & 0x80) { 
 
  264            $current+= array(
'headerlength' => $length + 2);
 
  266            extract(unpack(
'Nlength', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4)));
 
  268            $current+= array(
'headerlength' => 2);
 
  288        $class = (
$type >> 6) & 3;
 
  297                        'content'  => $content,
 
  302                $newcontent = array();
 
  303                $remainingLength = $length;
 
  304                while ($remainingLength > 0) {
 
  306                    $length = $temp[
'length'];
 
  308                    if (substr($content, $length, 2) == 
"\0\0") {
 
  311                        $newcontent[] = $temp;
 
  315                    $remainingLength-= $length;
 
  316                    $newcontent[] = $temp;
 
  324                    'content'  => $newcontent,
 
  341                $current[
'content'] = (bool) ord($content[0]);
 
  357                    $length-= strlen($content);
 
  358                    $last = count($temp) - 1;
 
  359                    for (
$i = 0; 
$i < $last; 
$i++) {
 
  364                        $current[
'content'].= substr($temp[
$i][
'content'], 1);
 
  370                    $current[
'content'] = $temp[$last][
'content'][0] . 
$current[
'content'] . substr($temp[
$i][
'content'], 1);
 
  379                    while (substr($content, 0, 2) != 
"\0\0") {
 
  386                        $current[
'content'].= $temp[
'content'];
 
  387                        $length+= $temp[
'length'];
 
  389                    if (substr($content, 0, 2) == 
"\0\0") {
 
  404                while (strlen($content)) {
 
  407                    if (!isset(
$current[
'headerlength']) && substr($content, 0, 2) == 
"\0\0") {
 
  408                        $length = $offset + 2; 
 
  414                    $offset+= $temp[
'length'];
 
  419                $current[
'content'] = sprintf(
'%d.%d', floor($temp / 40), $temp % 40);
 
  422                while (strlen($content)) {
 
  425                    $valuen |= $temp & 0x7F;
 
  491    function asn1map($decoded, $mapping, $special = array())
 
  493        if (isset($mapping[
'explicit']) && is_array($decoded[
'content'])) {
 
  494            $decoded = $decoded[
'content'][0];
 
  499                $intype = $decoded[
'type'];
 
  500                if (isset($decoded[
'constant']) || !isset($this->ANYmap[$intype]) || ($this->encoded[$decoded[
'start']] & 0x20)) {
 
  501                    return new Element(substr($this->encoded, $decoded[
'start'], $decoded[
'length']));
 
  503                $inmap = $this->ANYmap[$intype];
 
  504                if (is_string($inmap)) {
 
  505                    return array($inmap => $this->
asn1map($decoded, array(
'type' => $intype) + $mapping, $special));
 
  509                foreach ($mapping[
'children'] as 
$key => $option) {
 
  511                        case isset($option[
'constant']) && $option[
'constant'] == $decoded[
'constant']:
 
  512                        case !isset($option[
'constant']) && $option[
'type'] == $decoded[
'type']:
 
  513                            $value = $this->
asn1map($decoded, $option, $special);
 
  516                            $v = $this->
asn1map($decoded, $option, $special);
 
  522                        if (isset($special[
$key])) {
 
  523                            $value = call_user_func($special[
$key], $value);
 
  525                        return array(
$key => $value);
 
  529            case isset($mapping[
'implicit']):
 
  530            case isset($mapping[
'explicit']):
 
  531            case $decoded[
'type'] == $mapping[
'type']:
 
  537                    case $decoded[
'type'] < 18: 
 
  538                    case $decoded[
'type'] > 30: 
 
  539                    case $mapping[
'type'] < 18:
 
  540                    case $mapping[
'type'] > 30:
 
  545        if (isset($mapping[
'implicit'])) {
 
  546            $decoded[
'type'] = $mapping[
'type'];
 
  549        switch ($decoded[
'type']) {
 
  554                if (isset($mapping[
'min']) && isset($mapping[
'max'])) {
 
  555                    $child = $mapping[
'children'];
 
  556                    foreach ($decoded[
'content'] as $content) {
 
  557                        if ((
$map[] = $this->
asn1map($content, $child, $special)) === 
null) {
 
  565                $n = count($decoded[
'content']);
 
  568                foreach ($mapping[
'children'] as 
$key => $child) {
 
  571                        $temp = $decoded[
'content'][
$i];
 
  573                        if ($child[
'type'] != self::TYPE_CHOICE) {
 
  577                            if (isset($temp[
'constant'])) {
 
  580                            if (isset($child[
'class'])) {
 
  581                                $childClass = $child[
'class'];
 
  582                                $constant = $child[
'cast'];
 
  583                            } elseif (isset($child[
'constant'])) {
 
  585                                $constant = $child[
'constant'];
 
  588                            if (isset($constant) && isset($temp[
'constant'])) {
 
  590                                $maymatch = $constant == $temp[
'constant'] && $childClass == $tempClass;
 
  593                                $maymatch = !isset($child[
'constant']) && array_search($child[
'type'], array($temp[
'type'], self::TYPE_ANY, self::TYPE_CHOICE)) !== 
false;
 
  600                        $candidate = $this->
asn1map($temp, $child, $special);
 
  601                        $maymatch = $candidate !== 
null;
 
  606                        if (isset($special[
$key])) {
 
  607                            $candidate = call_user_func($special[
$key], $candidate);
 
  611                    } elseif (isset($child[
'default'])) {
 
  613                    } elseif (!isset($child[
'optional'])) {
 
  626                if (isset($mapping[
'min']) && isset($mapping[
'max'])) {
 
  627                    $child = $mapping[
'children'];
 
  628                    foreach ($decoded[
'content'] as $content) {
 
  629                        if ((
$map[] = $this->
asn1map($content, $child, $special)) === 
null) {
 
  637                for (
$i = 0; 
$i < count($decoded[
'content']); 
$i++) {
 
  638                    $temp = $decoded[
'content'][
$i];
 
  640                    if (isset($temp[
'constant'])) {
 
  644                    foreach ($mapping[
'children'] as 
$key => $child) {
 
  649                        if ($child[
'type'] != self::TYPE_CHOICE) {
 
  652                            if (isset($child[
'class'])) {
 
  653                                $childClass = $child[
'class'];
 
  654                                $constant = $child[
'cast'];
 
  655                            } elseif (isset($child[
'constant'])) {
 
  657                                $constant = $child[
'constant'];
 
  660                            if (isset($constant) && isset($temp[
'constant'])) {
 
  662                                $maymatch = $constant == $temp[
'constant'] && $childClass == $tempClass;
 
  665                                $maymatch = !isset($child[
'constant']) && array_search($child[
'type'], array($temp[
'type'], self::TYPE_ANY, self::TYPE_CHOICE)) !== 
false;
 
  671                            $candidate = $this->
asn1map($temp, $child, $special);
 
  672                            $maymatch = $candidate !== 
null;
 
  680                        if (isset($special[
$key])) {
 
  681                            $candidate = call_user_func($special[
$key], $candidate);
 
  688                foreach ($mapping[
'children'] as 
$key => $child) {
 
  690                        if (isset($child[
'default'])) {
 
  692                        } elseif (!isset($child[
'optional'])) {
 
  699                return isset($this->oids[$decoded[
'content']]) ? $this->oids[$decoded[
'content']] : $decoded[
'content'];
 
  702                if (isset($mapping[
'implicit'])) {
 
  703                    $decoded[
'content'] = $this->
_decodeTime($decoded[
'content'], $decoded[
'type']);
 
  705                return @date($this->format, $decoded[
'content']);
 
  707                if (isset($mapping[
'mapping'])) {
 
  708                    $offset = ord($decoded[
'content'][0]);
 
  709                    $size = (strlen($decoded[
'content']) - 1) * 8 - $offset;
 
  718                    $bits = count($mapping[
'mapping']) == 
$size ? array() : array_fill(0, count($mapping[
'mapping']) - 
$size, 
false);
 
  719                    for (
$i = strlen($decoded[
'content']) - 1; 
$i > 0; 
$i--) {
 
  721                        for ($j = $offset; $j < 8; $j++) {
 
  722                            $bits[] = (bool) (
$current & (1 << $j));
 
  727                    $map = array_reverse($mapping[
'mapping']);
 
  728                    foreach (
$map as 
$i => $value) {
 
  736                return base64_encode($decoded[
'content']);
 
  740                return $decoded[
'content'];
 
  752                return $decoded[
'content'];
 
  755                $temp = $decoded[
'content'];
 
  756                if (isset($mapping[
'implicit'])) {
 
  757                    $temp = 
new BigInteger($decoded[
'content'], -256);
 
  759                if (isset($mapping[
'mapping'])) {
 
  760                    $temp = (int) $temp->toString();
 
  761                    return isset($mapping[
'mapping'][$temp]) ?
 
  762                        $mapping[
'mapping'][$temp] :
 
  785        $this->location = array();
 
  805        if (isset($mapping[
'default']) && 
$source === $mapping[
'default']) {
 
  810            if (isset($special[$idx])) {
 
  813            $this->location[] = $idx;
 
  816        $tag = $mapping[
'type'];
 
  825                if (isset($mapping[
'min']) && isset($mapping[
'max'])) {
 
  826                    $child = $mapping[
'children'];
 
  828                    foreach (
$source as $content) {
 
  829                        $temp = $this->
_encode_der($content, $child, 
null, $special);
 
  830                        if ($temp === 
false) {
 
  838                foreach ($mapping[
'children'] as 
$key => $child) {
 
  840                        if (!isset($child[
'optional'])) {
 
  847                    if ($temp === 
false) {
 
  858                    if (isset($child[
'constant'])) {
 
  868                        if (isset($child[
'explicit']) || $child[
'type'] == self::TYPE_CHOICE) {
 
  869                            $subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | 0x20 | $child[
'constant']);
 
  870                            $temp = $subtag . $this->
_encodeLength(strlen($temp)) . $temp;
 
  872                            $subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | (ord($temp[0]) & 0x20) | $child[
'constant']);
 
  873                            $temp = $subtag . substr($temp, 1);
 
  882                foreach ($mapping[
'children'] as 
$key => $child) {
 
  888                    if ($temp === 
false) {
 
  898                    $tag = ord($temp[0]);
 
  901                    if (isset($child[
'constant'])) {
 
  902                        if (isset($child[
'explicit']) || $child[
'type'] == self::TYPE_CHOICE) {
 
  903                            $subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | 0x20 | $child[
'constant']);
 
  904                            $temp = $subtag . $this->
_encodeLength(strlen($temp)) . $temp;
 
  906                            $subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | (ord($temp[0]) & 0x20) | $child[
'constant']);
 
  907                            $temp = $subtag . substr($temp, 1);
 
  913                    array_pop($this->location);
 
  916                if ($temp && isset($mapping[
'cast'])) {
 
  917                    $temp[0] = chr(($mapping[
'class'] << 6) | (
$tag & 0x20) | $mapping[
'cast']);
 
  923                if (!isset($mapping[
'mapping'])) {
 
  927                    $value = 
$source->toBytes(
true);
 
  929                    $value = array_search(
$source, $mapping[
'mapping']);
 
  930                    if ($value === 
false) {
 
  934                    $value = $value->toBytes(
true);
 
  936                if (!strlen($value)) {
 
  942                $format = $mapping[
'type'] == self::TYPE_UTC_TIME ? 
'y' : 
'Y';
 
  947                if (isset($mapping[
'mapping'])) {
 
  948                    $bits = array_fill(0, count($mapping[
'mapping']), 0);
 
  950                    for (
$i = 0; 
$i < count($mapping[
'mapping']); 
$i++) {
 
  951                        if (in_array($mapping[
'mapping'][
$i], 
$source)) {
 
  957                    if (isset($mapping[
'min']) && $mapping[
'min'] >= 1 && 
$size < $mapping[
'min']) {
 
  958                        $size = $mapping[
'min'] - 1;
 
  961                    $offset = 8 - ((
$size + 1) & 7);
 
  962                    $offset = $offset !== 8 ? $offset : 0;
 
  964                    $value = chr($offset);
 
  966                    for (
$i = 
$size + 1; 
$i < count($mapping[
'mapping']); 
$i++) {
 
  970                    $bits = implode(
'', array_pad($bits, 
$size + $offset + 1, 0));
 
  971                    $bytes = explode(
' ', rtrim(chunk_split($bits, 8, 
' ')));
 
  972                    foreach ($bytes as $byte) {
 
  973                        $value.= chr(bindec($byte));
 
  983                $value = base64_decode(
$source);
 
  987                if ($oid === 
false) {
 
  988                    user_error(
'Invalid OID');
 
  992                $parts = explode(
'.', $oid);
 
  993                $value = chr(40 * $parts[0] + $parts[1]);
 
  994                for (
$i = 2; 
$i < count($parts); 
$i++) {
 
 1000                            $temp = chr(0x80 | ($parts[
$i] & 0x7F)) . $temp;
 
 1003                        $temp[strlen($temp) - 1] = $temp[strlen($temp) - 1] & chr(0x7F);
 
 1011                    array_pop($this->location);
 
 1016                        return $this->
_encode_der(
null, array(
'type' => self::TYPE_NULL) + $mapping, 
null, $special);
 
 1019                        return $this->
_encode_der(
$source, array(
'type' => self::TYPE_INTEGER) + $mapping, 
null, $special);
 
 1021                        return $this->
_encode_der(
$source, array(
'type' => self::TYPE_REAL) + $mapping, 
null, $special);
 
 1023                        return $this->
_encode_der(
$source, array(
'type' => self::TYPE_BOOLEAN) + $mapping, 
null, $special);
 
 1025                        $typename = implode(
'', array_keys(
$source));
 
 1026                        $outtype = array_search($typename, $this->ANYmap, 
true);
 
 1027                        if ($outtype !== 
false) {
 
 1028                            return $this->
_encode_der(
$source[$typename], array(
'type' => $outtype) + $mapping, 
null, $special);
 
 1033                foreach ($loc as $part) {
 
 1041                    user_error(
'No filters defined for ' . implode(
'/', $loc));
 
 1062                $value = 
$source ? 
"\xFF" : 
"\x00";
 
 1065                user_error(
'Mapping provides no type definition for ' . implode(
'/', $this->location));
 
 1070            array_pop($this->location);
 
 1073        if (isset($mapping[
'cast'])) {
 
 1074            if (isset($mapping[
'explicit']) || $mapping[
'type'] == self::TYPE_CHOICE) {
 
 1076                $tag = ($mapping[
'class'] << 6) | 0x20 | $mapping[
'cast'];
 
 1078                $tag = ($mapping[
'class'] << 6) | (ord($temp[0]) & 0x20) | $mapping[
'cast'];
 
 1097        if ($length <= 0x7F) {
 
 1098            return chr($length);
 
 1101        $temp = ltrim(pack(
'N', $length), chr(0));
 
 1102        return pack(
'Ca*', 0x80 | strlen($temp), $temp);
 
 1125        $pattern = 
$tag == self::TYPE_UTC_TIME ?
 
 1126            '#(..)(..)(..)(..)(..)(..)(.*)#' :
 
 1127            '#(....)(..)(..)(..)(..)(..).*([Z+-].*)$#';
 
 1129        preg_match($pattern, $content, $matches);
 
 1131        list(, $year, $month, $day, $hour, $minute, $second, $timezone) = $matches;
 
 1133        if (
$tag == self::TYPE_UTC_TIME) {
 
 1134            $year = $year >= 50 ? 
"19$year" : 
"20$year";
 
 1137        if ($timezone == 
'Z') {
 
 1138            $mktime = 
'gmmktime';
 
 1140        } elseif (preg_match(
'#([+-])(\d\d)(\d\d)#', $timezone, $matches)) {
 
 1141            $mktime = 
'gmmktime';
 
 1142            $timezone = 60 * $matches[3] + 3600 * $matches[2];
 
 1143            if ($matches[1] == 
'-') {
 
 1144                $timezone = -$timezone;
 
 1151        return @$mktime($hour, $minute, $second, $month, $day, $year) + $timezone;
 
 1177        $this->oids = 
$oids;
 
 1205        $substr = substr($string, 0, 
$index);
 
 1206        $string = substr($string, 
$index);
 
 1224        if (!isset($this->stringTypeSize[
$from]) || !isset($this->stringTypeSize[$to])) {
 
 1227        $insize = $this->stringTypeSize[
$from];
 
 1228        $outsize = $this->stringTypeSize[$to];
 
 1229        $inlength = strlen(
$in);
 
 1232        for (
$i = 0; 
$i < $inlength;) {
 
 1233            if ($inlength - 
$i < $insize) {
 
 1247                case (
$c & 0x80) == 0x00:
 
 1249                case (
$c & 0x40) == 0x00:
 
 1254                        if ($bit > 25 || 
$i >= $inlength || (ord(
$in[
$i]) & 0xC0) != 0x80) {
 
 1257                        $c = (
$c << 6) | (ord(
$in[
$i++]) & 0x3F);
 
 1260                    } 
while (
$c & $bit);
 
 1269                    $v .= chr(
$c & 0xFF);
 
 1271                    $v .= chr(
$c & 0xFF);
 
 1274                    $v .= chr(
$c & 0xFF);
 
 1277                    $v .= chr(
$c & 0xFF);
 
 1283                case (
$c & 0x80000000) != 0:
 
 1285                case $c >= 0x04000000:
 
 1286                    $v .= chr(0x80 | (
$c & 0x3F));
 
 1287                    $c = (
$c >> 6) | 0x04000000;
 
 1288                case $c >= 0x00200000:
 
 1289                    $v .= chr(0x80 | (
$c & 0x3F));
 
 1290                    $c = (
$c >> 6) | 0x00200000;
 
 1291                case $c >= 0x00010000:
 
 1292                    $v .= chr(0x80 | (
$c & 0x3F));
 
 1293                    $c = (
$c >> 6) | 0x00010000;
 
 1294                case $c >= 0x00000800:
 
 1295                    $v .= chr(0x80 | (
$c & 0x3F));
 
 1296                    $c = (
$c >> 6) | 0x00000800;
 
 1297                case $c >= 0x00000080:
 
 1298                    $v .= chr(0x80 | (
$c & 0x3F));
 
 1299                    $c = (
$c >> 6) | 0x000000C0;
 
if(php_sapi_name() !='cli') $in
An exception for terminatinating execution or to throw for unit testing.
const TYPE_PRINTABLE_STRING
const TYPE_GRAPHIC_STRING
encodeDER($source, $mapping, $special=array())
ASN.1 Encode.
const TYPE_OBJECT_IDENTIFIER
const TYPE_TELETEX_STRING
setTimeFormat($format)
Set the time format.
asn1map($decoded, $mapping, $special=array())
ASN.1 Map.
_encode_der($source, $mapping, $idx=null, $special=array())
ASN.1 Encode (Helper function)
loadFilters($filters)
Load filters.
decodeBER($encoded)
Parse BER-encoding.
const TYPE_GENERAL_STRING
const TYPE_GENERALIZED_TIME
const TYPE_UNIVERSAL_STRING
_string_shift(&$string, $index=1)
String Shift.
const TYPE_VISIBLE_STRING
loadOIDs($oids)
Load OIDs.
convert($in, $from=self::TYPE_UTF8_STRING, $to=self::TYPE_UTF8_STRING)
String type conversion.
const TYPE_VIDEOTEX_STRING
_decode_ber($encoded, $start=0)
Parse BER-encoding (Helper function)
const CLASS_CONTEXT_SPECIFIC
const CLASS_UNIVERSAL
#+ Tag Classes
const TYPE_NUMERIC_STRING
#-
_encodeLength($length)
DER-encode the length.
_decodeTime($content, $tag)
BER-decode the time.
if(function_exists( 'posix_getuid') &&posix_getuid()===0) if(!array_key_exists('t', $options)) $tag
Pure-PHP arbitrary precision integer arithmetic library.