1<?php 2 3class CertificateGenerator 4{ 5 const CONFIG = __DIR__. DIRECTORY_SEPARATOR . 'openssl.cnf'; 6 7 /** @var resource */ 8 private $ca; 9 10 /** @var resource */ 11 private $caKey; 12 13 /** @var resource|null */ 14 private $lastCert; 15 16 /** @var resource|null */ 17 private $lastKey; 18 19 public function __construct() 20 { 21 if (!extension_loaded('openssl')) { 22 throw new RuntimeException( 23 'openssl extension must be loaded to generate certificates' 24 ); 25 } 26 $this->generateCa(); 27 } 28 29 /** 30 * @param int|null $keyLength 31 * @return resource 32 */ 33 private static function generateKey($keyLength = null) 34 { 35 if (null === $keyLength) { 36 $keyLength = 2048; 37 } 38 39 return openssl_pkey_new([ 40 'private_key_bits' => $keyLength, 41 'private_key_type' => OPENSSL_KEYTYPE_RSA, 42 'encrypt_key' => false, 43 ]); 44 } 45 46 private function generateCa() 47 { 48 $this->caKey = self::generateKey(); 49 $dn = [ 50 'countryName' => 'GB', 51 'stateOrProvinceName' => 'Berkshire', 52 'localityName' => 'Newbury', 53 'organizationName' => 'Example Certificate Authority', 54 'commonName' => 'CA for PHP Tests' 55 ]; 56 57 $this->ca = openssl_csr_sign( 58 openssl_csr_new( 59 $dn, 60 $this->caKey, 61 [ 62 'x509_extensions' => 'v3_ca', 63 'config' => self::CONFIG, 64 ] 65 ), 66 null, 67 $this->caKey, 68 2 69 ); 70 } 71 72 public function getCaCert() 73 { 74 $output = ''; 75 openssl_x509_export($this->ca, $output); 76 77 return $output; 78 } 79 80 public function saveCaCert($file) 81 { 82 openssl_x509_export_to_file($this->ca, $file); 83 } 84 85 public function saveNewCertAsFileWithKey($commonNameForCert, $file, $keyLength = null) 86 { 87 $dn = [ 88 'countryName' => 'BY', 89 'stateOrProvinceName' => 'Minsk', 90 'localityName' => 'Minsk', 91 'organizationName' => 'Example Org', 92 'commonName' => $commonNameForCert, 93 ]; 94 95 $this->lastKey = self::generateKey($keyLength); 96 $this->lastCert = openssl_csr_sign( 97 openssl_csr_new($dn, $this->lastKey, ['req_extensions' => 'v3_req']), 98 $this->ca, 99 $this->caKey, 100 2 101 ); 102 103 $certText = ''; 104 openssl_x509_export($this->lastCert, $certText); 105 106 $keyText = ''; 107 openssl_pkey_export($this->lastKey, $keyText); 108 109 file_put_contents($file, $certText . PHP_EOL . $keyText); 110 } 111 112 public function getCertDigest($algo) 113 { 114 return openssl_x509_fingerprint($this->lastCert, $algo); 115 } 116} 117