Skip to content

Instantly share code, notes, and snippets.

@itc-lab
Last active January 17, 2022 12:03
Show Gist options
  • Save itc-lab/b27b87ed2157d23ef9c1a4f71c873fdd to your computer and use it in GitHub Desktop.
Save itc-lab/b27b87ed2157d23ef9c1a4f71c873fdd to your computer and use it in GitHub Desktop.
<?php
//verify QR code of Japanese COVID-19 vaccination certificate app
// https://spec.smarthealth.cards/examples/example-00-f-qr-code-numeric-value-0.txt
$shc =
"shc:/56762909524320603460292437404460312229595326546034602925407728043360287028647167452228092861333145643765314159064022030645045908564355034142454136403706366541713724123638030437562204673740753232392543344332605736010645293353123320242853503861415427430004753129732924613628592228745843637025633507624310445605276341230873773410384042310567070707557107456708120606570623663777033227585056600966652061117174674573052039356659081177056970202340093324411221033620704509340334726467084141553342105243565305117726236003330521350707280644115077311275690310252859522456650834302142030032421132356925364207640341547153233158256573404361230833427550287355370364073612617152257762554334416343592473506303250640723232755255224553615345283508034505715835543824640362752809742110292808262363330070672827105052096258577360225721657062351032403464112037593862616074377133321252633250456036590477732325236925540853264476722141625060067762414204690971254238066824724408560429331253305209115437341112115432637273272235114428647569653672234512286523392210043574710637564139651203320632115864330645577526363129506822397454221131362955556520732962772632113729236210713060617166542903672359353361406064457359396659096438076131446668670575607108610432300733774460560025267641305468504325341237666453750753127466352932402528406661571140042352723667640009716224095011767453691204746205704024595859401250577707075358002332050723250066113770014577047673320011127663106423774557605457453327093460560729346274592562703645075620044267387510507768385953326808311006586943413623095505586922122438246445563331303709345774";
// https://vc.vrs.digital.go.jp/issuer/.well-known/jwks.json
// keys.x5c[0]
$key =
"MIIByjCCAXGgAwIBAgIJAPZFN9WW4voaMAoGCCqGSM49BAMDMCIxIDAeBgNVBAMMF3ZjLnZycy5kaWdpdGFsLmdvLmpwIENBMB4XDTIxMTEyNTEyNTUxNloXDTIyMTEyNTEyNTUxNlowJjEkMCIGA1UEAwwbdmMudnJzLmRpZ2l0YWwuZ28uanAgSXNzdWVyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEViKBgZ0f3pQKv+tSz653HUtIzCS8TVSNu1Hwi0tKpSnTXXvtqkpcfYeAZ+SfvVk8SWNaTRDZ9wTNjb9c58v9l6OBizCBiDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIHgDAdBgNVHQ4EFgQUiIXKUyT93YdyqsIjE8i5I1z8w0IwHwYDVR0jBBgwFoAU0cYt0sPpuIDBt7a9PD3qs9mOu7EwLgYDVR0RBCcwJYYjaHR0cHM6Ly92Yy52cnMuZGlnaXRhbC5nby5qcC9pc3N1ZXIwCgYIKoZIzj0EAwMDRwAwRAIgEwVdLdbPqMYqEsVltnsm3bI/Z6eibgMwYaNVZiu0r2sCIFebHk1i6ghWOQn+Q0+t5F77fasgJ3Oc6NWx9I8AWjRM";
$jws = "";
for ($pos = 5; $pos < strlen($shc); $pos += 2) {
$jws .= chr(intval(substr($shc, $pos, 2)) + 45);
}
list($headb64, $bodyb64, $cryptob64) = explode(".", $jws);
$header = json_decode(base64url_decode($headb64), true);
$payload = base64url_decode($bodyb64);
$sig = base64url_decode($cryptob64);
echo "header: ";
print_json($header);
$body = $payload;
if ($header["zip"] == "DEF") {
$body = zlib_decode($body);
}
$body = json_decode($body, true);
echo "body: ";
print_json($body);
$public_key =
"-----BEGIN CERTIFICATE-----\n" .
chunk_split($key, 60, "\n") .
"-----END CERTIFICATE-----";
list($r, $s) = str_split($sig, strlen($sig) / 2);
$r = ltrim($r, "\x00");
$s = ltrim($s, "\x00");
if (ord($r[0]) > 0x7f) {
$r = "\x00" . $r;
}
if (ord($s[0]) > 0x7f) {
$s = "\x00" . $s;
}
$sig = encodeDER(0x30, encodeDER(0x02, $r) . encodeDER(0x02, $s));
$verified = openssl_verify(
"{$headb64}.{$bodyb64}",
$sig,
$public_key,
"sha256"
);
if ($verified === 1) {
echo "verified\n";
} elseif ($verified === 0) {
echo "unverified\n";
} else {
echo openssl_error_string() . "\n";
}
function base64url_decode($input)
{
$remainder = (4 - (strlen($input) % 4)) % 4;
$input .= str_repeat("=", $remainder);
return base64_decode(strtr($input, "-_", "+/"));
}
function encodeDER($type, $value)
{
$der = chr($type);
$der .= chr(strlen($value));
return $der . $value;
}
function print_json($array)
{
echo json_encode(
$array,
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT
) . "\n\n";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment