/** * Generate a timestamp request (tsq) for a given hash * @param string $data the hash to be timestamped (raw binary) * @param boolean|string $nonce should a nonce be used - defaults to true, could be a value to use as nonce * @param boolean $requireCert should a certificate be returned in the response, defaults to false * @param string $alg the algorithm to use, defaults to 'sha1' * @param string|null $policy the policy to use, defaults to null * @return string the raw timestamp request */ public static function generateRequestFromHash($data, $nonce = true, $requireCert = false, $alg = 'sha1', $policy = null) { if (!in_array($alg, ['sha1', 'sha256', 'sha384', 'sha512', 'md5'])) { throw new TimestampException('Unsupported hash algorithm'); } if ($nonce === true) { $nonce = rand(1, PHP_INT_MAX); } if (!$nonce) { $nonce = null; } $src = ['version' => 'v1', 'reqPolicy' => $policy, 'messageImprint' => ['hashAlgorithm' => ["algorithm" => $alg, 'parameters' => null], 'hashedMessage' => base64_encode($data)], 'nonce' => $nonce, 'certReq' => $requireCert]; return ASN1::encodeDER($src, static::$request); }
/** * Save a SPKAC CSR request * * @param Array $csr * @param Integer $format optional * @access public * @return String */ function saveSPKAC($spkac, $format = X509_FORMAT_PEM) { if (!is_array($spkac) || !isset($spkac['publicKeyAndChallenge'])) { return false; } $algorithm = $this->_subArray($spkac, 'publicKeyAndChallenge/spki/algorithm/algorithm'); switch (true) { case !$algorithm: case is_object($spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']): break; default: switch ($algorithm) { case 'rsaEncryption': $spkac['publicKeyAndChallenge']['spki']['subjectPublicKey'] = base64_encode("" . base64_decode(preg_replace('#-.+-|[\\r\\n]#', '', $spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']))); } } $asn1 = new ASN1(); $asn1->loadOIDs($this->oids); $spkac = $asn1->encodeDER($spkac, $this->SignedPublicKeyAndChallenge); switch ($format) { case X509_FORMAT_DER: return $spkac; // case X509_FORMAT_PEM: // case X509_FORMAT_PEM: default: // OpenSSL's implementation of SPKAC requires the SPKAC be preceeded by SPKAC= and since there are pretty much // no other SPKAC decoders phpseclib will use that same format return 'SPKAC=' . base64_encode($spkac); } }
/** * Get the Distinguished Name for a certificates subject * * @param Mixed $format optional * @param Array $dn optional * @access public * @return Boolean */ function getDN($format = FILE_X509_DN_ARRAY, $dn = NULL) { if (!isset($dn)) { $dn = isset($this->currentCert['tbsCertList']) ? $this->currentCert['tbsCertList']['issuer'] : $this->dn; } switch ((int) $format) { case FILE_X509_DN_ARRAY: return $dn; case FILE_X509_DN_ASN1: $asn1 = new ASN1(); $asn1->loadOIDs($this->oids); $filters = array(); $filters['rdnSequence']['value'] = array('type' => FILE_ASN1_TYPE_UTF8_STRING); $asn1->loadFilters($filters); return $asn1->encodeDER($dn, $this->Name); case FILE_X509_DN_OPENSSL: $dn = $this->getDN(FILE_X509_DN_STRING, $dn); if ($dn === false) { return false; } $attrs = preg_split('#((?:^|, *|/)[a-z][a-z0-9]*=)#i', $dn, -1, PREG_SPLIT_DELIM_CAPTURE); $dn = array(); for ($i = 1; $i < count($attrs); $i += 2) { $prop = trim($attrs[$i], ', =/'); $value = $attrs[$i + 1]; if (!isset($dn[$prop])) { $dn[$prop] = $value; } else { $dn[$prop] = array_merge((array) $dn[$prop], array($value)); } } return $dn; case FILE_X509_DN_CANON: // No SEQUENCE around RDNs and all string values normalized as // trimmed lowercase UTF-8 with all spacing as one blank. $asn1 = new ASN1(); $asn1->loadOIDs($this->oids); $filters = array(); $filters['value'] = array('type' => FILE_ASN1_TYPE_UTF8_STRING); $asn1->loadFilters($filters); $result = ''; foreach ($dn['rdnSequence'] as $rdn) { foreach ($rdn as &$attr) { if (is_array($attr['value'])) { foreach ($attr['value'] as $type => $v) { $type = array_search($type, $asn1->ANYmap, true); if ($type !== false && isset($asn1->stringTypeSize[$type])) { $v = $asn1->convert($v, $type); if ($v !== false) { $v = preg_replace('/\\s+/', ' ', $v); $attr['value'] = strtolower(trim($v)); break; } } } } } $result .= $asn1->encodeDER($rdn, $this->RelativeDistinguishedName); } return $result; case FILE_X509_DN_HASH: $dn = $this->getDN(FILE_X509_DN_CANON, $dn); $hash = new Hash('sha1'); $hash = $hash->hash($dn); extract(unpack('Vhash', $hash)); return strtolower(bin2hex(pack('N', $hash))); } // Defaut is to return a string. $start = true; $output = ''; $asn1 = new ASN1(); foreach ($dn['rdnSequence'] as $field) { $prop = $field[0]['type']; $value = $field[0]['value']; $delim = ', '; switch ($prop) { case 'id-at-countryName': $desc = 'C='; break; case 'id-at-stateOrProvinceName': $desc = 'ST='; break; case 'id-at-organizationName': $desc = 'O='; break; case 'id-at-organizationalUnitName': $desc = 'OU='; break; case 'id-at-commonName': $desc = 'CN='; break; case 'id-at-localityName': $desc = 'L='; break; case 'id-at-surname': $desc = 'SN='; break; case 'id-at-uniqueIdentifier': $delim = '/'; $desc = 'x500UniqueIdentifier='; break; default: $delim = '/'; $desc = preg_replace('#.+-([^-]+)$#', '$1', $prop) . '='; } if (!$start) { $output .= $delim; } if (is_array($value)) { foreach ($value as $type => $v) { $type = array_search($type, $asn1->ANYmap, true); if ($type !== false && isset($asn1->stringTypeSize[$type])) { $v = $asn1->convert($v, $type); if ($v !== false) { $value = $v; break; } } } if (is_array($value)) { $value = array_pop($value); // Always strip data type. } } $output .= $desc . $value; $start = false; } return $output; }