dnomd343
3 years ago
commit
fd95377993
4 changed files with 1003 additions and 0 deletions
File diff suppressed because one or more lines are too long
@ -0,0 +1,644 @@ |
|||
<?php |
|||
|
|||
class Output { |
|||
private static $colorEnum = array( |
|||
'red' => '[31m', |
|||
'green' => '[32m', |
|||
'yellow' => '[33m', |
|||
'blue' => '[34m', |
|||
'purple' => '[35m', |
|||
'sky-blue' => '[36m', |
|||
); |
|||
|
|||
public static function str($content, $color = '') { // 输出字符串 |
|||
if (!isset(self::$colorEnum[$color])) { |
|||
echo $content; |
|||
return; |
|||
} |
|||
echo "\033" . self::$colorEnum[$color] . $content . "\033" . "[0m"; |
|||
} |
|||
|
|||
public static function line($content, $color = '') { // 输出一行 |
|||
self::str($content . PHP_EOL, $color); |
|||
} |
|||
} |
|||
|
|||
class Fake { |
|||
private static function randLocation() { // 生成虚假地址及编码 |
|||
$gb2260 = Storage::getGB2260(); |
|||
$subData = array(); |
|||
foreach ($gb2260 as $code => $content) { |
|||
if (substr($code, 2, 2) === '00') { continue; } |
|||
if (substr($code, 4, 2) === '00') { continue; } |
|||
$subData[$code] = $content; |
|||
} |
|||
$code = array_rand($subData); |
|||
return array( |
|||
'code' => $code, |
|||
'level_1' => $gb2260[substr($code, 0, 2) . '0000'], |
|||
'level_2' => $gb2260[substr($code, 0, 4) . '00'], |
|||
'level_3' => $gb2260[$code], |
|||
); |
|||
} |
|||
|
|||
private static function randDate() { // 随机生成日期 |
|||
$time = rand(3000, 12000) * 24 * 3600; |
|||
return array( |
|||
'date' => date("Ymd", $time), |
|||
'format' => date("Y-m-d", $time) |
|||
); |
|||
} |
|||
|
|||
public static function randIdNum() { // 生成身份证号 |
|||
$wi = array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); |
|||
$ai = array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'); |
|||
$location = self::randLocation(); |
|||
$date = self::randDate(); |
|||
$orderNum = rand(100, 999); |
|||
$sex = ($orderNum % 2 !== 0) ? 'male' : 'female'; |
|||
$idNum = $location['code'] . $date['date'] . $orderNum; |
|||
$sign = 0; |
|||
for ($i = 0; $i < 17; $i++) { |
|||
$bit = (int)$idNum{$i}; |
|||
$sign += $bit * $wi[$i]; |
|||
} |
|||
unset($location['code']); |
|||
return array( |
|||
'idNum' => $idNum . $ai[$sign % 11], |
|||
'location' => $location, |
|||
'date' => $date['format'], |
|||
'sex' => $sex |
|||
); |
|||
} |
|||
|
|||
public static function randPhoneNum() { // 随机电话号码 |
|||
$prefix = array( |
|||
130,131,132,133,134,135,136,137,138,139, |
|||
144,147, |
|||
150,151,152,153,155,156,157,158,159, |
|||
176,177,178, |
|||
180,181,182,183,184,185,186,187,188,189, |
|||
); |
|||
return $prefix[array_rand($prefix)] . rand(10000000, 99999999); |
|||
} |
|||
|
|||
public static function randName($male = true) { // 随机姓名 |
|||
$firstname = array( |
|||
'赵','钱','孙','李','周','吴','郑','王','冯','陈','褚','卫','蒋','沈','韩','杨','朱','秦','尤','许','何','吕','施','张','孔','曹','严','华','金','魏','陶','姜','倪','姬', |
|||
'戚','谢','邹','喻','柏','水','窦','章','云','苏','潘','葛','奚','范','彭','郎','鲁','韦','昌','马','苗','凤','花','方','任','袁','柳','史','唐','费','薛','雷','贺','熊', |
|||
'汤','滕','殷','罗','毕','郝','安','常','傅','卞','齐','元','顾','孟','平','黄','穆','萧','尹','姚','邵','湛','汪','祁','毛','狄','米','伏','成','戴','谈','宋','茅','庞', |
|||
'纪','舒','屈','项','祝','董','梁','杜','阮','蓝','闵','季','贾','路','江','童','颜','郭','梅','卢','林','钟','徐','邱','骆','高','夏','蔡','田','樊','胡','凌','霍','虞', |
|||
); |
|||
$lastname_male = array( |
|||
'伟','刚','勇','毅','俊','峰','强','军','平','保','东','文','辉','力','明','永','健','世','广','志','义','兴','良','海','山','仁','波','宁','贵','福','生','龙','行','坚', |
|||
'元','全','国','胜','学','祥','才','发','武','新','利','清','飞','彬','富','顺','信','子','杰','涛','昌','成','康','星','光','天','达','安','岩','中','茂','进','林','有', |
|||
'和','彪','博','诚','先','敬','震','振','壮','会','思','群','豪','心','邦','承','乐','绍','功','松','善','厚','庆','磊','民','友','裕','河','哲','江','超','浩','亮','政', |
|||
'亨','奇','固','之','轮','翰','朗','伯','宏','言','若','鸣','朋','斌','梁','栋','维','启','克','伦','翔','旭','鹏','泽','晨','辰','士','以','建','家','致','树','炎','德', |
|||
); |
|||
$lastname_female = array( |
|||
'时','泰','盛','雄','琛','钧','冠','策','腾','楠','榕','风','航','弘','秀','娟','英','慧','巧','美','娜','静','淑','惠','珠','翠','雅','芝','玉','萍','红','娥','玲','芬', |
|||
'芳','燕','彩','春','菊','兰','凤','洁','梅','琳','素','云','莲','真','环','雪','荣','爱','妹','霞','香','月','莺','媛','艳','瑞','凡','佳','嘉','琼','珍','贞','莉','桂', |
|||
'娣','叶','璐','娅','琦','晶','妍','茜','秋','珊','莎','锦','黛','青','倩','婷','姣','婉','娴','瑾','颖','露','瑶','怡','婵','雁','蓓','纨','仪','荷','丹','蓉','眉','君', |
|||
'琴','蕊','薇','菁','梦','岚','苑','婕','馨','瑗','琰','韵','融','园','艺','咏','卿','聪','澜','纯','毓','悦','昭','冰','爽','琬','茗','羽','希','欣','飘','育','滢','馥', |
|||
); |
|||
$lastname = ($male) ? $lastname_male : $lastname_female; |
|||
$name = $lastname[array_rand($lastname)]; |
|||
if (rand(1, 6) > 1) { |
|||
$name .= $lastname[array_rand($lastname)]; |
|||
} |
|||
return $firstname[array_rand($firstname)] . $name; |
|||
} |
|||
} |
|||
|
|||
class Storage { |
|||
private static $workDir = '/etc/encryption365'; |
|||
|
|||
public static function getGB2260() { // 读取GB2260数据 |
|||
return json_decode(file_get_contents(self::$workDir . 'GB2260.json'), true); |
|||
} |
|||
|
|||
public static function setClientInfo($email, $clientId, $token) { // 客户端凭证写入到本地文件 |
|||
$content = 'account = ' . $email . PHP_EOL; |
|||
$content .= 'client_id = ' . $clientId . PHP_EOL; |
|||
$content .= 'access_token = ' . $token . PHP_EOL; |
|||
file_put_contents(self::$workDir . '/client.conf', $content); |
|||
} |
|||
|
|||
public static function getClientInfo() { // 本地文件读取客户端凭证 |
|||
$raw = explode(PHP_EOL, file_get_contents(self::$workDir . '/client.conf')); |
|||
$info = array(); |
|||
foreach ($raw as $row) { |
|||
$row = explode('=', $row); |
|||
if (count($row) !== 2) { continue; } |
|||
$info[trim($row[0])] = trim($row[1]); |
|||
} |
|||
return $info; |
|||
} |
|||
|
|||
public static function setValidation($content) { // 设置验证内容 |
|||
file_put_contents(self::$workDir . '/validation.txt', $content); |
|||
} |
|||
|
|||
public static function delValidation() { // 删除验证文件 |
|||
unlink(self::$workDir . '/validation.txt'); |
|||
} |
|||
|
|||
public static function getHostList() { // 获取站点列表 |
|||
// working |
|||
} |
|||
|
|||
public static function delHost() { // 删除一个站点 |
|||
// working |
|||
} |
|||
|
|||
private static function setHostConfig($host, $file, $content) { // 写入站点文件 |
|||
$dir = self::$workDir . '/' . $host; |
|||
if (!is_dir($dir)) { |
|||
mkdir($dir); |
|||
} |
|||
file_put_contents(self::$workDir . '/' . $host . '/' . $file, $content); |
|||
} |
|||
|
|||
private static function getHostConfig($host, $file) { // 读取站点文件 |
|||
return file_get_contents(self::$workDir . '/' . $host . '/' . $file); |
|||
} |
|||
|
|||
public static function setPrivkey($host, $content) { // 存储站点私钥 |
|||
self::setHostConfig($host, 'private.key', $content); |
|||
} |
|||
|
|||
public static function getPrivkey($host) { // 读取站点私钥 |
|||
return self::getHostConfig($host, 'private.key'); |
|||
} |
|||
|
|||
public static function setCsr($host, $content) { // 存储站点CSR记录 |
|||
self::setHostConfig($host, 'csr.dat', $content); |
|||
} |
|||
|
|||
public static function getCsr($host) { // 读取站点CSR记录 |
|||
return self::getHostConfig($host, 'csr.dat'); |
|||
} |
|||
|
|||
public static function setCert($host, $content) { // 储存站点证书文件 |
|||
self::setHostConfig($host, 'cert.crt', $content); |
|||
} |
|||
|
|||
public static function getCert($host) { // 读取站点证书文件 |
|||
return self::getHostConfig($host, 'cert.crt'); |
|||
} |
|||
|
|||
public static function setCaCert($host, $content) { // 存储站点CA证书 |
|||
self::setHostConfig($host, 'ca.crt', $content); |
|||
} |
|||
|
|||
public static function getCaCert($host) { // 读取站点CA证书 |
|||
return self::getHostConfig($host, 'ca.crt'); |
|||
} |
|||
|
|||
public static function setInfo($host, $info) { // 记录站点信息 |
|||
self::setHostConfig($host, 'info.json', json_encode($info)); |
|||
} |
|||
|
|||
public static function getInfo($host) { // 读取站点信息 |
|||
return json_decode(self::getHostConfig($host, 'info.json'), true); |
|||
} |
|||
} |
|||
|
|||
class Encryption365 { |
|||
private static $version = '1.3.1'; |
|||
private static $apiEntry = 'https://encrypt365.trustocean.com'; |
|||
|
|||
private function callApi(string $uri, array $params) { // Encrypt365 API接口 |
|||
$curl = curl_init(); |
|||
curl_setopt($curl, CURLOPT_URL, self::$apiEntry . $uri); |
|||
curl_setopt($curl, CURLOPT_POST, 1); |
|||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); |
|||
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST"); |
|||
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($params)); |
|||
curl_setopt($curl, CURLOPT_USERAGENT, 'Encryption365-Client/' . self::$version . ';BaotaPanel-LinuxVersion'); |
|||
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); |
|||
$callResult = curl_exec($curl); |
|||
if (curl_error($curl)) { |
|||
die('Curl Error: ' . curl_error($curl)); |
|||
} |
|||
curl_close($curl); |
|||
$result = json_decode($callResult, true); |
|||
if(isset($result['status']) && $result['status'] === 'error') { |
|||
return array( |
|||
'status' => 'error', |
|||
'message' => $result['message'] |
|||
); |
|||
} |
|||
return $result; |
|||
} |
|||
|
|||
private static function getClientInfo() { // 获取客户端ID和token |
|||
$info = Storage::getClientInfo(); |
|||
if (!isset($info['client_id'])) { |
|||
die('Fail to get client_id'); |
|||
} |
|||
if (!isset($info['access_token'])) { |
|||
die('Fail to get access_token'); |
|||
} |
|||
return array( |
|||
'client_id' => $info['client_id'], |
|||
'access_token' => $info['access_token'] |
|||
); |
|||
} |
|||
|
|||
public static function getLatest() { // 获取最新版本 |
|||
return self::callApi('/client/version', array()); |
|||
} |
|||
|
|||
public static function authcodeSend($email) { // 发送注册验证码 |
|||
return self::callApi('/account/register/authcode', array( |
|||
'username' => $email |
|||
)); |
|||
} |
|||
|
|||
public static function accountRegister($info) { // 注册账号 |
|||
return self::callApi('/account/register', array( |
|||
'username' => $info['email'], |
|||
'password' => $info['password'], |
|||
'authcode' => $info['authcode'], |
|||
'realName' => $info['realName'], |
|||
'idcardNumber' => $info['idcardNumber'], |
|||
'phoneNumber' => $info['phoneNumber'], |
|||
'country' => $info['country'], |
|||
'companyname' => $info['companyName'] |
|||
)); |
|||
} |
|||
|
|||
public static function clientLogin($username, $password) { // 客户端登录 |
|||
return self::callApi("/client/create", array( |
|||
'username' => $username, |
|||
'password' => $password, |
|||
'servername' => 'example.com', |
|||
)); |
|||
} |
|||
|
|||
public static function getAccountDetail() { // 获取账户信息 |
|||
return self::callApi('/account/details', self::getClientInfo()); |
|||
} |
|||
|
|||
public static function getProducts() { // 获取可购买产品 |
|||
return self::callApi('/account/products', self::getClientInfo())['products']; |
|||
} |
|||
|
|||
public static function certCreate($productId, $csrCode, $domains) { // 创建证书 |
|||
return self::callApi('/cert/create', self::getClientInfo() + array( |
|||
'pid' => $productId, |
|||
'period' => 'quarterly', |
|||
'csr_code' => $csrCode, |
|||
'domains' => implode(',', $domains), |
|||
'renew' => false, |
|||
'old_vendor_id' => -1, |
|||
)); |
|||
} |
|||
|
|||
public static function certReValidation($vendorId) { // 重新执行域名验证 |
|||
return self::callApi('/cert/challenge', self::getClientInfo() + array( |
|||
'trustocean_id' => $vendorId |
|||
)); |
|||
} |
|||
|
|||
public static function certDetails($vendorId) { // 查询证书详细信息 |
|||
return self::callApi('/cert/details', self::getClientInfo() + array( |
|||
'trustocean_id' => $vendorId |
|||
)); |
|||
} |
|||
|
|||
public static function certRenew($productId, $csrCode, $domains, $oldVendorId) { // 更新证书 |
|||
return self::callApi('/cert/create', self::getClientInfo() + array( |
|||
'pid' => $productId, |
|||
'period' => 'quarterly', |
|||
'csr_code' => $csrCode, |
|||
'domains' => implode(',', $domains), |
|||
'renew' => true, |
|||
'old_vendor_id' => $oldVendorId, |
|||
)); |
|||
} |
|||
|
|||
public static function certReissue($vendorId, $csrCode, $domains) { // 重签SSL证书 |
|||
return self::callApi('/cert/reissue', self::getClientInfo() + array( |
|||
'trustocean_id' => $vendorId, |
|||
'csr_code' => $csrCode, |
|||
'domains' => implode(',', $domains) |
|||
)); |
|||
} |
|||
} |
|||
|
|||
class Certificate { |
|||
public static function generateKeyPair($commonName, $isEcc = false) { // 生成密钥对 |
|||
if (filter_var($commonName, FILTER_VALIDATE_IP)) { // 若为IP地址 |
|||
$commonName = 'common-name-for-public-ip-address.com'; |
|||
} |
|||
$subject = array( |
|||
"commonName" => $commonName, |
|||
"organizationName" => "Encryption365 SSL Security", |
|||
"organizationalUnitName" => "Encryption365 SSL Security", |
|||
"localityName" => "Xian", |
|||
"stateOrProvinceName" => "Shaanxi", |
|||
"countryName" => "CN", |
|||
); |
|||
if (!$isEcc) { // RSA证书 |
|||
$private_key = openssl_pkey_new(array( |
|||
'private_key_type' => OPENSSL_KEYTYPE_RSA, |
|||
'private_key_bits' => 2048, |
|||
'config' => __DIR__ . '/openssl.cnf' |
|||
)); |
|||
$csr_resource = openssl_csr_new($subject, $private_key, array( |
|||
'digest_alg' => 'sha256', |
|||
'config' => __DIR__ . '/openssl.cnf' |
|||
)); |
|||
} else { // ECC证书 |
|||
$private_key = openssl_pkey_new(array( |
|||
'private_key_type' => OPENSSL_KEYTYPE_EC, |
|||
'curve_name' => 'prime256v1', |
|||
'config' => __DIR__.'/openssl.cnf' |
|||
)); |
|||
$csr_resource = openssl_csr_new($subject, $private_key, array( |
|||
'digest_alg' => 'sha384', |
|||
'config' => __DIR__ . '/openssl.cnf' |
|||
)); |
|||
} |
|||
openssl_csr_export($csr_resource, $csr_string); |
|||
openssl_pkey_export($private_key, $private_key_string, null, array( |
|||
'config' => __DIR__ . '/openssl.cnf' |
|||
)); |
|||
return array( |
|||
'csr_code' => $csr_string, |
|||
'key_code' => $private_key_string |
|||
); |
|||
} |
|||
|
|||
public static function preCheck($domains) { // 预先检查http验证是否正常 |
|||
$randStr = md5(uniqid(microtime(true), true)); |
|||
Storage::setValidation($randStr); |
|||
$result = self::checkValidation($domains, $randStr); |
|||
Storage::delValidation(); |
|||
return $result; |
|||
} |
|||
|
|||
public static function checkValidation($domains, $expect) { // 检查http验证是否正常 |
|||
foreach ($domains as $domain) { |
|||
$content = file_get_contents('http://' . $domain . '/.well-known/pki-validation/check'); |
|||
if ($content !== $expect) { return false; } |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
private static function waitIssued($vendorId) { // 等待证书签发 |
|||
$maxTime = 20; |
|||
$interval = 30; |
|||
for ($i = 0; $i < 20; $i++) { |
|||
Output::line('Let\'s wait ' . $interval . ' seconds and query certificate status...'); |
|||
sleep($interval); |
|||
$detail = Encryption365::certDetails($vendorId); |
|||
if ($detail['result'] !== "success") { |
|||
Output::str('Fail to get certificate details => '); |
|||
Output::line($detail['message'], 'red'); |
|||
continue; |
|||
} |
|||
if ($detail['cert_status'] === 'issued_active') { |
|||
Output::line('Certificate issue success', 'green'); |
|||
return $detail; |
|||
} else { |
|||
Output::str('Certificate status: '); |
|||
Output::line($detail['cert_status'], 'yellow'); |
|||
} |
|||
} |
|||
return array('result' => 'fail'); |
|||
} |
|||
|
|||
private static function issueCert($host) { // 轮询证书签发并存储 |
|||
$info = Stoarge::getInfo($host); |
|||
$vendorId = $info['vendorId']; |
|||
$domains = $info['domains']; |
|||
$certInfo = self::waitIssued($vendorId); |
|||
if ($certInfo['result'] !== "success") { |
|||
Output::line('Issue certificate time out, you may validate again...', 'red'); |
|||
return false; |
|||
} |
|||
$cert = $certInfo['cert_code']; |
|||
$caCert = $certInfo['ca_code']; |
|||
$startTime = $certInfo['created_at']; |
|||
$endTime = $certInfo['expire_at']; |
|||
$info['status'] = 'issued'; |
|||
$info['createTime'] = $startTime; |
|||
$info['expireTime'] = $endTime; |
|||
Storage::setInfo($host, $info); |
|||
Storage::setCert($host, $cert); |
|||
Storage::setCaCert($host, $caCert); |
|||
Output::line('Certificate: ', 'purple'); |
|||
echo $cert . PHP_EOL; |
|||
Output::line('CA Certificate: ', 'purple'); |
|||
echo $caCert . PHP_EOL; |
|||
Output::str('Create time: '); |
|||
Output::line($startTime, 'sky-blue'); |
|||
Output::str('Expire time: '); |
|||
Output::line($endTime, 'sky-blue'); |
|||
return true; |
|||
} |
|||
|
|||
public static function createCert($productId, $domains, $isEcc = false) { // 创建新的证书订单 |
|||
if (!self::preCheck($domains)) { |
|||
Output::line('Inaccessible http://{domain}/.well-known/pki-validation/... as validation.'); |
|||
return; |
|||
} |
|||
$host = $domains[0]; |
|||
$newCsrKey = self::generateKeyPair($host, $isEcc); |
|||
Storage::setPrivkey($host, $newCsrKey['key_code']); |
|||
Storage::setCsr($host, $newCsrKey['csr_code']); |
|||
$orderRlt = Encryption365::certCreate($productId, $newCsrKey['csr_code'], $domains); |
|||
if ($orderRlt['result'] !== "success") { |
|||
Output::str('Fail to create certificate => '); |
|||
Output::line($orderRlt['message'], 'red'); |
|||
return; |
|||
} |
|||
$vendorId = $orderRlt['trustocean_id']; |
|||
foreach ($orderRlt['dcv_info'] as $domain => $dcvInfo) { |
|||
$verifyLink = $dcvInfo['http_verifylink']; |
|||
$verifyContent = $dcvInfo['http_filecontent']; |
|||
break; |
|||
} |
|||
Storage::setInfo($host, array( |
|||
'host' => $host, |
|||
'vendorId' => $vendorId, |
|||
'productId' => $productId, |
|||
'domains' => $domains, |
|||
'status' => 'issuing', |
|||
'isEcc' => $isEcc |
|||
)); |
|||
Output::str('Vendor id: '); |
|||
Output::str($vendorId . PHP_EOL, 'sky-blue'); |
|||
Output::str('Verify link: '); |
|||
Output::str($verifyLink . PHP_EOL, 'sky-blue'); |
|||
Output::line('Verify content: '); |
|||
Output::str($verifyContent . PHP_EOL, 'sky-blue'); |
|||
Storage::setValidation($verifyContent); |
|||
if (self::issueCert($host)) { |
|||
Storage::delValidation(); |
|||
} |
|||
} |
|||
|
|||
public static function reValidate($host) { // 重新发起验证 |
|||
$info = Stoarge::getInfo($host); |
|||
if ($info['status'] === 'issued') { |
|||
Output::line('This has been issued succeed.'); |
|||
return; |
|||
} |
|||
if (!self::preCheck($info['domains'])) { |
|||
Output::line('Inaccessible http://{domain}/.well-known/pki-validation/... as validation.'); |
|||
return; |
|||
} |
|||
$status = Encryption365::certReValidation($info['vendorId']); |
|||
var_dump($status); |
|||
if ($status['result'] !== "success") { |
|||
Output::str('Fail to revalidate certificate => '); |
|||
Output::line($status['message'], 'red'); |
|||
return; |
|||
} |
|||
if (self::issueCert($host)) { |
|||
Storage::delValidation(); |
|||
} |
|||
} |
|||
|
|||
public static function renewCert($host) { // 更新证书 |
|||
$info = Stoarge::getInfo($host); |
|||
if ($info['status'] !== 'issued') { |
|||
Output::line('This site has never been issued.'); |
|||
return; |
|||
} |
|||
if (!self::preCheck($info['domains'])) { |
|||
Output::line('Inaccessible http://{domain}/.well-known/pki-validation/... as validation.'); |
|||
return; |
|||
} |
|||
$newCsrKey = self::generateKeyPair($host, $info['isEcc']); |
|||
Storage::setPrivkey($host, $newCsrKey['key_code']); |
|||
Storage::setCsr($host, $newCsrKey['csr_code']); |
|||
$orderRlt = Encryption365::certRenew($info['productId'], $newCsrKey['csr_code'], $info['domains'], $info['vendorId']); |
|||
if ($orderRlt['result'] !== "success") { |
|||
Output::str('Fail to renew certificate => '); |
|||
Output::line($orderRlt['message'], 'red'); |
|||
return; |
|||
} |
|||
$vendorId = $orderRlt['trustocean_id']; |
|||
foreach ($orderRlt['dcv_info'] as $domain => $dcvInfo) { |
|||
$verifyLink = $dcvInfo['http_verifylink']; |
|||
$verifyContent = $dcvInfo['http_filecontent']; |
|||
break; |
|||
} |
|||
$info['status'] = 'issuing'; |
|||
$info['vendorId'] = $vendorId; |
|||
Storage::setInfo($host, $info); |
|||
Output::str('Vendor id: '); |
|||
Output::str($vendorId . PHP_EOL, 'sky-blue'); |
|||
Output::str('Verify link: '); |
|||
Output::str($verifyLink . PHP_EOL, 'sky-blue'); |
|||
Output::line('Verify content: '); |
|||
Output::str($verifyContent . PHP_EOL, 'sky-blue'); |
|||
Storage::setValidation($verifyContent); |
|||
if (self::issueCert($host)) { |
|||
Storage::delValidation(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
class RegistCtr { |
|||
public static function interact() { // 注册交互 |
|||
Output::line('This process help you regist a Trustocean account, all you need is an email address to receive the verification code.'); |
|||
Output::str('Email: ', 'yellow'); |
|||
$email = trim(fgets(STDIN)); |
|||
$result = Encryption365::authcodeSend($email); |
|||
if ($result['result'] !== 'success') { |
|||
Output::str('Fail to send auth code: '); |
|||
Output::str($result['message'], 'red'); |
|||
return; |
|||
} |
|||
Output::line('There will be an email sent to ' . $email . ', please note checking.'); |
|||
Output::str('Verification code: ', 'yellow'); |
|||
$code = trim(fgets(STDIN)); |
|||
Output::line('Set a password for your account.'); |
|||
Output::str('Password: ', 'yellow'); |
|||
$passwd = trim(fgets(STDIN)); |
|||
Output::line('Trustocean need your Chinese ID card num, but you can just press ENTER to generate one.'); |
|||
Output::str('ID card num: ', 'yellow'); |
|||
$idNum = trim(fgets(STDIN)); |
|||
if ($idNum === '') { |
|||
$fake = Fake::randIdNum(); |
|||
Output::str('Random ID card num: '); |
|||
Output::str($fake['idNum'] . PHP_EOL, 'sky-blue'); |
|||
Output::str('Random ID card info: '); |
|||
Output::str(implode(' ', $fake['location']) . ' ' . $fake['date'] . ' ' . $fake['sex'] . PHP_EOL, 'sky-blue'); |
|||
} |
|||
Output::line('Please enter your real name, or press ENTER to generate one.'); |
|||
Output::str('Name: ', 'yellow'); |
|||
$name = trim(fgets(STDIN)); |
|||
if ($name === '') { |
|||
$fake['name'] = Fake::randName(($fake['sex'] === 'male')); |
|||
Output::str('Random name: '); |
|||
Output::str($fake['name'] . PHP_EOL, 'sky-blue'); |
|||
} |
|||
Output::line('Last step, enter your phone num, or randomly generate one by press ENTER.'); |
|||
Output::str('Phone: ', 'yellow'); |
|||
$phone = trim(fgets(STDIN)); |
|||
if ($phone === '') { |
|||
$fake['phone'] = Fake::randPhoneNum(); |
|||
Output::str('Random phone: '); |
|||
Output::str($fake['phone'] . PHP_EOL, 'sky-blue'); |
|||
} |
|||
Output::str('It seems that all the information is complete, press ENTER to register your account...'); |
|||
fgets(STDIN); |
|||
self::regist($email, $passwd, $code, $fake['name'], $fake['idNum'], $fake['phone']); |
|||
Output::line('Use "encryption365 login" command to login.'); |
|||
} |
|||
|
|||
public static function regist($email, $passwd, $code, $name, $idNum, $phone) { // 发起注册 |
|||
$result = Encryption365::accountRegister(array( |
|||
'email' => $email, |
|||
'password' => $passwd, |
|||
'authcode' => $code, |
|||
'realName' => $name, |
|||
'idcardNumber' => $idNum, |
|||
'phoneNumber' => $phone, |
|||
'country' => 'CN', |
|||
'companyName' => '无' |
|||
)); |
|||
if ($result['result'] !== 'success') { |
|||
Output::str('Fail to regist: '); |
|||
Output::str($result['message'], 'red'); |
|||
return; |
|||
} |
|||
Output::str('Regist success' . PHP_EOL, 'green'); |
|||
} |
|||
} |
|||
|
|||
class LoginCtr { |
|||
public static function interact() { // 登录交互 |
|||
Output::line('This process need a Trustocean account, if you don\'t have it currently, there are two methods:'); |
|||
Output::line('1. Manually register at "https://page.trustocean.com/websecurity/welcome"'); |
|||
Output::line('2. Use "encryption365 regist" command regist automatically'); |
|||
Output::str('Email: '); |
|||
$email = trim(fgets(STDIN)); |
|||
Output::str('Password: '); |
|||
$passwd = trim(fgets(STDIN)); |
|||
self::login($email, $passwd); |
|||
} |
|||
|
|||
public static function login($email, $passwd) { // 发起登录 |
|||
$result = Encryption365::clientLogin($email, $passwd); |
|||
if ($result['result'] !== 'success') { |
|||
Output::str('Fail to login: '); |
|||
Output::str($result['message'], 'red'); |
|||
return; |
|||
} |
|||
Output::str('Login success' . PHP_EOL, 'green'); |
|||
Output::line('Account status: ' . $result['status']); |
|||
Output::line('Login time: ' . $result['created_at']); |
|||
Storage::setClientInfo($email, $result['client_id'], $result['access_token']); |
|||
} |
|||
} |
|||
|
|||
?> |
|||
|
@ -0,0 +1,350 @@ |
|||
# |
|||
# OpenSSL example configuration file. |
|||
# This is mostly being used for generation of certificate requests. |
|||
# |
|||
|
|||
# This definition stops the following lines choking if HOME isn't |
|||
# defined. |
|||
HOME = . |
|||
RANDFILE = $ENV::HOME/.rnd |
|||
|
|||
# Extra OBJECT IDENTIFIER info: |
|||
#oid_file = $ENV::HOME/.oid |
|||
oid_section = new_oids |
|||
|
|||
# To use this configuration file with the "-extfile" option of the |
|||
# "openssl x509" utility, name here the section containing the |
|||
# X.509v3 extensions to use: |
|||
# extensions = |
|||
# (Alternatively, use a configuration file that has only |
|||
# X.509v3 extensions in its main [= default] section.) |
|||
|
|||
[ new_oids ] |
|||
|
|||
# We can add new OIDs in here for use by 'ca', 'req' and 'ts'. |
|||
# Add a simple OID like this: |
|||
# testoid1=1.2.3.4 |
|||
# Or use config file substitution like this: |
|||
# testoid2=${testoid1}.5.6 |
|||
|
|||
# Policies used by the TSA examples. |
|||
tsa_policy1 = 1.2.3.4.1 |
|||
tsa_policy2 = 1.2.3.4.5.6 |
|||
tsa_policy3 = 1.2.3.4.5.7 |
|||
|
|||
#################################################################### |
|||
[ ca ] |
|||
default_ca = CA_default # The default ca section |
|||
|
|||
#################################################################### |
|||
[ CA_default ] |
|||
|
|||
dir = ./demoCA # Where everything is kept |
|||
certs = $dir/certs # Where the issued certs are kept |
|||
crl_dir = $dir/crl # Where the issued crl are kept |
|||
database = $dir/index.txt # database index file. |
|||
#unique_subject = no # Set to 'no' to allow creation of |
|||
# several ctificates with same subject. |
|||
new_certs_dir = $dir/newcerts # default place for new certs. |
|||
|
|||
certificate = $dir/cacert.pem # The CA certificate |
|||
serial = $dir/serial # The current serial number |
|||
crlnumber = $dir/crlnumber # the current crl number |
|||
# must be commented out to leave a V1 CRL |
|||
crl = $dir/crl.pem # The current CRL |
|||
private_key = $dir/private/cakey.pem# The private key |
|||
RANDFILE = $dir/private/.rand # private random number file |
|||
|
|||
x509_extensions = usr_cert # The extentions to add to the cert |
|||
|
|||
# Comment out the following two lines for the "traditional" |
|||
# (and highly broken) format. |
|||
name_opt = ca_default # Subject Name options |
|||
cert_opt = ca_default # Certificate field options |
|||
|
|||
# Extension copying option: use with caution. |
|||
# copy_extensions = copy |
|||
|
|||
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs |
|||
# so this is commented out by default to leave a V1 CRL. |
|||
# crlnumber must also be commented out to leave a V1 CRL. |
|||
# crl_extensions = crl_ext |
|||
|
|||
default_days = 365 # how long to certify for |
|||
default_crl_days= 30 # how long before next CRL |
|||
default_md = default # use public key default MD |
|||
preserve = no # keep passed DN ordering |
|||
|
|||
# A few difference way of specifying how similar the request should look |
|||
# For type CA, the listed attributes must be the same, and the optional |
|||
# and supplied fields are just that :-) |
|||
policy = policy_match |
|||
|
|||
# For the CA policy |
|||
[ policy_match ] |
|||
countryName = match |
|||
stateOrProvinceName = match |
|||
organizationName = match |
|||
organizationalUnitName = optional |
|||
commonName = supplied |
|||
emailAddress = optional |
|||
|
|||
# For the 'anything' policy |
|||
# At this point in time, you must list all acceptable 'object' |
|||
# types. |
|||
[ policy_anything ] |
|||
countryName = optional |
|||
stateOrProvinceName = optional |
|||
localityName = optional |
|||
organizationName = optional |
|||
organizationalUnitName = optional |
|||
commonName = supplied |
|||
emailAddress = optional |
|||
|
|||
#################################################################### |
|||
[ req ] |
|||
default_bits = 2048 |
|||
default_keyfile = privkey.pem |
|||
distinguished_name = req_distinguished_name |
|||
attributes = req_attributes |
|||
x509_extensions = v3_ca # The extentions to add to the self signed cert |
|||
|
|||
# Passwords for private keys if not present they will be prompted for |
|||
# input_password = secret |
|||
# output_password = secret |
|||
|
|||
# This sets a mask for permitted string types. There are several options. |
|||
# default: PrintableString, T61String, BMPString. |
|||
# pkix : PrintableString, BMPString (PKIX recommendation before 2004) |
|||
# utf8only: only UTF8Strings (PKIX recommendation after 2004). |
|||
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). |
|||
# MASK:XXXX a literal mask value. |
|||
# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings. |
|||
string_mask = utf8only |
|||
|
|||
# req_extensions = v3_req # The extensions to add to a certificate request |
|||
|
|||
[ req_distinguished_name ] |
|||
countryName = Country Name (2 letter code) |
|||
countryName_default = AU |
|||
countryName_min = 2 |
|||
countryName_max = 2 |
|||
|
|||
stateOrProvinceName = State or Province Name (full name) |
|||
stateOrProvinceName_default = Some-State |
|||
|
|||
localityName = Locality Name (eg, city) |
|||
|
|||
0.organizationName = Organization Name (eg, company) |
|||
0.organizationName_default = Internet Widgits Pty Ltd |
|||
|
|||
# we can do this but it is not needed normally :-) |
|||
#1.organizationName = Second Organization Name (eg, company) |
|||
#1.organizationName_default = World Wide Web Pty Ltd |
|||
|
|||
organizationalUnitName = Organizational Unit Name (eg, section) |
|||
#organizationalUnitName_default = |
|||
|
|||
commonName = Common Name (e.g. server FQDN or YOUR name) |
|||
commonName_max = 64 |
|||
|
|||
emailAddress = Email Address |
|||
emailAddress_max = 64 |
|||
|
|||
# SET-ex3 = SET extension number 3 |
|||
|
|||
[ req_attributes ] |
|||
challengePassword = A challenge password |
|||
challengePassword_min = 4 |
|||
challengePassword_max = 20 |
|||
|
|||
unstructuredName = An optional company name |
|||
|
|||
[ usr_cert ] |
|||
|
|||
# These extensions are added when 'ca' signs a request. |
|||
|
|||
# This goes against PKIX guidelines but some CAs do it and some software |
|||
# requires this to avoid interpreting an end user certificate as a CA. |
|||
|
|||
basicConstraints=CA:FALSE |
|||
|
|||
# Here are some examples of the usage of nsCertType. If it is omitted |
|||
# the certificate can be used for anything *except* object signing. |
|||
|
|||
# This is OK for an SSL server. |
|||
# nsCertType = server |
|||
|
|||
# For an object signing certificate this would be used. |
|||
# nsCertType = objsign |
|||
|
|||
# For normal client use this is typical |
|||
# nsCertType = client, email |
|||
|
|||
# and for everything including object signing: |
|||
# nsCertType = client, email, objsign |
|||
|
|||
# This is typical in keyUsage for a client certificate. |
|||
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment |
|||
|
|||
# This will be displayed in Netscape's comment listbox. |
|||
nsComment = "OpenSSL Generated Certificate" |
|||
|
|||
# PKIX recommendations harmless if included in all certificates. |
|||
subjectKeyIdentifier=hash |
|||
authorityKeyIdentifier=keyid,issuer |
|||
|
|||
# This stuff is for subjectAltName and issuerAltname. |
|||
# Import the email address. |
|||
# subjectAltName=email:copy |
|||
# An alternative to produce certificates that aren't |
|||
# deprecated according to PKIX. |
|||
# subjectAltName=email:move |
|||
|
|||
# Copy subject details |
|||
# issuerAltName=issuer:copy |
|||
|
|||
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem |
|||
#nsBaseUrl |
|||
#nsRevocationUrl |
|||
#nsRenewalUrl |
|||
#nsCaPolicyUrl |
|||
#nsSslServerName |
|||
|
|||
# This is required for TSA certificates. |
|||
# extendedKeyUsage = critical,timeStamping |
|||
|
|||
[ v3_req ] |
|||
|
|||
# Extensions to add to a certificate request |
|||
|
|||
basicConstraints = CA:FALSE |
|||
keyUsage = nonRepudiation, digitalSignature, keyEncipherment |
|||
|
|||
[ v3_ca ] |
|||
|
|||
|
|||
# Extensions for a typical CA |
|||
|
|||
|
|||
# PKIX recommendation. |
|||
|
|||
subjectKeyIdentifier=hash |
|||
|
|||
authorityKeyIdentifier=keyid:always,issuer |
|||
|
|||
# This is what PKIX recommends but some broken software chokes on critical |
|||
# extensions. |
|||
#basicConstraints = critical,CA:true |
|||
# So we do this instead. |
|||
basicConstraints = CA:true |
|||
|
|||
# Key usage: this is typical for a CA certificate. However since it will |
|||
# prevent it being used as an test self-signed certificate it is best |
|||
# left out by default. |
|||
# keyUsage = cRLSign, keyCertSign |
|||
|
|||
# Some might want this also |
|||
# nsCertType = sslCA, emailCA |
|||
|
|||
# Include email address in subject alt name: another PKIX recommendation |
|||
# subjectAltName=email:copy |
|||
# Copy issuer details |
|||
# issuerAltName=issuer:copy |
|||
|
|||
# DER hex encoding of an extension: beware experts only! |
|||
# obj=DER:02:03 |
|||
# Where 'obj' is a standard or added object |
|||
# You can even override a supported extension: |
|||
# basicConstraints= critical, DER:30:03:01:01:FF |
|||
|
|||
[ crl_ext ] |
|||
|
|||
# CRL extensions. |
|||
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. |
|||
|
|||
# issuerAltName=issuer:copy |
|||
authorityKeyIdentifier=keyid:always |
|||
|
|||
[ proxy_cert_ext ] |
|||
# These extensions should be added when creating a proxy certificate |
|||
|
|||
# This goes against PKIX guidelines but some CAs do it and some software |
|||
# requires this to avoid interpreting an end user certificate as a CA. |
|||
|
|||
basicConstraints=CA:FALSE |
|||
|
|||
# Here are some examples of the usage of nsCertType. If it is omitted |
|||
# the certificate can be used for anything *except* object signing. |
|||
|
|||
# This is OK for an SSL server. |
|||
# nsCertType = server |
|||
|
|||
# For an object signing certificate this would be used. |
|||
# nsCertType = objsign |
|||
|
|||
# For normal client use this is typical |
|||
# nsCertType = client, email |
|||
|
|||
# and for everything including object signing: |
|||
# nsCertType = client, email, objsign |
|||
|
|||
# This is typical in keyUsage for a client certificate. |
|||
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment |
|||
|
|||
# This will be displayed in Netscape's comment listbox. |
|||
nsComment = "OpenSSL Generated Certificate" |
|||
|
|||
# PKIX recommendations harmless if included in all certificates. |
|||
subjectKeyIdentifier=hash |
|||
authorityKeyIdentifier=keyid,issuer |
|||
|
|||
# This stuff is for subjectAltName and issuerAltname. |
|||
# Import the email address. |
|||
# subjectAltName=email:copy |
|||
# An alternative to produce certificates that aren't |
|||
# deprecated according to PKIX. |
|||
# subjectAltName=email:move |
|||
|
|||
# Copy subject details |
|||
# issuerAltName=issuer:copy |
|||
|
|||
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem |
|||
#nsBaseUrl |
|||
#nsRevocationUrl |
|||
#nsRenewalUrl |
|||
#nsCaPolicyUrl |
|||
#nsSslServerName |
|||
|
|||
# This really needs to be in place for it to be a proxy certificate. |
|||
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo |
|||
|
|||
#################################################################### |
|||
[ tsa ] |
|||
|
|||
default_tsa = tsa_config1 # the default TSA section |
|||
|
|||
[ tsa_config1 ] |
|||
|
|||
# These are used by the TSA reply generation only. |
|||
dir = ./demoCA # TSA root directory |
|||
serial = $dir/tsaserial # The current serial number (mandatory) |
|||
crypto_device = builtin # OpenSSL engine to use for signing |
|||
signer_cert = $dir/tsacert.pem # The TSA signing certificate |
|||
# (optional) |
|||
certs = $dir/cacert.pem # Certificate chain to include in reply |
|||
# (optional) |
|||
signer_key = $dir/private/tsakey.pem # The TSA private key (optional) |
|||
|
|||
default_policy = tsa_policy1 # Policy if request did not specify it |
|||
# (optional) |
|||
other_policies = tsa_policy2, tsa_policy3 # acceptable policies (optional) |
|||
digests = md5, sha1 # Acceptable message digests (mandatory) |
|||
accuracy = secs:1, millisecs:500, microsecs:100 # (optional) |
|||
clock_precision_digits = 0 # number of digits after dot. (optional) |
|||
ordering = yes # Is ordering defined for timestamps? |
|||
# (optional, default: no) |
|||
tsa_name = yes # Must the TSA name be included in the reply? |
|||
# (optional, default: no) |
|||
ess_cert_id_chain = no # Must the ESS cert id chain be included? |
|||
# (optional, default: no) |
@ -0,0 +1,8 @@ |
|||
<?php |
|||
|
|||
$workDir = '/etc/encryption365'; |
|||
$host = $_SERVER['HTTP_HOST']; |
|||
$content = file_get_contents($workDir . '/validation.txt'); |
|||
echo $content; |
|||
|
|||
?> |
Loading…
Reference in new issue