mirror of
https://github.com/phpseclib/phpseclib.git
synced 2024-11-16 02:07:09 +00:00
ASN1 / X509: update to use DateTime instead of unix time
This commit is contained in:
parent
5c792f6bc1
commit
09c17b1a31
@ -554,7 +554,9 @@ class File_ASN1
|
||||
break;
|
||||
case FILE_ASN1_TYPE_UTC_TIME:
|
||||
case FILE_ASN1_TYPE_GENERALIZED_TIME:
|
||||
$current['content'] = $this->_decodeTime(substr($content, $content_pos), $tag);
|
||||
$current['content'] = class_exists('DateTime') ?
|
||||
$this->_decodeDateTime(substr($content, $content_pos), $tag) :
|
||||
$this->_decodeUnixTime(substr($content, $content_pos), $tag);
|
||||
default:
|
||||
}
|
||||
|
||||
@ -788,10 +790,20 @@ class File_ASN1
|
||||
return isset($this->oids[$decoded['content']]) ? $this->oids[$decoded['content']] : $decoded['content'];
|
||||
case FILE_ASN1_TYPE_UTC_TIME:
|
||||
case FILE_ASN1_TYPE_GENERALIZED_TIME:
|
||||
if (class_exists('DateTime')) {
|
||||
if (isset($mapping['implicit'])) {
|
||||
$decoded['content'] = $this->_decodeTime($decoded['content'], $decoded['type']);
|
||||
$decoded['content'] = $this->_decodeDateTime($decoded['content'], $decoded['type']);
|
||||
}
|
||||
if (!$decoded['content']) {
|
||||
return false;
|
||||
}
|
||||
return $decoded['content']->format($this->format);
|
||||
} else {
|
||||
if (isset($mapping['implicit'])) {
|
||||
$decoded['content'] = $this->_decodeUnixTime($decoded['content'], $decoded['type']);
|
||||
}
|
||||
return @date($this->format, $decoded['content']);
|
||||
}
|
||||
case FILE_ASN1_TYPE_BIT_STRING:
|
||||
if (isset($mapping['mapping'])) {
|
||||
$offset = ord($decoded['content'][0]);
|
||||
@ -1040,7 +1052,12 @@ class File_ASN1
|
||||
case FILE_ASN1_TYPE_GENERALIZED_TIME:
|
||||
$format = $mapping['type'] == FILE_ASN1_TYPE_UTC_TIME ? 'y' : 'Y';
|
||||
$format.= 'mdHis';
|
||||
if (!class_exists('DateTime')) {
|
||||
$value = @gmdate($format, strtotime($source)) . 'Z';
|
||||
} else {
|
||||
$date = new DateTime($source, new DateTimeZone('GMT'));
|
||||
$value = $date->format($format) . 'Z';
|
||||
}
|
||||
break;
|
||||
case FILE_ASN1_TYPE_BIT_STRING:
|
||||
if (isset($mapping['mapping'])) {
|
||||
@ -1202,7 +1219,7 @@ class File_ASN1
|
||||
}
|
||||
|
||||
/**
|
||||
* BER-decode the time
|
||||
* BER-decode the time (using UNIX time)
|
||||
*
|
||||
* Called by _decode_ber() and in the case of implicit tags asn1map().
|
||||
*
|
||||
@ -1211,7 +1228,7 @@ class File_ASN1
|
||||
* @param int $tag
|
||||
* @return string
|
||||
*/
|
||||
function _decodeTime($content, $tag)
|
||||
function _decodeUnixTime($content, $tag)
|
||||
{
|
||||
/* UTCTime:
|
||||
http://tools.ietf.org/html/rfc5280#section-4.1.2.5.1
|
||||
@ -1250,6 +1267,55 @@ class File_ASN1
|
||||
return @$mktime((int)$hour, (int)$minute, (int)$second, (int)$month, (int)$day, (int)$year) + $timezone;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* BER-decode the time (using DateTime)
|
||||
*
|
||||
* Called by _decode_ber() and in the case of implicit tags asn1map().
|
||||
*
|
||||
* @access private
|
||||
* @param string $content
|
||||
* @param int $tag
|
||||
* @return string
|
||||
*/
|
||||
function _decodeDateTime($content, $tag)
|
||||
{
|
||||
/* UTCTime:
|
||||
http://tools.ietf.org/html/rfc5280#section-4.1.2.5.1
|
||||
http://www.obj-sys.com/asn1tutorial/node15.html
|
||||
|
||||
GeneralizedTime:
|
||||
http://tools.ietf.org/html/rfc5280#section-4.1.2.5.2
|
||||
http://www.obj-sys.com/asn1tutorial/node14.html */
|
||||
|
||||
$format = 'YmdHis';
|
||||
|
||||
if ($tag == FILE_ASN1_TYPE_UTC_TIME) {
|
||||
// https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=28 says "the seconds
|
||||
// element shall always be present" but none-the-less I've seen X509 certs where it isn't and if the
|
||||
// browsers parse it phpseclib ought to too
|
||||
if (preg_match('#^(\d{10})(Z|[+-]\d{4})$#', $content, $matches)) {
|
||||
$content = $matches[1] . '00' . $matches[2];
|
||||
}
|
||||
$prefix = substr($content, 0, 2) >= 50 ? '19' : '20';
|
||||
$content = $prefix . $content;
|
||||
} elseif (strpos($content, '.') !== false) {
|
||||
$format.= '.u';
|
||||
}
|
||||
|
||||
if ($content[strlen($content) - 1] == 'Z') {
|
||||
$content = substr($content, 0, -1) . '+0000';
|
||||
}
|
||||
|
||||
if (strpos($content, '-') !== false || strpos($content, '+') !== false) {
|
||||
$format.= 'O';
|
||||
}
|
||||
|
||||
// error supression isn't necessary as of PHP 7.0:
|
||||
// http://php.net/manual/en/migration70.other-changes.php
|
||||
return @DateTime::createFromFormat($format, $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the time format
|
||||
*
|
||||
|
@ -2114,7 +2114,9 @@ class File_X509
|
||||
}
|
||||
|
||||
if (!isset($date)) {
|
||||
$date = time();
|
||||
$date = class_exists('DateTime') ?
|
||||
new DateTime($date, new DateTimeZone(date_default_timezone_get())) :
|
||||
time();
|
||||
}
|
||||
|
||||
$notBefore = $this->currentCert['tbsCertificate']['validity']['notBefore'];
|
||||
@ -2123,9 +2125,17 @@ class File_X509
|
||||
$notAfter = $this->currentCert['tbsCertificate']['validity']['notAfter'];
|
||||
$notAfter = isset($notAfter['generalTime']) ? $notAfter['generalTime'] : $notAfter['utcTime'];
|
||||
|
||||
if (class_exists('DateTime')) {
|
||||
$notBefore = new DateTime($notBefore, new DateTimeZone(@date_default_timezone_get()));
|
||||
$notAfter = new DateTime($notAfter, new DateTimeZone(@date_default_timezone_get()));
|
||||
} else {
|
||||
$notBefore = @strtotime($notBefore);
|
||||
$notAfter = @strtotime($notAfter);
|
||||
}
|
||||
|
||||
switch (true) {
|
||||
case $date < @strtotime($notBefore):
|
||||
case $date > @strtotime($notAfter):
|
||||
case $date < $notBefore:
|
||||
case $date > $notAfter:
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3385,7 +3395,15 @@ class File_X509
|
||||
*/
|
||||
function _timeField($date)
|
||||
{
|
||||
if (is_object($date) && strtolower(get_class($date)) == 'file_asn1_element') {
|
||||
return $date;
|
||||
}
|
||||
if (!class_exists('DateTime')) {
|
||||
$year = @gmdate("Y", @strtotime($date)); // the same way ASN1.php parses this
|
||||
} else {
|
||||
$dateObj = new DateTime($date, new DateTimeZone('GMT'));
|
||||
$year = $dateObj->format('Y');
|
||||
}
|
||||
if ($year < 2050) {
|
||||
return array('utcTime' => $date);
|
||||
} else {
|
||||
@ -3450,8 +3468,16 @@ class File_X509
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!class_exists('DateTime')) {
|
||||
$startDate = !empty($this->startDate) ? $this->startDate : @date('D, d M Y H:i:s O');
|
||||
$endDate = !empty($this->endDate) ? $this->endDate : @date('D, d M Y H:i:s O', strtotime('+1 year'));
|
||||
} else {
|
||||
$startDate = new DateTime('now', new DateTimeZone(@date_default_timezone_get()));
|
||||
$startDate = !empty($this->startDate) ? $this->startDate : $startDate->format('D, d M Y H:i:s O');
|
||||
|
||||
$endDate = new DateTime('+1 year', new DateTimeZone(@date_default_timezone_get()));
|
||||
$endDate = !empty($this->endDate) ? $this->endDate : $endDate->format('D, d M Y H:i:s O');
|
||||
}
|
||||
if (!empty($this->serialNumber)) {
|
||||
$serialNumber = $this->serialNumber;
|
||||
} else {
|
||||
@ -3724,7 +3750,12 @@ class File_X509
|
||||
|
||||
$currentCert = isset($this->currentCert) ? $this->currentCert : null;
|
||||
$signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null;
|
||||
if (!class_exists('DateTime')) {
|
||||
$thisUpdate = !empty($this->startDate) ? $this->startDate : @date('D, d M Y H:i:s O');
|
||||
} else {
|
||||
$thisUpdate = new DateTime('now', new DateTimeZone(@date_default_timezone_get()));
|
||||
$thisUpdate = !empty($this->startDate) ? $this->startDate : $thisUpdate->format('D, d M Y H:i:s O');
|
||||
}
|
||||
|
||||
if (isset($crl->currentCert) && is_array($crl->currentCert) && isset($crl->currentCert['tbsCertList'])) {
|
||||
$this->currentCert = $crl->currentCert;
|
||||
@ -3876,8 +3907,13 @@ class File_X509
|
||||
*/
|
||||
function setStartDate($date)
|
||||
{
|
||||
if (class_exists('DateTime')) {
|
||||
$date = new DateTime($date);
|
||||
$this->startDate = $date->format('D, d M Y H:i:s O');
|
||||
} else {
|
||||
$this->startDate = @date('D, d M Y H:i:s O', @strtotime($date));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set certificate end date
|
||||
@ -3899,10 +3935,15 @@ class File_X509
|
||||
$asn1 = new File_ASN1();
|
||||
$temp = chr(FILE_ASN1_TYPE_GENERALIZED_TIME) . $asn1->_encodeLength(strlen($temp)) . $temp;
|
||||
$this->endDate = new File_ASN1_Element($temp);
|
||||
} else {
|
||||
if (class_exists('DateTime')) {
|
||||
$date = new DateTime($date);
|
||||
$this->endDate = $date->format('D, d M Y H:i:s O');
|
||||
} else {
|
||||
$this->endDate = @date('D, d M Y H:i:s O', @strtotime($date));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Serial Number
|
||||
@ -4640,9 +4681,16 @@ class File_X509
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!class_exists('DateTime')) {
|
||||
$revocationDate = @date('D, d M Y H:i:s O');
|
||||
} else {
|
||||
$revocationDate = new DateTime('now', new DateTimeZone(@date_default_timezone_get()));
|
||||
$revocationDate = $revocationDate->format('D, d M Y H:i:s O');
|
||||
}
|
||||
|
||||
$i = count($rclist);
|
||||
$rclist[] = array('userCertificate' => $serial,
|
||||
'revocationDate' => $this->_timeField(@date('D, d M Y H:i:s O')));
|
||||
'revocationDate' => $this->_timeField($revocationDate));
|
||||
return $i;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user