bytes = $data; } else if ($data instanceof ASN1DEREncodable) { $this->bytes = $data->encodeDER(); } else { throw new GTException("paramater data must be an array of bytes or an instance of ASN1DEREncodable"); } } /** * Destructs this X509Certificate. * * This method frees any allocated OpenSSL resources. * */ public function __destruct() { if ($this->pkey !== null && $this->pkey !== false) { openssl_pkey_free($this->pkey); } if ($this->cert !== null && $this->cert !== false) { openssl_x509_free($this->cert); } } /** * PEM encodes this certificate. * * @return string pem encoded certificate */ public function encodePEM() { $pem = ""; $pem .= "-----BEGIN CERTIFICATE-----\r\n"; $body = GTBase64::encode($this->bytes); $body = wordwrap($body, 64, "\r\n", true); if ($body{strlen($body) - 1} != "\n") { $body .= "\r\n"; } $pem .= $body; $pem .= "-----END CERTIFICATE-----\r\n"; return $pem; } /** * Verifies the given signature using this certificate's public key. * * @param array $data byte array containing the data bytes that were signed * @param array $sign byte array containing the signature bytes * @param string $algorithm the hash algorithm to use * @return bool true if the signature is valid */ public function verifySignature($data, $sign, $algorithm = 'sha256') { if (empty($data)) { throw new GTException("Parameter data is required"); } if (empty($sign)) { throw new GTException("Parameter sign is required"); } if ($this->cert === null || $this->cert === false) { $this->cert = openssl_x509_read($this->encodePEM()); } if ($this->pkey == null || $this->pkey === false) { $this->pkey = openssl_pkey_get_public($this->cert); } return X509Certificate::verifyPublicKeySignature($this->pkey, $data, $sign, $algorithm); } /** * Gets the certificate parameters. * * @return array containing the certificate parameters * @see openssl_x509_parse */ public function getParameters() { if ($this->cert === null || $this->cert === false) { $this->cert = openssl_x509_read($this->encodePEM()); } if ($this->data === null) { $this->data = openssl_x509_parse($this->cert); } return $this->data; } /** * Gets this certificate's public key. * * @return resource OpenSSL public key resource * @see openssl_pkey_get_public * */ public function getPublicKey() { if ($this->cert === null || $this->cert === false) { $this->cert = openssl_x509_read($this->encodePEM()); } if ($this->pkey === null || $this->pkey === false) { $this->pkey = openssl_pkey_get_public($this->cert); } return $this->pkey; } /** * Checks if this certificate is valid for given purpose. * * @throws GTException * @param int $purpose purpose * @param array $chain certificate chain * @param array $cainfo root certificates * @return bool true if this certificate is valid * * @see openssl_x509_checkpurpose */ public function isValid($purpose, $chain = array(), $cainfo = array()) { if ($this->cert === null || $this->cert === false) { $this->cert = openssl_x509_parse($this->encodePEM()); } // $untrustedFile = tempnam(sys_get_temp_dir(), "guardtime_ca"); $untrustedFile = tempnam(DOKU_INC.'/data/tmp/', "guardtime_ca"); foreach ($chain as $cert) { GTUtil::write($untrustedFile, GTUtil::toByteArray($cert->encodePEM())); } if ($cainfo == null) { $cainfo = array(); } else if (is_string($cainfo)) { if (!is_file($cainfo)) { throw new GTException("Specified cainfo file does not exist: {$cainfo}"); } $cainfo = array($cainfo); } else { throw new GTException("Invalid cainfo specified: " . $cainfo); } $result = openssl_x509_checkpurpose($this->cert, $purpose, $cainfo, $untrustedFile) === true; unlink($untrustedFile); return $result; } /** * Gets the public key hash for given public key. * * @static * @throws GTException * @param resource $pkey OpenSSL public key resource * @return GTDataHash public key hash */ public static function getPublicKeyHash($pkey) { if (!is_resource($pkey)) { throw new GTException("Parameter pkey must be a valid resource of type OpenSSL key"); } $params = openssl_pkey_get_details($pkey); $string = $params["key"]; $string = str_replace("-----BEGIN PUBLIC KEY-----", "", $string); $string = str_replace("-----END PUBLIC KEY-----", "", $string); $string = str_replace("\r", "", $string); $string = str_replace("\n", "", $string); $bytes = GTBase64::decode($string); $hash = new GTDataHash(GTHashAlgorithm::getByName('SHA256')); $hash->update($bytes); $hash->close(); return $hash; } /** * Verifies public key signature. * * @static * @throws GTException * @param resource $pkey public key to use for verification * @param array $data array of data bytes * @param array $sign array of signature bytes * @param string $algorithm the hash algorithm to use * @return bool true if signature is valid */ public static function verifyPublicKeySignature($pkey, $data, $sign, $algorithm = 'sha256') { if (empty($data)) { throw new GTException("Parameter data is required"); } if (empty($sign)) { throw new GTException("Parameter sign is required"); } if (!is_resource($pkey)) { throw new GTException("Parameter pkey must be a valid resource of type OpenSSL key"); } $data = GTUtil::fromByteArray($data); $sign = GTUtil::fromByteArray($sign); return openssl_verify($data, $sign, $pkey, $algorithm) === 1; } } ?>