923 lines
23 KiB
PHP
923 lines
23 KiB
PHP
<?php
|
||
|
||
trait cmpOpenSSLTrait {
|
||
var $cmpOpenSSLVersion = "20240126";
|
||
|
||
var $caDN = NULL ;
|
||
|
||
var $caPub = NULL ;
|
||
var $caPubPEM = "" ;
|
||
var $caPubFile = "" ;
|
||
|
||
var $caPrv = NULL ;
|
||
var $caPrvPEM = "" ;
|
||
var $caPrvFile = "" ;
|
||
|
||
var $caCrt = NULL ;
|
||
var $caCrtPEM = "" ;
|
||
var $caCrtFile = "" ;
|
||
|
||
|
||
var $cliDN = NULL ;
|
||
|
||
var $cliPub = NULL ;
|
||
var $cliPubPEM = "" ;
|
||
var $cliPubFile = "" ;
|
||
|
||
var $cliPrv = NULL ;
|
||
var $cliPrvPEM = "" ;
|
||
var $cliPrvFile = "" ;
|
||
|
||
var $cliCrt = NULL ;
|
||
var $cliCrtPEM = "" ;
|
||
var $cliCrtFile = "" ;
|
||
|
||
var $cmpOpenSslConf = array() ;
|
||
|
||
function cmpOpenSslConfSetDefault() {
|
||
$claver = __CLASS__ . "-" . $this->cmpOpenSSLVersion;
|
||
|
||
$this->cmpOpenSslConf = array (
|
||
"GLOBAL" => array (
|
||
"oid_section" => "OIDs",
|
||
),
|
||
"OIDs" => array (
|
||
"cmpExtOid" => "1.2.3.20190828",
|
||
"certificateTemplateName" => "\${cmpExtOid}.1",
|
||
),
|
||
"ca" => array (
|
||
"default_ca" => "cmp_ca",
|
||
),
|
||
"cmp_ca" => array (
|
||
"dir" => ".",
|
||
"certs" => "\$dir",
|
||
"crl_dir" => "\$dir}",
|
||
"database" => "\$dir/index.txt",
|
||
"new_certs_dir" => "\$dir",
|
||
"serial" => "\$dir/serial",
|
||
"crl" => "\$dir/crl.pem",
|
||
"certificate" => "\$dir/ca.crt",
|
||
"private_key" => "\$dir/ca.key",
|
||
"RANDFILE" => "\$dir/.rand",
|
||
"x509_extensions" => "cmp_x509_ext_basic",
|
||
"crl_extensions" => "cmp_crl_ext",
|
||
"default_days" => 3650,
|
||
"default_crl_days" => 30,
|
||
"default_md" => "sha256",
|
||
"preserve" => "no",
|
||
"policy" => "cmp_policy_anything",
|
||
),
|
||
"cmp_policy_anything" => array (
|
||
"countryName" => "optional",
|
||
"stateOrProvinceName" => "optional",
|
||
"localityName" => "optional",
|
||
"organizationName" => "optional",
|
||
"organizationalUnitName" => "optional",
|
||
"commonName" => "supplied",
|
||
"name" => "optional",
|
||
"emailAddress" => "optional",
|
||
),
|
||
"req" => array (
|
||
"default_bits" => 2048,
|
||
"default_keyfile" => "privkey.pem",
|
||
"default_md" => "sha256",
|
||
"distinguished_name" => "cmp_dst_ext",
|
||
"x509_extensions" => "cmp_x509_ext_rsa",
|
||
"req_extensions" => "cmp_req_ext_v3",
|
||
),
|
||
"cmp_dst_ext" => array (
|
||
"commonName" => "Common Name (eg: your user, host, or server name)",
|
||
"commonName_max" => 64,
|
||
"commonName_default" => $claver . "-commonName_default",
|
||
// "certificateTemplateName" => $claver , // "-certificateTemplateName",
|
||
"certificateTemplateName_default" => $claver ,
|
||
),
|
||
"cmp_req_ext_v3" => array (
|
||
"certificateTemplateName" => "ASN1:PRINTABLESTRING:CustomUserOffline",
|
||
),
|
||
"cmp_org" => array (
|
||
"countryName" => "Country Name (2 letter code)",
|
||
"countryName_default" => "RU",
|
||
"countryName_min" => 2,
|
||
"countryName_max" => 2,
|
||
|
||
"stateOrProvinceName" => "State or Province Name (full name)",
|
||
"stateOrProvinceName_default" => $claver . "-stateOrProvinceName_default",
|
||
|
||
"localityName" => "Locality Name (eg, city)",
|
||
"localityName_default" => $claver . "-localityName_default",
|
||
|
||
"organizationName" => "Organization Name (eg, company)",
|
||
"organizationName_default" => $claver . "-organizationName_default",
|
||
|
||
"organizationalUnitName" => "Organizational Unit Name (eg, section)",
|
||
"organizationalUnitName_default" => $claver . "-organizationalUnitName_default",
|
||
|
||
"emailAddress" => "Email Address",
|
||
"emailAddress_default" => $claver . "@example.org",
|
||
"emailAddress_max" => 64,
|
||
),
|
||
"cmp_crl_ext" => array (
|
||
"authorityKeyIdentifier" => "keyid:always,issuer:always",
|
||
),
|
||
"cmp_x509_ext_basic" => array (
|
||
"basicConstraints" => "CA:FALSE",
|
||
"subjectKeyIdentifier" => "hash",
|
||
"authorityKeyIdentifier" => "keyid,issuer:always",
|
||
),
|
||
"cmp_x509_ext_rsa" => array (
|
||
"subjectKeyIdentifier" => "hash",
|
||
"authorityKeyIdentifier" => "keyid:always,issuer:always",
|
||
"basicConstraints" => "CA:true",
|
||
"keyUsage" => "cRLSign, keyCertSign",
|
||
),
|
||
"cmp_x509_ext_srv" => array (
|
||
"basicConstraints" => "CA:FALSE",
|
||
"nsCertType" => "server",
|
||
"nsComment" => "\"OpenSSL Generated Server Certificate\"",
|
||
"subjectKeyIdentifier" => "hash",
|
||
"authorityKeyIdentifier" => "keyid,issuer:always",
|
||
"extendedKeyUsage" => "serverAuth",
|
||
"keyUsage" => "digitalSignature, keyEncipherment",
|
||
),
|
||
"cmp_x509_ext_cli" => array (
|
||
"basicConstraints" => "CA:FALSE",
|
||
"nsCertType" => "client",
|
||
"nsComment" => "\"OpenSSL Generated Client Certificate\"",
|
||
"subjectKeyIdentifier" => "hash",
|
||
"authorityKeyIdentifier" => "keyid,issuer",
|
||
"keyUsage" => "critical, nonRepudiation, digitalSignature, keyEncipherment",
|
||
"extendedKeyUsage" => "clientAuth",
|
||
),
|
||
);
|
||
|
||
|
||
return true;
|
||
}
|
||
|
||
function cmpOpenSslConfTemp() {
|
||
$a = array();
|
||
|
||
if(!isset($this->cmpOpenSslConf["GLOBAL"])) {
|
||
$this->cmpOpenSslConfSetDefault();
|
||
}
|
||
|
||
if(!isset($this->cmpOpenSslConf["GLOBAL"])) {
|
||
throw new Exception("No GLOBAL section");
|
||
}
|
||
|
||
foreach($this->cmpOpenSslConf["GLOBAL"] as $key => $val) {
|
||
$a[] = "\t" . $key . "=" . $val . "";
|
||
}
|
||
|
||
foreach($this->cmpOpenSslConf as $sec => $prm) {
|
||
if($sec == "GLOBAL")
|
||
continue;
|
||
|
||
$a[] = "";
|
||
$a[] = "[" . $sec . "]";
|
||
|
||
foreach($prm as $key => $val) {
|
||
$a[] = "\t" . $key . " = " . $val . "";
|
||
}
|
||
}
|
||
|
||
$a[] = "";
|
||
|
||
$t = join("\n", $a);
|
||
|
||
|
||
$rand = mt_rand(100000, 999999);
|
||
|
||
$file = "/tmp/openssl-$rand.conf";
|
||
|
||
$w = @file_put_contents($file, $t);
|
||
|
||
if(!$w) {
|
||
throw new Exception("Can't write file '$file'");
|
||
}
|
||
|
||
return $file;
|
||
}
|
||
|
||
function cmpOpenSslConfRead($file) {
|
||
$t = file_get_contents($file);
|
||
|
||
$a = explode("\n", $t);
|
||
|
||
$sec = "GLOBAL";
|
||
$key = "";
|
||
$val = "";
|
||
$obj = array();
|
||
|
||
for($i = 0; $i < count($a); $i++) {
|
||
$a[$i] = trim($a[$i], "\n \t\r");
|
||
|
||
if(!$a[$i])
|
||
continue;
|
||
|
||
if(substr($a[$i], 0, 1) == "#")
|
||
continue;
|
||
|
||
$m = array();
|
||
$s = "";
|
||
|
||
if(preg_match("/^(.+)#.+$/", $a[$i], $m)) {
|
||
$s = trim($m[1], "\n \t\r");
|
||
}
|
||
else {
|
||
$s = $a[$i];
|
||
}
|
||
|
||
if(preg_match("/^\[(.+)\]$/", $a[$i], $m)) {
|
||
$sec = trim($m[1], "\n \t\r");
|
||
|
||
if(!isset($obj[$sec])) {
|
||
$obj[$sec] = array();
|
||
}
|
||
|
||
continue;
|
||
}
|
||
|
||
$b = explode("=", $s, 2);
|
||
|
||
$key = trim($b[0], "\n \t\r");
|
||
$val = trim($b[1], "\n \t\r");
|
||
|
||
// echo "STR: " . $sec . " === " . $key . " === " . $val . "\n";
|
||
|
||
$obj[$sec][$key] = $val;
|
||
}
|
||
|
||
$this->cmpOpenSslConf = $obj;
|
||
|
||
// var_export($obj);
|
||
|
||
return true;
|
||
}
|
||
|
||
function cmpOpenSslParm($parm, $key, $def = "") {
|
||
if(!is_array($parm))
|
||
return $def;
|
||
|
||
if(!isset($parm[$key]))
|
||
return $def;
|
||
|
||
return $parm[$key];
|
||
}
|
||
|
||
function cmpOpenSslParmConfSection($parm, $sec, &$out) {
|
||
if(!isset($this->cmpOpenSslConf[$sec])) {
|
||
;
|
||
}
|
||
|
||
foreach($this->cmpOpenSslConf[$sec] as $key => $val) {
|
||
$m = array();
|
||
|
||
if(!preg_match("/^(.+)_default$/", $key, $m))
|
||
continue;
|
||
|
||
$key = $m[1];
|
||
|
||
$out[$key] = $this->cmpOpenSslParm(
|
||
$parm,
|
||
$key,
|
||
$val
|
||
);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
function cmpOpenSslCertGetInfo($crt, $prv, &$out = null) {
|
||
$txtPub = "";
|
||
$txtPrv = "";
|
||
|
||
openssl_x509_export($crt , $txtPub, false );
|
||
openssl_pkey_export($prv , $txtPrv, NULL );
|
||
|
||
if(!$out)
|
||
$out = array();
|
||
|
||
$out["fingerprint"] = array(
|
||
"default" => @openssl_x509_fingerprint($crt),
|
||
"sha256" => @openssl_x509_fingerprint($crt, "sha256")
|
||
);
|
||
|
||
$out["err"] = array();
|
||
|
||
do {
|
||
$cert = @openssl_x509_parse($txtPub);
|
||
|
||
if(!$cert) {
|
||
$out["err"][] = array(__LINE__, openssl_error_string());
|
||
break;
|
||
}
|
||
|
||
if(!isset($cert["subject"])) {
|
||
$out["err"][] = array(__LINE__, "Invalid subject");
|
||
break;
|
||
}
|
||
|
||
if(!isset($cert["subject"]["CN"])) {
|
||
$out["err"][] = array(__LINE__, "Invalid subject CN");
|
||
break;
|
||
}
|
||
|
||
if(!isset($cert["extensions"])) {
|
||
$out["err"][] = array(__LINE__, "Invalid extensions");
|
||
break;
|
||
}
|
||
|
||
if(!isset($cert["extensions"]["authorityKeyIdentifier"])) {
|
||
$out["err"][] = array(__LINE__, "Invalid extensions authorityKeyIdentifier");
|
||
break;
|
||
}
|
||
|
||
if(!isset($cert["extensions"]["subjectKeyIdentifier"])) {
|
||
$out["err"][] = array(__LINE__, "Invalid extensions subjectKeyIdentifier");
|
||
break;
|
||
}
|
||
} while(0);
|
||
|
||
if($out["err"]) {
|
||
$this->d($out["err"]);
|
||
return NULL;
|
||
}
|
||
|
||
unset($out["err"]);
|
||
|
||
$nrmz = array( /* "A" => "a", "B" => "b", "C" => "c", "D" => "d", "E" => "e", "F" => "f", */ ":" => "");
|
||
|
||
do {
|
||
if(preg_match("/^[0-9A-F:]+$/", $cert["extensions"]["authorityKeyIdentifier"])) {
|
||
$certAuth = $cert["extensions"]["authorityKeyIdentifier"];
|
||
break;
|
||
}
|
||
|
||
$a = explode("\n", $cert["extensions"]["authorityKeyIdentifier"]);
|
||
$b = null;
|
||
$c = array();
|
||
|
||
for($i = 0; $i < count($a); $i++) {
|
||
$b = explode(":", $a[$i], 2);
|
||
$c[$b[0]] = $b[1];
|
||
}
|
||
|
||
// $this->d($c);
|
||
|
||
if(!isset($c["keyid"]) || !$c["keyid"]) {
|
||
$out["err"][] = array(__LINE__, "Invalid authorityKeyIdentifier: '". $cert["extensions"]["authorityKeyIdentifier"] ."'");
|
||
return NULL;
|
||
}
|
||
|
||
$certAuth = strtolower($c["keyid"]);
|
||
} while(0);
|
||
|
||
$certAuth = strtr($certAuth, $nrmz);
|
||
$certAuth = strtolower($certAuth);
|
||
|
||
$certSubj = $cert["extensions"]["subjectKeyIdentifier"];
|
||
$certSubj = strtr($certSubj, $nrmz);
|
||
$certSubj = strtolower($certSubj);
|
||
|
||
$out["certAuth" ] = $certAuth;
|
||
$out["validFrom"] = date("Y-m-d H:i:s", $cert["validFrom_time_t" ]);
|
||
$out["validTo" ] = date("Y-m-d H:i:s", $cert["validTo_time_t" ]);
|
||
$out["certSubj" ] = $certSubj;
|
||
$out["certCN" ] = $cert["subject"]["CN"];
|
||
$out["public" ] = $txtPub;
|
||
$out["private" ] = $txtPrv;
|
||
|
||
return $out;
|
||
}
|
||
|
||
function cmpOpenSslCaGen($parm, &$out = null) {
|
||
try {
|
||
$confFile = $this->cmpOpenSslConfTemp();
|
||
|
||
$digest_alg = $this->cmpOpenSslParm($parm, "digest_alg" , "sha256" );
|
||
$x509_extensions = $this->cmpOpenSslParm($parm, "x509_extensions" , "cmp_x509_ext_rsa" );
|
||
$days = $this->cmpOpenSslParm($parm, "days" , 365 );
|
||
$outfile = $this->cmpOpenSslParm($parm, "outfile" );
|
||
$serial = $this->cmpOpenSslParm($parm, "serial" , mt_rand(0, PHP_INT_MAX) );
|
||
|
||
$this->caDN = array();
|
||
|
||
$this->cmpOpenSslParmConfSection($parm, "cmp_org", $this->caDN);
|
||
$this->cmpOpenSslParmConfSection($parm, "cmp_dst_ext", $this->caDN);
|
||
|
||
if(!$this->caDN["commonName"]) {
|
||
throw new Exception("Empty commonName");
|
||
}
|
||
|
||
$confFile = $this->cmpOpenSslConfTemp();
|
||
|
||
$pcsrs = array(
|
||
"digest_alg" => $digest_alg ,
|
||
);
|
||
|
||
$pcsrn = array(
|
||
"config" => $confFile ,
|
||
"digest_alg" => $digest_alg ,
|
||
"x509_extensions" => $x509_extensions ,
|
||
);
|
||
|
||
$ppkey = array(
|
||
"config" => $confFile ,
|
||
"encrypt_key" => $this->cmpOpenSslParm($parm, "encrypt_key" , false ),
|
||
"private_key_type" => $this->cmpOpenSslParm($parm, "private_key_type" , OPENSSL_KEYTYPE_RSA ),
|
||
"private_key_bits" => $this->cmpOpenSslParm($parm, "private_key_bits" , 4096 ),
|
||
);
|
||
|
||
$this->caPrv = openssl_pkey_new($ppkey);
|
||
|
||
if(!$this->caPrv) {
|
||
throw new Exception("openssl_pkey_new: " . openssl_error_string());
|
||
}
|
||
|
||
$csr = openssl_csr_new($this->caDN, $this->caPrv, $pcsrn);
|
||
|
||
if(!$csr) {
|
||
throw new Exception("openssl_csr_new: " . openssl_error_string());
|
||
}
|
||
|
||
// Создание самоподписанного сертификата со сроком жизни $days дней
|
||
$this->caCrt = openssl_csr_sign($csr, null, $this->caPrv, $days, $pcsrs, $serial);
|
||
|
||
if(!$this->caCrt) {
|
||
throw new Exception("openssl_csr_sign: " . openssl_error_string());
|
||
}
|
||
|
||
@unlink($confFile);
|
||
} catch(Exception|Throwable $e) {
|
||
@unlink($confFile);
|
||
|
||
$this->e($e);
|
||
|
||
return NULL;
|
||
}
|
||
|
||
$this->cmpOpenSslCertGetInfo($this->caCrt, $this->caPrv, $out);
|
||
|
||
$txtPub = "";
|
||
$txtPrv = "";
|
||
|
||
openssl_x509_export($this->caCrt , $txtPub, false );
|
||
openssl_pkey_export($this->caPrv , $txtPrv, NULL );
|
||
|
||
if($out !== null) {
|
||
if(!$this->cmpOpenSslCertGetInfo($this->caCrt, $this->caPrv, $out))
|
||
return NULL;
|
||
}
|
||
|
||
if($outfile) {
|
||
openssl_x509_export_to_file($this->caCrt , "$outfile.crt" );
|
||
openssl_pkey_export_to_file($this->caPrv , "$outfile.prv" , NULL );
|
||
}
|
||
|
||
$this->caPub = openssl_pkey_get_public($this->caCrt);
|
||
|
||
if(!$this->caPub) {
|
||
throw new Exception("openssl_pkey_get_public: " . openssl_error_string());
|
||
}
|
||
|
||
// var_export($csrout);
|
||
// echo "\n";
|
||
|
||
return true;
|
||
}
|
||
|
||
function cmpOpenSslCaCertFromFile($file) {
|
||
// var_dump(openssl_get_cert_locations());
|
||
|
||
$this->caCrtFile = $file;
|
||
|
||
$text = @file_get_contents($file);
|
||
|
||
if($this->cmpOpenSslCaCertFromText($text)) {
|
||
$this->caCrtFile = $file;
|
||
return true;
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
function cmpOpenSslCaCertFromText($text) {
|
||
$this->caCrtFile = "";
|
||
|
||
$this->caCrtPEM = $text;
|
||
|
||
if(!$this->caCrtPEM) {
|
||
throw new Exception("Invalid CA text");
|
||
}
|
||
|
||
// openssl_get_privatekey()
|
||
$this->caCrt = openssl_x509_read( $this->caCrtPEM );
|
||
|
||
if(!$this->caCrt) {
|
||
throw new Exception("openssl_x509_read: " . openssl_error_string());
|
||
}
|
||
|
||
// openssl_x509_parse(file_get_contents($file));
|
||
|
||
$this->caPub = openssl_pkey_get_public($this->caCrt);
|
||
|
||
if(!$this->caPub) {
|
||
throw new Exception("openssl_pkey_get_public: " . openssl_error_string());
|
||
}
|
||
|
||
$pkey = openssl_pkey_get_details($this->caPub);
|
||
|
||
if(!$pkey) {
|
||
throw new Exception("openssl_pkey_get_details: " . openssl_error_string());
|
||
}
|
||
|
||
$this->caPubPEM = $pkey["key"];
|
||
|
||
$this->caPub = openssl_pkey_get_public($this->caPubPEM);
|
||
|
||
if(!$this->caPub) {
|
||
throw new Exception("openssl_pkey_get_public: " . openssl_error_string());
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
function cmpOpenSslCaPrivFromFile($file, $pass = NULL) {
|
||
$this->caPrvFile = $file;
|
||
|
||
$text = @file_get_contents($file);
|
||
|
||
if($this->cmpOpenSslCaPrivFromText($text, $pass)) {
|
||
$this->caPrvFile = $file;
|
||
return true;
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
function cmpOpenSslCaPrivFromText($text, $pass = NULL) {
|
||
$this->caPrvFile = "";
|
||
/*
|
||
if(@$file)
|
||
$this->caPrvPEM = @file_get_contents($file);
|
||
else
|
||
$this->caPrvPEM = "";
|
||
|
||
if(!$text) {
|
||
$this->e(__LINE__, "Invalid CA private key text");
|
||
return NULL;
|
||
}
|
||
*/
|
||
$this->caPrvPEM = $text;
|
||
|
||
$this->caPrv = openssl_pkey_get_private($this->caPrvPEM, $pass);
|
||
|
||
if(!$this->caPrv) {
|
||
throw new Exception("openssl_pkey_get_private: " . openssl_error_string());
|
||
}
|
||
|
||
$sign = "";
|
||
$test = "test-test";
|
||
|
||
//Вычисляем подпись
|
||
if(!openssl_sign($test, $sign, $this->caPrv, "sha1WithRSAEncryption")) {
|
||
throw new Exception("openssl_sign: " . openssl_error_string());
|
||
}
|
||
|
||
switch( openssl_verify($test, $sign, $this->caPub, OPENSSL_ALGO_SHA1) ) {
|
||
case 1:
|
||
// echo "корректна\n";
|
||
return true;
|
||
|
||
case 0:
|
||
// echo "некорректна\n";
|
||
$this->e("Incorrect CA private key");
|
||
return NULL;
|
||
|
||
case -1:
|
||
$this->e(openssl_error_string());
|
||
return NULL;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
function cmpOpenSslCertGen($parm, &$out = null) {
|
||
try {
|
||
$confFile = $this->cmpOpenSslConfTemp();
|
||
|
||
$digest_alg = $this->cmpOpenSslParm($parm, "digest_alg" , "sha256" );
|
||
$x509_extensions = $this->cmpOpenSslParm($parm, "x509_extensions" , "" );
|
||
$days = $this->cmpOpenSslParm($parm, "days" , 365 );
|
||
$outfile = $this->cmpOpenSslParm($parm, "outfile" );
|
||
$serial = $this->cmpOpenSslParm($parm, "serial" , mt_rand(0, PHP_INT_MAX) );
|
||
|
||
$this->cliDN = array();
|
||
|
||
$this->cmpOpenSslParmConfSection($parm, "cmp_org", $this->cliDN);
|
||
$this->cmpOpenSslParmConfSection($parm, "cmp_dst_ext", $this->cliDN);
|
||
|
||
if(!$this->cliDN["commonName"]) {
|
||
throw new Exception("Empty commonName");
|
||
}
|
||
|
||
if(!$x509_extensions) {
|
||
throw new Exception("Empty x509_extensions");
|
||
}
|
||
|
||
$pcsrn = array(
|
||
"config" => $confFile ,
|
||
"digest_alg" => $digest_alg ,
|
||
"x509_extensions" => $x509_extensions ,
|
||
);
|
||
|
||
$ppkey = array(
|
||
"config" => $confFile ,
|
||
"encrypt_key" => $this->cmpOpenSslParm($parm, "encrypt_key" , false ),
|
||
"private_key_type" => $this->cmpOpenSslParm($parm, "private_key_type" , OPENSSL_KEYTYPE_RSA ),
|
||
"private_key_bits" => $this->cmpOpenSslParm($parm, "private_key_bits" , 4096 ),
|
||
);
|
||
|
||
$this->cliPrv = openssl_pkey_new($ppkey);
|
||
|
||
if(!$this->cliPrv) {
|
||
throw new Exception("openssl_csr_new: " . openssl_error_string());
|
||
}
|
||
|
||
$csr = @openssl_csr_new($this->cliDN, $this->cliPrv, $pcsrn);
|
||
|
||
if(!$csr) {
|
||
throw new Exception("openssl_csr_new: " . openssl_error_string());
|
||
}
|
||
|
||
$this->cliCrt = openssl_csr_sign($csr, $this->caCrt, $this->caPrv, $days, $pcsrn, $serial);
|
||
|
||
if(!$this->cliCrt) {
|
||
throw new Exception("openssl_csr_sign: " . openssl_error_string());
|
||
}
|
||
|
||
@unlink($confFile);
|
||
} catch(Exception|Throwable $e) {
|
||
@unlink($confFile);
|
||
|
||
$this->e($e);
|
||
|
||
return NULL;
|
||
}
|
||
|
||
$txtPub = "";
|
||
$txtPrv = "";
|
||
|
||
openssl_x509_export($this->cliCrt, $txtPub, false );
|
||
openssl_pkey_export($this->cliPrv, $txtPrv, NULL );
|
||
|
||
if($out !== null) {
|
||
if(!$this->cmpOpenSslCertGetInfo($this->cliCrt, $this->cliPrv, $out))
|
||
return NULL;
|
||
}
|
||
|
||
if($outfile) {
|
||
openssl_x509_export_to_file($this->cliCrt , "$outfile.crt" );
|
||
openssl_pkey_export_to_file($this->cliPrv , "$outfile.prv" , NULL );
|
||
}
|
||
|
||
$this->cliPub = openssl_pkey_get_public($this->cliCrt);
|
||
|
||
if(!$this->cliPub) {
|
||
throw new Exception("openssl_pkey_get_public: " . openssl_error_string());
|
||
}
|
||
|
||
// var_export($csrout);
|
||
// echo "\n";
|
||
|
||
return true;
|
||
}
|
||
|
||
function cmpOpenSslCertClientGen($parm = NULL, &$out = null) {
|
||
$parm["x509_extensions"] = "cmp_x509_ext_cli";
|
||
return $this->cmpOpenSslCertGen($parm, $out);
|
||
}
|
||
|
||
function cmpOpenSslCertServerGen($parm = NULL, &$out = null) {
|
||
$parm["x509_extensions"] = "cmp_x509_ext_srv";
|
||
return $this->cmpOpenSslCertGen($parm, $out);
|
||
}
|
||
|
||
function cmpOpenSslGenDh($bits = 2048) {
|
||
$a = array(
|
||
"openssl",
|
||
"dhparam",
|
||
$bits
|
||
);
|
||
|
||
if(!method_exists($this, "cmpSysExec")) {
|
||
$this->d("Invalid method cmpSysExec");
|
||
return null;
|
||
}
|
||
|
||
$arr = $this->cmpSysExec($a, array("return" => "outarr", "noerror" => 1));
|
||
|
||
if(0) {
|
||
var_export($arr);
|
||
echo "\n";
|
||
}
|
||
|
||
if($arr[0] != "-----BEGIN DH PARAMETERS-----") {
|
||
$this->d("Invalid first string");
|
||
return null;
|
||
}
|
||
|
||
$lst = count($arr) - 2;
|
||
|
||
if($arr[$lst] != "-----END DH PARAMETERS-----") {
|
||
$this->d("Invalid last string");
|
||
return null;
|
||
}
|
||
|
||
return join("\n", $arr);
|
||
}
|
||
|
||
function cmpOpenVpnGenTa() {
|
||
$a = array(
|
||
"openvpn",
|
||
"--genkey",
|
||
// Valid keytype arguments are:
|
||
"secret" // Standard OpenVPN shared secret keys
|
||
// "tls-crypt" // Alias for secret
|
||
// "tls-auth" // Alias for secret
|
||
);
|
||
|
||
$arr = $this->cmpSysExec($a, array("return" => "outarr", "noerror" => 1));
|
||
|
||
if(0) {
|
||
var_export($arr);
|
||
echo "\n";
|
||
}
|
||
|
||
$idx = array();
|
||
|
||
for($i = 0; $i < count($arr); $i++) {
|
||
if($arr[$i] == "-----BEGIN OpenVPN Static key V1-----") {
|
||
$idx["bgn"] = $i;
|
||
continue;
|
||
}
|
||
|
||
if($arr[$i] == "-----END OpenVPN Static key V1-----") {
|
||
$idx["end"] = $i;
|
||
continue;
|
||
}
|
||
}
|
||
|
||
if(!isset($idx["bgn"]) || !isset($idx["end"])) {
|
||
$this->d("Invalid output key");
|
||
return null;
|
||
}
|
||
|
||
return join("\n", $arr);
|
||
}
|
||
|
||
function cmpOpenSslGenCrl($caCrtText, $caPrvText, $outCrlFile) {
|
||
$now = date("Y-m-d H:i:s");
|
||
$dir = "/tmp/tmp-ca-dir-" . md5("tmp-ca-dir-" . $now);
|
||
|
||
if(!mkdir($dir))
|
||
return null;
|
||
|
||
$caCrtFile = $dir . "/ca.crt";
|
||
$caPrvFile = $dir . "/ca.prv";
|
||
$indexFile = $dir . "/index.txt";
|
||
$serialFile = $dir . "/serial";
|
||
|
||
file_put_contents($caCrtFile, $caCrtText);
|
||
file_put_contents($caPrvFile, $caPrvText);
|
||
|
||
file_put_contents($indexFile, "");
|
||
file_put_contents($serialFile, "");
|
||
|
||
$a = array(
|
||
"cd" ,
|
||
$dir ,
|
||
["asis", "&&"] ,
|
||
"openssl" ,
|
||
"ca" ,
|
||
"-config" ,
|
||
"65-openssl.cnf" ,
|
||
"-gencrl" ,
|
||
"-out" ,
|
||
$outCrlFile ,
|
||
"-cert" ,
|
||
$caCrtFile ,
|
||
"-keyfile" ,
|
||
$caPrvFile ,
|
||
);
|
||
|
||
$arr = $this->cmpSysExec($a, array(/* "return" => "outarr", "noerror" => 1 */));
|
||
|
||
unlink($caCrtFile);
|
||
unlink($caPrvFile);
|
||
unlink($indexFile);
|
||
unlink($serialFile);
|
||
|
||
if(!rmdir($dir)) {
|
||
$this->d("Can't remove directory '$dir'");
|
||
}
|
||
|
||
if(1) {
|
||
var_export($arr);
|
||
echo "\n";
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
function cmpOpenSslAddCrl($caCrtText, $caPrvText, $outCrlFile, $sjCrtText) {
|
||
$now = date("Y-m-d H:i:s");
|
||
$dir = "/tmp/tmp-ca-dir-" . md5("tmp-ca-dir-" /* . $now . "-" . mt_rand(10000, 99999) */ );
|
||
|
||
if(!mkdir($dir)) {
|
||
;
|
||
// return null;
|
||
}
|
||
|
||
$caCrtFile = $dir . "/ca.crt";
|
||
$caPrvFile = $dir . "/ca.prv";
|
||
$indexFile = $dir . "/index.txt";
|
||
$serialFile= $dir . "/serial";
|
||
$sjCrtFile = $dir . "/cert.pem";
|
||
|
||
$crlFile = $dir . "/crl.pem";
|
||
|
||
if(!is_file($caCrtFile))
|
||
file_put_contents($caCrtFile, $caCrtText);
|
||
if(!is_file($caPrvFile))
|
||
file_put_contents($caPrvFile, $caPrvText);
|
||
|
||
file_put_contents($sjCrtFile, $sjCrtText);
|
||
|
||
if(!is_file($indexFile))
|
||
file_put_contents($indexFile, "");
|
||
if(!is_file($serialFile))
|
||
file_put_contents($serialFile, "");
|
||
|
||
if(is_file($outCrlFile)) {
|
||
copy($outCrlFile, $crlFile);
|
||
// $a[] = "-in";
|
||
// $a[] = $outCrlFile;
|
||
$this->d("Add IN");
|
||
}
|
||
|
||
$a = array(
|
||
"cd" ,
|
||
$dir ,
|
||
["asis", "&&"] ,
|
||
"openssl" ,
|
||
"ca" ,
|
||
"-config" ,
|
||
"65-openssl.cnf" ,
|
||
"-revoke" ,
|
||
$sjCrtFile ,
|
||
// "-out" ,
|
||
// $outCrlFile ,
|
||
"-cert" ,
|
||
$caCrtFile ,
|
||
"-keyfile" ,
|
||
$caPrvFile ,
|
||
);
|
||
|
||
// $a[] = "-in";
|
||
// $a[] = $outCrlFile;
|
||
|
||
$arr = $this->cmpSysExec($a, array(/* "return" => "outarr", "noerror" => 1 */));
|
||
|
||
if(1) {
|
||
var_export($arr);
|
||
echo "\n";
|
||
}
|
||
|
||
// unlink($caCrtFile);
|
||
// unlink($caPrvFile);
|
||
// unlink($sjCrtFile);
|
||
// unlink($indexFile);
|
||
// unlink($serialFile);
|
||
|
||
if(is_file($crlFile)) {
|
||
copy($crlFile, $outCrlFile);
|
||
// unlink($crlFile);
|
||
}
|
||
|
||
// unlink($dir . "/index.txt.attr");
|
||
// unlink($dir . "/index.txt.old");
|
||
|
||
// if(!rmdir($dir)) {
|
||
// $this->d("Can't remove directory '$dir'");
|
||
// }
|
||
|
||
return;
|
||
}
|
||
|
||
// trait
|
||
}
|