PHP操作证书

来源:互联网 发布:设计模式php 编辑:程序博客网 时间:2024/05/01 06:02
<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
 * Certificate Class
 *
 * 处理证书:获取证书信息,匹配证书密钥等
 *
 * @package CodeIgniter
 * @subpackage Libraries
 * @category Libraries
 */
define("CERT_DER", 0);
define("CERT_PEM", 1);
define('CHECK_HEADER_LEN', 100);


class Certificate {
/**
* 字符串日期转换为时间戳后再转化为存储到数据库的形式
*
* @param $date_time 字符串日期
* @return 时间戳
*/
private function get_timestamp($date_time)
{
$date = new DateTime($date_time);
$time = $date->format('U');
return date('Y-m-d H:i:s', $time);
}

/**
* 判断证书格式类型 DER 或 PEM
*
* @param $file 证书路径
* @return CERT_PEM => PEM格式 CERT_DER => DER格式
*/
public function judge_inform($file)
{
if (! file_exists($file))
{
//show_error('input file is not exists');
return ERROR_ERR;
}

// 根据证书前面数据判断文件格式
$fp = fopen($file, 'r');
while (! feof($fp))
{
$buf = fread($fp, CHECK_HEADER_LEN);
for ($i=0; $i<strlen($buf); $i++)
{
if (ord($buf[$i]) == 0)// 判断字符
{
return CERT_DER;
}
}
}

return CERT_PEM;
}

/**
* 转换证书格式类型 DER转PEM
*
* @param $infile 证书路径
* @param $outfile 转换后的证书路径
* @return 转换是否成功 ERROR_ERR 失败, ERROR_SUC成功
*/
public function change_to_pem($infile, $outfile)
{
if (! file_exists($infile))
{
//show_error("input file is not exists");
return ERROR_ERR;
}

// openssl 转换DER格式证书为PEM格式证书
$cmd = 'openssl x509 -inform DER -outform PEM -in '.
escapeshellarg($infile).' -out '.escapeshellarg($outfile);
if (system($cmd) === false)
{
return ERROR_ERR;
}
return ERROR_SUC;
}

/**
* 获取证书过期时间,开始时间
*
* @param $file 证书路径
* @return ERROR_ERR => 失败,其他 => 开始时间
*/
public function get_not_before($file)
{
if (! file_exists($file))
{
//show_error('input file is not exists');
return ERROR_ERR;
}

// 获取证书开始时间
$cmd = 'openssl x509 -startdate -in '.escapeshellarg($file).' -noout';
$fp = popen($cmd, "r");
$ctx = fgets($fp);
pclose($fp);


$not_before = substr(trim($ctx), strlen('notBefore='));
return $this->get_timestamp($not_before);
}

/**
* 获取证书过期时间,结束时间
*
* @param $file 证书路径
* @return ERROR_ERR => 失败,其他 => 结束时间
*/
public function get_not_after($file)
{
if (! file_exists($file))
{
//show_error('input file is not exists');
return ERROR_ERR;
}

// 获取证书结束时间
$cmd = 'openssl x509 -enddate -in '.escapeshellarg($file).' -noout';
$fp = popen($cmd, 'r');
$ctx = fgets($fp);
pclose($fp);

$not_after = substr(trim($ctx), strlen('notAfter='));
return $this->get_timestamp($not_after);
}

/**
* 获取证书序列号
*
* @param $file 证书路径
* @return ERROR_ERR => 失败,其他 => 序列号
*/
public function get_serial_num($file)
{
if (! file_exists($file))
{
//show_error('input file is not exists');
return ERROR_ERR;
}

// 获取证书序列号
$cmd = 'openssl x509 -serial -in '.escapeshellarg($file).' -noout';
$fp = popen($cmd, 'r');
$ctx = fgets($fp);
pclose($fp);

$serial_num = substr(trim($ctx), strlen('serial='));
return $serial_num;
}

/**
* 获取证书签发者
*
* @param $file 证书路径
* @return ERROR_ERR => 失败,其他 => 签发者
*/
public function get_issuer($file)
{
if (! file_exists($file))
{
//show_error('input file is not exists');
return ERROR_ERR;
}

// 获取证书签发者
$cmd = 'openssl x509 -issuer -in '.escapeshellarg($file).' -noout';
$fp = popen($cmd, 'r');
$ctx = fgets($fp);
pclose($fp);

$serial_num = substr(trim($ctx), strlen('issuer= '));
return $serial_num;
}

/**
* 获取主题信息
*
* @param $file 证书路径
* @return ERROR_ERR => 失败,其他 => 签发者
*/
public function get_subject($file)
{
if (! file_exists($file))
{
//show_error('input file is not exists');
return ERROR_ERR;
}

// 获取证书签发者
$cmd = 'openssl x509 -subject -in '.escapeshellarg($file).' -noout';
$fp = popen($cmd, 'r');
$ctx = fgets($fp);
pclose($fp);

$serial_num = substr(trim($ctx), strlen('subject= '));
return $serial_num;
}

/**
* 获取证书信息
*
* @param $file 证书路径
* @param[out] $info_arr 证书信息,包括过期时间,序列号,签发者
* @return ERROR_ERR => 失败,ERROR_SUC => 成功
*/
public function get_cert_info($file, &$info_arr)
{
if (! file_exists($file))
{
//show_error('input file is not exists');
return ERROR_ERR;
}

// 临时文件
$tmp_file = pathinfo($file, PATHINFO_DIRNAME).'/'.gen_uniqid_name();
// 判断证书内容格式
if($this->judge_inform($file) == CERT_DER)
{
// 转换DER格式证书为PEM格式
$ret = $this->change_to_pem($file, $tmp_file);
if ($ret != ERROR_SUC)
{
return ERROR_ERR;
}
// 指向临时文件
$file = $tmp_file;
}

// 获取证书开始有效期,结束有效期,序列号,签发者,主题
$info_arr['not_before'] = $this->get_not_before($file);
$info_arr['not_after'] = $this->get_not_after($file);
$info_arr['serial_num'] = $this->get_serial_num($file);
$info_arr['issuer'] = $this->get_issuer($file);
$info_arr['subject'] = $this->get_subject($file);

// 删除转换的临时文件
if (file_exists($tmp_file))
{
system("rm -f ".escapeshellarg($tmp_file));
}

return ERROR_SUC;
}

/**
* 检测证书KEY密码是否正确
*
* @param $file 证书KEY路径
* @param $passwd 证书KEY密码
* @return ERROR_ERR => 错误,ERROR_SUC => 正确
*/
public function check_key_pass($file, $passwd)
{
if (! file_exists($file))
{
//show_error('input file is not exists');
return ERROR_ERR;
}

// 通过openssl是否能读取KEY内容,判断KEY密码是否正确
// 不限后缀,先当p12验证
$cmd = 'openssl pkcs12 -in '.escapeshellarg($file).
' -passin pass:'.escapeshellarg($passwd).' -noout >/dev/stdout 2>&1';
$fp = popen($cmd, 'r');
$ctx = fgets($fp);
pclose($fp);

if (preg_match("/^MAC verified OK/i", $ctx))
{
return ERROR_SUC;
}
/*
// 确认IOS的KEY必须是p12格式的,下面屏蔽掉
// 上面检测不过,作为key文件检测
$cmd = 'openssl pkey -in '.escapeshellarg($file).
' -passin pass:'.escapeshellarg($passwd).' >/dev/stdout 2>&1';


$fp = popen($cmd, 'r');
$ctx = fgets($fp);
pclose($fp);


// 不能加载KEY内容,则密码错误
if (preg_match("/^unable to load key/i", $ctx))
{
return ERROR_ERR;
}

return ERROR_SUC;
*/
return ERROR_ERR;
}

/**
* 检测keystore中指定别名证书密码是否正确
*
* @param $file keystore路径
* @param $passwd keystore密码
* @param $cert 证书别名
* @param $cert_pass 证书密码
* @return ERROR_ERR => 错误,ERROR_SUC => 正确
*/
public function check_keystore_key_pass($file, $passwd, $cert, $cert_passwd)
{
if (! file_exists($file))
{
//show_error('input file is not exists');
return ERROR_ERR;
}

// 同过keytool修改keystore中证书密码,判断证书密码是否正确
$cmd = 'keytool -keypasswd  -alias '.escapeshellarg($cert).
' -keystore '.escapeshellarg($file).' -storepass '.escapeshellarg($passwd).
' -keypass '.escapeshellarg($cert_passwd).' -new '.escapeshellarg($cert_passwd);
$fp = popen($cmd, 'r');
$ctx = fgets($fp);
pclose($fp);

// keytool解析错误,则密码错误
if (preg_match("/^keytool error/i", $ctx))
{
return ERROR_ERR;
}
return ERROR_SUC;
}

/**
* 获取证书信息
*
* @param $file keystore路径
* @param $passwd keystore密码
* @param [out] $out_arr 证书列表/错误信息
* @return ERROR_ERR => 失败,ERROR_SUC => 成功
*/
public function list_cert_in_keystore($file, $passwd, &$out_arr)
{
if (! file_exists($file))
{
//show_error('input file is not exists');
return ERROR_ERR;
}

// 调用列出keystore中证书命令,并通过grep和sed截取证书别名
$cmd = "keytool -list -v -keystore ".escapeshellarg($file).
" -storepass ".escapeshellarg($passwd)." | grep 'Alias name' | sed 's/^Alias name: //'";
exec($cmd, $out_arr);

if (! empty($out_arr))
{
return ERROR_SUC;
}

// 调用列出keystore中证书命令,通过grep和sed截取错误信息
$cmd = "keytool -list -v -keystore ".escapeshellarg($file).
" -storepass ".escapeshellarg($passwd)." | grep '^keytool error:' | sed 's/^keytool error: //'";
exec($cmd, $out_arr);

return ERROR_ERR;
}

/**
* 获取keystore中证书信息
*
* @param $file keystore路径
* @param $passwd keystore密码
* @param $cert_alias 证书别名
* @param[out] $info_arr 证书信息,包括过期时间,序列号,签发者
* @return ERROR_ERR => 失败,ERROR_SUC => 成功
*/
public function get_keystore_cert_info($file, $passwd, $cert_alias, &$info_arr)
{
if (! file_exists($file))
{
//show_error('input file is not exists');
return ERROR_ERR;
}

// 别名对应的临时证书文件
$tmp_file = pathinfo($file, PATHINFO_DIRNAME).'/'.gen_uniqid_name();

// 导出别名证书
$cmd = 'keytool -export -alias '.escapeshellarg($cert_alias).
' -file '.escapeshellarg($tmp_file).' -keystore '.escapeshellarg($file).
' -storepass '.escapeshellarg($passwd);
if(system($cmd) === false)
{
//show_error('export cert: '.$cert_alias.' failed');
return ERROR_ERR;
}

// 获取指定证书信息
$ret = $this->get_cert_info($tmp_file, $info_arr);

// 删除转换的临时文件
if (file_exists($tmp_file))
{
system('rm -f '.escapeshellarg($tmp_file));
}

return $ret;
}

}

