protected function validateSslOptions()
{
// Get the contents.
$sslCertFile = file_exists($this->certPath) ? trim(file_get_contents($this->certPath)) : '';
$sslKeyFile = file_exists($this->keyPath) ? trim(file_get_contents($this->keyPath)) : '';
$sslChainFiles = $this->assembleChainFiles($this->chainPaths);
// Do a bit of validation.
// @todo: Cert first.
$certResource = openssl_x509_read($sslCertFile);
if (!$certResource) {
throw new \Exception("The provided certificate is either not a valid X509 certificate or could not be read.");
}
// Then the key. Does it match?
$keyResource = openssl_pkey_get_private($sslKeyFile);
if (!$keyResource) {
throw new \Exception("The provided private key is either not a valid RSA private key or could not be read.");
}
$keyMatch = openssl_x509_check_private_key($certResource, $keyResource);
if (!$keyMatch) {
throw new \Exception("The provided certificate does not match the provided private key.");
}
// Each chain needs to be a valid cert.
foreach ($sslChainFiles as $chainFile) {
$chainResource = openssl_x509_read($chainFile);
if (!$chainResource) {
throw new \Exception("One of the provided certificates in the chain is not a valid X509 certificate.");
} else {
openssl_x509_free($chainResource);
}
}
// Yay we win.
$this->sslOptions = array('certificate' => $sslCertFile, 'key' => $sslKeyFile, 'chain' => $sslChainFiles);
return true;
}
/**
* @return bool
*/
protected function validateSslOptions()
{
// Get the contents.
if (!is_readable($this->certPath)) {
$this->stdErr->writeln("The certificate file could not be read: " . $this->certPath);
return false;
}
$sslCert = trim(file_get_contents($this->certPath));
// Do a bit of validation.
$certResource = openssl_x509_read($sslCert);
if (!$certResource) {
$this->stdErr->writeln("The certificate file is not a valid X509 certificate: " . $this->certPath);
return false;
}
// Then the key. Does it match?
if (!is_readable($this->keyPath)) {
$this->stdErr->writeln("The private key file could not be read: " . $this->keyPath);
return false;
}
$sslPrivateKey = trim(file_get_contents($this->keyPath));
$keyResource = openssl_pkey_get_private($sslPrivateKey);
if (!$keyResource) {
$this->stdErr->writeln("Private key not valid, or passphrase-protected: " . $this->keyPath);
return false;
}
$keyMatch = openssl_x509_check_private_key($certResource, $keyResource);
if (!$keyMatch) {
$this->stdErr->writeln("The provided certificate does not match the provided private key.");
return false;
}
// Each chain needs to contain one or more valid certificates.
$chainFileContents = $this->readChainFiles($this->chainPaths);
foreach ($chainFileContents as $filePath => $data) {
$chainResource = openssl_x509_read($data);
if (!$chainResource) {
$this->stdErr->writeln("File contains an invalid X509 certificate: " . $filePath);
return false;
}
openssl_x509_free($chainResource);
}
// Split up the chain file contents.
$chain = [];
$begin = '-----BEGIN CERTIFICATE-----';
foreach ($chainFileContents as $data) {
if (substr_count($data, $begin) > 1) {
foreach (explode($begin, $data) as $cert) {
$chain[] = $begin . $cert;
}
} else {
$chain[] = $data;
}
}
// Yay we win.
$this->sslOptions = ['certificate' => $sslCert, 'key' => $sslPrivateKey, 'chain' => $chain];
return true;
}
/**
* Set our public certificate and private key.
*
* @param string $public_cert
* @param string $private_key
* @return self
*/
public function set_certificate($public_cert, $private_key)
{
// Parse the certificate
$this->public_cert = openssl_x509_read($public_cert);
// Parse our private key
$this->private_key = openssl_get_privatekey($private_key);
// Validate our certificate & private key
if (!$this->public_cert || !$this->private_key) {
throw new SecurityException('Invalid public certificate');
}
// Validate that our private key corresponds with our public certificate
if (!openssl_x509_check_private_key($this->public_cert, $this->private_key)) {
throw new SecurityException('Your private key does not correspond with your public certificate');
}
return $this;
}
/**
* Create encrypted buttons.
*
* Requires that the plugin is configured to do so, and that the key files
* are set up correctly. If an error is encountered, an empty string
* is returned so the caller can proceed with an un-encrypted button.
*
* @since version 0.4.0
* @param array $fields Array of data to encrypt into buttons
* @return string Encrypted_value, or empty string on error
*/
private function _encButton($fields)
{
global $_CONF, $_PP_CONF;
// Make sure button encryption is enabled and needed values are set
if ($this->config['encrypt'] != 1 || empty($this->config['prv_key']) || empty($this->config['pub_key']) || empty($this->config['pp_cert']) || $this->cert_id == '') {
return '';
}
// Now check that the files exist and can be read
foreach (array('prv_key', 'pub_key', 'pp_cert') as $idx => $name) {
if (!is_file($this->config[$name]) || !is_readable($this->config[$name])) {
return '';
}
}
// Create a temporary file to begin storing our data. If this fails,
// then return.
$dataFile = tempnam($_PP_CONF['tmpdir'], 'data');
if (!is_writable($dataFile)) {
return '';
}
$plainText = '';
$signedText = array();
$encText = '';
$pub_key = @openssl_x509_read(file_get_contents($this->config['pub_key']));
if (!$pub_key) {
COM_errorLog("Failed reading public key from {$this->config['pub_key']}", 1);
return '';
}
$prv_key = @openssl_get_privatekey(file_get_contents($this->config['prv_key']));
if (!$prv_key) {
COM_errorLog("Failed reading private key from {$this->config['prv_key']}", 1);
return '';
}
$pp_cert = @openssl_x509_read(file_get_contents($this->config['pp_cert']));
if (!$pp_cert) {
COM_errorLog("Failed reading PayPal certificate from {$this->config['pp_cert']}", 1);
return '';
}
// Make sure this key and certificate belong together
if (!openssl_x509_check_private_key($pub_key, $prv_key)) {
COM_errorLog("Mismatched private & public keys", 1);
return '';
}
// Start off the form data with the PayPal certificate ID
$plainText .= "cert_id=" . $this->cert_id;
// Create the form data by separating each value set by a new line
// Make sure that required fields are available. We assume that the
// item_number, item_name and amount are in.
if (!isset($fields['business'])) {
$fields['business'] = $this->receiver_email;
}
if (!isset($fields['currency_code'])) {
$fields['currency_code'] = $this->currency_code;
}
foreach ($fields as $key => $value) {
$plainText .= "\n{$key}={$value}";
}
// First create a file for storing the plain text values
$fh = fopen($dataFile . '_plain.txt', 'wb');
if ($fh) {
fwrite($fh, $plainText);
} else {
return '';
}
@fclose($fh);
// Now sign the plaintext values into the signed file
//$fh = fopen($dataFile . "_signed.txt", "w+");
if (!openssl_pkcs7_sign($dataFile . '_plain.txt', $dataFile . '_signed.txt', $pub_key, $prv_key, array(), PKCS7_BINARY)) {
return '';
}
// Parse the signed file between the header and content
$signedText = explode("\n\n", file_get_contents($dataFile . '_signed.txt'));
// Save only the content but base64 decode it first
$fh = fopen($dataFile . '_signed.txt', 'wb');
if ($fh) {
fwrite($fh, base64_decode($signedText[1]));
} else {
return '';
}
@fclose($fh);
// Now encrypt the signed file we just wrote
if (!openssl_pkcs7_encrypt($dataFile . '_signed.txt', $dataFile . '_enc.txt', $pp_cert, array(), PKCS7_BINARY)) {
return '';
}
// Parse the encrypted file between header and content
$encryptedData = explode("\n\n", file_get_contents($dataFile . "_enc.txt"));
$encText = $encryptedData[1];
// Delete all of our temporary files
@unlink($dataFile);
@unlink($dataFile . "_plain.txt");
//.........这里部分代码省略.........
//.........这里部分代码省略.........
}
if (count($ca) > 1) {
$m = 'This certificate cannot be imported because multiple possible ' . 'signers exist.';
return $m;
}
$caId = isset($ca[0]['Id']) ? $ca[0]['Id'] : false;
if (!is_numeric($caId) or $caId < 1) {
return 'Failed to locate issuing CA id.';
}
// Validate expiration date of CA cert. Only warn if the expiration dates
// don't jive.
$this->ca->resetProperties();
if ($this->ca->populateFromDb($caId) === false) {
return 'Failed to locate issuer information.';
}
$caValidTo = $this->ca->getProperty('ValidTo');
if (substr($validTo, 0, 10) > substr($caValidTo, 0, 10)) {
$m = 'WARNING: The certificate expiration date is invalid, the issuer ' . 'certficate expires ' . $caValidTo . ', this certificate expires ' . $validTo . '.';
$this->html->errorMsgSet($m);
}
// Determine the last serial number issued by the ca in case the
// serial number of the current certificate is higher and we need
// to bump the ca last serial issued.
$caLastSerial = $this->ca->getLastSerialIssued($caId);
if ($caLastSerial === false or !is_numeric($caLastSerial)) {
return 'Failed to determine CA last serial issued.';
}
// Validate the private key
if (is_string($privKey)) {
$pKey = openssl_pkey_get_private($privKey, $passPhrase);
if ($pKey === false) {
return 'Private key or password is invalid.';
}
if (!openssl_x509_check_private_key($pemCert, $pKey)) {
return 'Private key does not belong to cert.';
}
}
// Did they include a csr?
if (is_string($certRequest)) {
$csrPubKey = openssl_csr_get_public_key($certRequest);
if ($csrPubKey === false) {
return 'Failed to extract public key from CSR.';
}
if (openssl_pkey_get_details($pubKeyRes) !== openssl_pkey_get_details($csrPubKey)) {
return 'CSR and cert do not match.';
}
}
// Import the cert into the database
$this->server->resetProperties();
// required properties
$this->server->setProperty('Certificate', $pemCert);
$this->server->setProperty('CommonName', implode("\n", $pc['certificate']['subject']['CommonName']));
$this->server->setProperty('CreateDate', 'now()');
$this->server->setProperty('Description', 'imported');
$this->server->setProperty('FingerprintMD5', $pc['fingerprints']['md5']);
$this->server->setProperty('FingerprintSHA1', $pc['fingerprints']['sha1']);
$this->server->setProperty('ParentId', $caId);
$this->server->setProperty('PrivateKey', $privKey);
$this->server->setProperty('PublicKey', $pubKey);
$this->server->setProperty('SerialNumber', $serialNumber);
$this->server->setProperty('ValidFrom', $validFrom);
$this->server->setProperty('ValidTo', $validTo);
// optional properties
if (is_string($certRequest)) {
$this->server->setProperty('CSR', $certRequest);
}
请发表评论