mirror of
https://github.com/phpseclib/phpseclib.git
synced 2024-12-26 11:37:33 +00:00
fix certificate date encoding
RFC 3280 requires in section - 4.1.2.5 Validity - 5.1.2.4 This Update - 5.1.2.5 Next Update - 5.1.2.6 Revoked Certificates that dates are to be encoded as utcTime iff they are before 2050 and as generalTime otherwise. Currently, phpseclib does not respect this by always choosing generalTime. Further, the format used interally to represent dates only keeps two digits, so dates in 2050 and later cannot be represented in this format. This patch fixes this by 1. changing the interal format to be capable of unambiguously representing dates in 2050 or later (i.e. use four digits to represent the year), 2. choosing between utcTime and generalTime accordingly. Without this patch, openssl_x509_parse complains: Warning: openssl_x509_parse(): illegal ASN1 data type for timestamp
This commit is contained in:
parent
b77b26f692
commit
457f8fbb99
@ -162,7 +162,7 @@ class File_ASN1
|
||||
* @access private
|
||||
* @link http://php.net/class.datetime
|
||||
*/
|
||||
var $format = 'D, d M y H:i:s O';
|
||||
var $format = 'D, d M Y H:i:s O';
|
||||
|
||||
/**
|
||||
* Default date format
|
||||
|
@ -3116,6 +3116,28 @@ class File_X509
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to build a time field according to RFC 3280 section
|
||||
* - 4.1.2.5 Validity
|
||||
* - 5.1.2.4 This Update
|
||||
* - 5.1.2.5 Next Update
|
||||
* - 5.1.2.6 Revoked Certificates
|
||||
* by choosing utcTime iff year of date given is before 2050 and generalTime else.
|
||||
*
|
||||
* @param String $date in format date('D, d M Y H:i:s O')
|
||||
* @access private
|
||||
* @return Array
|
||||
*/
|
||||
function _timeField($date)
|
||||
{
|
||||
$year = @gmdate("Y", @strtotime($date)); // the same way ASN1.php parses this
|
||||
if ($year < 2050) {
|
||||
return Array('utcTime' => $date);
|
||||
} else {
|
||||
return Array('generalTime' => $date);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign an X.509 certificate
|
||||
*
|
||||
@ -3148,12 +3170,10 @@ class File_X509
|
||||
$this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm;
|
||||
|
||||
if (!empty($this->startDate)) {
|
||||
$this->currentCert['tbsCertificate']['validity']['notBefore']['generalTime'] = $this->startDate;
|
||||
unset($this->currentCert['tbsCertificate']['validity']['notBefore']['utcTime']);
|
||||
$this->currentCert['tbsCertificate']['validity']['notBefore'] = $this->_timeField($this->startDate);
|
||||
}
|
||||
if (!empty($this->endDate)) {
|
||||
$this->currentCert['tbsCertificate']['validity']['notAfter']['generalTime'] = $this->endDate;
|
||||
unset($this->currentCert['tbsCertificate']['validity']['notAfter']['utcTime']);
|
||||
$this->currentCert['tbsCertificate']['validity']['notAfter'] = $this->_timeField($this->endDate);
|
||||
}
|
||||
if (!empty($this->serialNumber)) {
|
||||
$this->currentCert['tbsCertificate']['serialNumber'] = $this->serialNumber;
|
||||
@ -3175,8 +3195,8 @@ class File_X509
|
||||
return false;
|
||||
}
|
||||
|
||||
$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'));
|
||||
$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'));
|
||||
$serialNumber = !empty($this->serialNumber) ? $this->serialNumber : new Math_BigInteger();
|
||||
|
||||
$this->currentCert = array(
|
||||
@ -3187,8 +3207,8 @@ class File_X509
|
||||
'signature' => array('algorithm' => $signatureAlgorithm),
|
||||
'issuer' => false, // this is going to be overwritten later
|
||||
'validity' => array(
|
||||
'notBefore' => array('generalTime' => $startDate), // $this->setStartDate()
|
||||
'notAfter' => array('generalTime' => $endDate) // $this->setEndDate()
|
||||
'notBefore' => $this->_timeField($startDate), // $this->setStartDate()
|
||||
'notAfter' => $this->_timeField($endDate) // $this->setEndDate()
|
||||
),
|
||||
'subject' => $subject->dn,
|
||||
'subjectPublicKeyInfo' => $subjectPublicKey
|
||||
@ -3367,7 +3387,7 @@ class File_X509
|
||||
|
||||
$currentCert = isset($this->currentCert) ? $this->currentCert : null;
|
||||
$signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null;
|
||||
$thisUpdate = !empty($this->startDate) ? $this->startDate : @date('D, d M y H:i:s O');
|
||||
$thisUpdate = !empty($this->startDate) ? $this->startDate : @date('D, d M Y H:i:s O');
|
||||
|
||||
if (isset($crl->currentCert) && is_array($crl->currentCert) && isset($crl->currentCert['tbsCertList'])) {
|
||||
$this->currentCert = $crl->currentCert;
|
||||
@ -3380,7 +3400,7 @@ class File_X509
|
||||
'version' => 'v2',
|
||||
'signature' => array('algorithm' => $signatureAlgorithm),
|
||||
'issuer' => false, // this is going to be overwritten later
|
||||
'thisUpdate' => array('generalTime' => $thisUpdate) // $this->setStartDate()
|
||||
'thisUpdate' => $this->_timeField($thisUpdate) // $this->setStartDate()
|
||||
),
|
||||
'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
|
||||
'signature' => false // this is going to be overwritten later
|
||||
@ -3389,10 +3409,10 @@ class File_X509
|
||||
|
||||
$tbsCertList = &$this->currentCert['tbsCertList'];
|
||||
$tbsCertList['issuer'] = $issuer->dn;
|
||||
$tbsCertList['thisUpdate'] = array('generalTime' => $thisUpdate);
|
||||
$tbsCertList['thisUpdate'] = $this->_timeField($thisUpdate);
|
||||
|
||||
if (!empty($this->endDate)) {
|
||||
$tbsCertList['nextUpdate'] = array('generalTime' => $this->endDate); // $this->setEndDate()
|
||||
$tbsCertList['nextUpdate'] = $this->_timeField($this->endDate); // $this->setEndDate()
|
||||
} else {
|
||||
unset($tbsCertList['nextUpdate']);
|
||||
}
|
||||
@ -3515,7 +3535,7 @@ class File_X509
|
||||
*/
|
||||
function setStartDate($date)
|
||||
{
|
||||
$this->startDate = @date('D, d M y H:i:s O', @strtotime($date));
|
||||
$this->startDate = @date('D, d M Y H:i:s O', @strtotime($date));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3539,7 +3559,7 @@ class File_X509
|
||||
$temp = chr(FILE_ASN1_TYPE_GENERALIZED_TIME) . $asn1->_encodeLength(strlen($temp)) . $temp;
|
||||
$this->endDate = new File_ASN1_Element($temp);
|
||||
} else {
|
||||
$this->endDate = @date('D, d M y H:i:s O', @strtotime($date));
|
||||
$this->endDate = @date('D, d M Y H:i:s O', @strtotime($date));
|
||||
}
|
||||
}
|
||||
|
||||
@ -4213,7 +4233,7 @@ class File_X509
|
||||
|
||||
$i = count($rclist);
|
||||
$rclist[] = array('userCertificate' => $serial,
|
||||
'revocationDate' => array('generalTime' => @date('D, d M y H:i:s O')));
|
||||
'revocationDate' => $this->_timeField(@date('D, d M Y H:i:s O')));
|
||||
return $i;
|
||||
}
|
||||
|
||||
@ -4233,7 +4253,7 @@ class File_X509
|
||||
if (($i = $this->_revokedCertificate($rclist, $serial, true)) !== false) {
|
||||
|
||||
if (!empty($date)) {
|
||||
$rclist[$i]['revocationDate'] = array('generalTime' => $date);
|
||||
$rclist[$i]['revocationDate'] = $this->_timeField($date);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
Loading…
Reference in New Issue
Block a user