/**
 * 创建mdm证书
*/
private function CreateMDMCert($addr)
{
$path = '/tmp/mdm';
if(!is_dir($path))
{
mkdir($path);
}
$cmd = "openssl genrsa -out $path/mdm_ssl.key 2048";
$pp = popen($cmd, "r");
if(!$pp)
{
return ERROR_FAIL;
}
pclose($pp);
if(!file_exists("$path/mdm_ssl.key"))
{
return ERROR_FAIL;
}
$cmd = sprintf("more $path/temp.tmp | openssl req -new -out $path/temp.csr -key $path/mdm_ssl.key");
$fp = fopen("$path/temp.tmp", "w");
if(!$fp) 
{
return ERROR_FAIL;
}
fwrite($fp, "cn\n");
fwrite($fp, "gd\n");
fwrite($fp, "sz\n");
fwrite($fp, "sf\n");
fwrite($fp, "mdm\n");
fwrite($fp, $addr."\n");
fwrite($fp, "mdm@sf.com\n\n\n\n");
fclose($fp);

$pp = popen($cmd, "r");
if(!$pp) 
{
return ERROR_FAIL;
}
pclose($pp);
if(!file_exists("$path/temp.csr") || !file_exists("/etc/ssl/mdm/mdm_ca.crt") || !file_exists("/etc/ssl/mdm/mdm_ca.key"))
{
return ERROR_NOT_EXIST;
}
$cmd = sprintf("openssl x509 -req -in $path/temp.csr -out $path/mdm_ssl.crt -CA /etc/ssl/mdm/mdm_ca.crt -CAkey /etc/ssl/mdm/mdm_ca.key -CAcreateserial -days 10950");
$pp = popen($cmd, "r");
if(!$pp)
{
return ERROR_FAIL;
}
pclose($pp);

exec("cp -af $path/mdm_ssl.* /etc/ssl/");
exec("cp -af $path/mdm_ssl.* /config/etc/ssl/");
exec("rm -rf $path");
return ERROR_OK;
}

0 0
原创粉丝点击