Closed kildom closed 2 years ago
Extracting certificate only for github from cacert.pem:
function get_url($url, $cert) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_USERAGENT, "WordPress Downloader PHP script");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_CAINFO, __DIR__ . "/" . $cert);
curl_setopt($ch, CURLOPT_CAPATH, __DIR__ . "/empty");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 10);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_CERTINFO, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$res = curl_exec($ch);
if (curl_error($ch)) {
echo("\n" . curl_error($ch) . "\n");
$res = false;
} else {
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($status != 200) {
echo("\nHTTP status code: $status\n");
$res = false;
}
}
if ($res !== false) {
$res = curl_getinfo($ch, CURLINFO_CERTINFO);
}
curl_close($ch);
return $res;
}
$list = get_url('https://raw.githubusercontent.com/kildom/wp_downloader/main/test.js', 'cacert.pem');
$certs = array();
foreach ($list as $c) {
$x = openssl_x509_parse($c['Cert']);
$x['-'] = $c['Cert'];
$x['-in-cacert'] = false;
array_push($certs, $x);
}
$list = file_get_contents('cacert.pem');
preg_match_all('/-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----/ms', $list, $m);
$cacerts = array();
foreach ($m[0] as $c) {
$x = openssl_x509_parse($c);
$x['-'] = $c;
$x['-in-cacert'] = true;
array_push($cacerts, $x);
}
$all = array_merge($certs, $cacerts);
function parseKeyIdentifier($key, $force) {
$key = trim($key);
$key = strtoupper(trim(preg_replace('/keyid\s*:?/i', '', $key)));
if ($key == '' && $force) {
echo('Invalid key!');
exit(1);
}
return $key;
}
function find_root($c) {
global $all;
$subject = parseKeyIdentifier($c['extensions']['subjectKeyIdentifier'], true);
$authority = parseKeyIdentifier($c['extensions']['authorityKeyIdentifier'], true);
if ($c['-in-cacert']) {
return $c;
}
foreach ($all as $cc) {
$s = parseKeyIdentifier($cc['extensions']['subjectKeyIdentifier'], false);
if ($s == $authority) {
return find_root($cc);
}
}
echo("Cannot find root for $subject!");
exit(1);
}
$roots = array();
foreach ($certs as $c) {
$r = find_root($c);
$rs = parseKeyIdentifier($r['extensions']['subjectKeyIdentifier'], true);
$roots[$rs] = $r;
}
$pem = '';
foreach ($roots as $root) {
$pem .= trim($root['-']) . "\n\n";
}
file_put_contents('temp.pem', $pem);
$test = get_url('https://raw.githubusercontent.com/kildom/wp_downloader/main/test.js', 'temp.pem');
if ($test) {
echo($pem);
} else {
echo("Extracted certificate is invalid\n");
exit(1);
}
Signing JSON:
$data['signature'] = '---SIGNATURE---';
$data = json_encode($data, JSON_PRETTY_PRINT);
$data = str_replace('---SIGNATURE---', sign($data), $data);
Verify JSON:
$file = '...';
$data = json_decode($file);
$file = str_replace($data['signature'], '---SIGNATURE---', $file);
verify($data['signature'], $file);
With this following levels of cacert workarounds can be used:
Done in v0.0.5
Create a new orphan branch
releases
containing release information. It will have following files:info.json
- information about newest release and certificates:wp_downlaoder.php
cacert.pem
README.md
If this will be implemented, following thinks can be removed from the source code:
Reading release information consist of following steps:
info.json
info.json
Action running on schedule will (following step should also be in the release action):
.sha1
file contains different hash than in json, else use cacert from the last commit,releases
branch if something was updated.