You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1443 lines
84 KiB

<!doctype html>
<head>
<link rel="stylesheet" href="css/style.v2.css">
<link rel="stylesheet" href="css/topnav.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="https://www.pathcheck.org/hubfs/Favicon.png">
<title>EU's Digital Green Certificate Payloads</title>
</head>
<body>
<div class="topnav">
<div class="topnavContainer">
<a class="active" href="index.html">Signers</a>
<a href="verify.html"><span class="xs-hidden">Universal </span>Verifier</a>
<a class="xs-hidden" href="debug.html">QR Debugger</a>
<a class="xs-hidden" href="https://github.com/Path-Check/paper-cred-demo">Source Code</a>
<a href="https://github.com/Path-Check/paper-cred"><span class="xs-hidden"> QR </span>Specs</a>
<a href="http://vaccine-docs.pathcheck.org"><span class="xs-hidden">Vaccine </span>Docs</a>
<a class="xs-hidden" href="http://pathcheck.org">About PathCheck</a>
</div>
</div>
<div class="subnav">
<div class="subnavContainer">
<a href="index.v5.html">PCF<span class="xs-hidden">'s 4 QRs</span></a>
<a class="active" href="eu.dgc.html">EU<span class="xs-hidden"> Green Pass</span></a>
<a href="icao.html">ICAO<span class="xs-hidden"> Seals</span></a>
<a href="cowin.html">DIVOC<span class="xs-hidden">/India</span></a>
<a href="liberty.html">IBM/NY<span class="xs-hidden"> Excelsior</span></a>
<a href="opencerta.html"><span class="xs-hidden">Open</span>Certa</a>
<a href="vial.html">Vial<span class="xs-hidden"> Label</span></a>
<a href="us.ma.id.html"><span class="xs-hidden">Mass </span>ID</a>
<a href="banknote.html">Cash<span class="xs-hidden"> Bills</span></a>
</div>
</div>
<div class="center">
<h1>EU's Digital Green Certificate Payloads</h1>
<div class="full-div">
<div class="third">
<h4>Immunization</h4>
<table>
<tr><td>Fam Name</td><td><input id="qr-vax-nam-fn" type="text" placeholder=""/></td></tr>
<tr><td>Given Name</td><td><input id="qr-vax-nam-gn" type="text" placeholder=""/></td></tr>
<tr><td>Std Family</td><td><input id="qr-vax-nam-fnt" type="text" placeholder=""/></td></tr>
<tr><td>Std Given</td><td><input id="qr-vax-nam-gnt" type="text" placeholder=""/></td></tr>
<tr><td>DoB</td><td><input id="qr-vax-dob-date" type="text" placeholder=""/></td></tr>
<tr><td>Disease</td><td><input id="qr-vax-tg" type="text" placeholder=""/></td></tr>
<tr><td>Prophylaxis</td><td><input id="qr-vax-vp" type="text" placeholder=""/></td></tr>
<tr><td>Product</td><td><input id="qr-vax-mp" type="text" placeholder=""/></td></tr>
<tr><td>Manuf</td><td><input id="qr-vax-ma" type="text" placeholder=""/></td></tr>
<tr><td>Dose #</td><td><input id="qr-vax-dn" type="text" placeholder=""/></td></tr>
<tr><td>Doses</td><td><input id="qr-vax-sd" type="text" placeholder=""/></td></tr>
<tr><td>Date</td><td><input id="qr-vax-dt-date" type="text" placeholder=""/></td></tr>
<tr><td>Country</td><td><input id="qr-vax-co" type="text" placeholder=""/></td></tr>
<tr><td>Issuer</td><td><input id="qr-vax-is" type="text" placeholder=""/></td></tr>
<tr><td>Cert ID</td><td><input id="qr-vax-ci" type="text" placeholder=""/></td></tr>
</table>
</div>
<div class="third">
<h4>COVID Test</h4>
<table>
<tr><td>Fam Name</td><td><input id="qr-test-nam-fn" type="text" placeholder=""/></td></tr>
<tr><td>Given Name</td><td><input id="qr-test-nam-gn" type="text" placeholder=""/></td></tr>
<tr><td>Std Family</td><td><input id="qr-test-nam-fnt" type="text" placeholder=""/></td></tr>
<tr><td>Std Given</td><td><input id="qr-test-nam-gnt" type="text" placeholder=""/></td></tr>
<tr><td>DoB</td><td><input id="qr-test-dob-date" type="text" placeholder=""/></td></tr>
<tr><td>Disease</td><td><input id="qr-test-tg" type="text" placeholder=""/></td></tr>
<tr><td>Type</td><td><input id="qr-test-tt" type="text" placeholder=""/></td></tr>
<tr><td>Test Name</td><td><input id="qr-test-nm" type="text" placeholder=""/></td></tr>
<tr><td>Manuf</td><td><input id="qr-test-ma" type="text" placeholder=""/></td></tr>
<tr><td>Date Colect</td><td><input id="qr-test-sc-date" type="text" placeholder=""/></td></tr>
<tr><td>Date Result</td><td><input id="qr-test-dr-date" type="text" placeholder=""/></td></tr>
<tr><td>Result</td><td><input id="qr-test-tr" type="text" placeholder=""/></td></tr>
<tr><td>Centre</td><td><input id="qr-test-tc" type="text" placeholder=""/></td></tr>
<tr><td>Country</td><td><input id="qr-test-co" type="text" placeholder=""/></td></tr>
<tr><td>Issuer</td><td><input id="qr-test-is" type="text" placeholder=""/></td></tr>
<tr><td>Cert ID</td><td><input id="qr-test-ci" type="text" placeholder=""/></td></tr>
</table>
</div>
<div class="third">
<h4>Recovery</h4>
<table>
<tr><td>Fam Name</td><td><input id="qr-recov-nam-fn" type="text" placeholder=""/></td></tr>
<tr><td>Given Name</td><td><input id="qr-recov-nam-gn" type="text" placeholder=""/></td></tr>
<tr><td>Std Family</td><td><input id="qr-recov-nam-fnt" type="text" placeholder=""/></td></tr>
<tr><td>Std Given</td><td><input id="qr-recov-nam-gnt" type="text" placeholder=""/></td></tr>
<tr><td>DoB</td><td><input id="qr-recov-dob-date" type="text" placeholder=""/></td></tr>
<tr><td>Disease</td><td><input id="qr-recov-tg" type="text" placeholder=""/></td></tr>
<tr><td>Date 1st Pos</td><td><input id="qr-recov-fr-date" type="text" placeholder=""/></td></tr>
<tr><td>Valid From</td><td><input id="qr-recov-df-date" type="text" placeholder=""/></td></tr>
<tr><td>Valid Until</td><td><input id="qr-recov-du-date" type="text" placeholder=""/></td></tr>
<tr><td>Country</td><td><input id="qr-recov-co" type="text" placeholder=""/></td></tr>
<tr><td>Issuer</td><td><input id="qr-recov-is" type="text" placeholder=""/></td></tr>
<tr><td>Cert ID</td><td><input id="qr-recov-ci" type="text" placeholder=""/></td></tr>
</table>
</div>
<div class="quarter">
<h4>CRED Credentials</h4>
<label for="privkey">Private Key</label><br/>
<textarea id="privkey" rows="10" style="width: 100%;">-----BEGIN EC PARAMETERS-----
BgUrgQQACg==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIPWKbSezZMY1gCpvN42yaVv76Lo47FvSsVZpQl0a5lWRoAcGBSuBBAAK
oUQDQgAE6DeIun4EgMBLUmbtjQw7DilMJ82YIvOR2jz/IK0R/F7/zXY1z+gqvFXf
DcJqR5clbAYlO9lHmvb4lsPLZHjugQ==
-----END EC PRIVATE KEY-----</textarea>
<br><br>
<label for="pubkey">Public Key</label><br/>
<textarea id="qr-link" rows="1" cols="30">1A9.PCF</textarea>
<h4>EU HC1 Credentials</h4>
<label for="privkey">P8 Private Key</label><br/>
<textarea id="privkeyEU" rows="10" style="width: 100%;">-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgZgp3uylFeCIIXozb
ZkCkSNr4DcLDxplZ1ax/u7ndXqahRANCAARkJeqyO85dyR+UrQ5Ey8EdgLyf9Nts
CrwORAj6T68/elL19aoISQDbzaNYJjdD77XdHtd+nFGTQVpB88wPTwgb
-----END PRIVATE KEY-----</textarea>
<br><br>
<label for="pubkey">PublicKey Certificate</label><br/>
<textarea id="pubkeyEU" rows="10" style="width: 100%;">-----BEGIN CERTIFICATE-----
MIIBYDCCAQYCEQCAG8uscdLb0ppaneNN5sB7MAoGCCqGSM49BAMCMDIxIzAhBgNV
BAMMGk5hdGlvbmFsIENTQ0Egb2YgRnJpZXNsYW5kMQswCQYDVQQGEwJGUjAeFw0y
MTA0MjcyMDQ3MDVaFw0yNjAzMTIyMDQ3MDVaMDYxJzAlBgNVBAMMHkRTQyBudW1i
ZXIgd29ya2VyIG9mIEZyaWVzbGFuZDELMAkGA1UEBhMCRlIwWTATBgcqhkjOPQIB
BggqhkjOPQMBBwNCAARkJeqyO85dyR+UrQ5Ey8EdgLyf9NtsCrwORAj6T68/elL1
9aoISQDbzaNYJjdD77XdHtd+nFGTQVpB88wPTwgbMAoGCCqGSM49BAMCA0gAMEUC
IQDvDacGFQO3tuATpoqf40CBv09nfglL3wh5wBwA1uA7lAIgZ4sOK2iaaTsFNqEN
AF7zi+d862ePRQ9Lwymr7XfwVm0=
-----END CERTIFICATE-----</textarea>
</div>
</div>
<br>
<div class="four-quarter">
<button class="qr-btn" onclick="generateQRCodes()">Create Certificates</button>
</div>
<div class="four-quarter">
<h2>PathCheck CRED-style URI</h2>
</div>
<div class="full-div">
<div class="third">
<h4 id="qr-vax-code-label" style="display: none;">Immunization QR</h4>
<canvas id="qr-vax-code"></canvas><br/>
<h4 id="qr-vax-pdf-label" style="display: none;">PDF 417 Format</h4>
<canvas id="qr-vax-pdf"></canvas><br/>
<pre id="qr-vax-result"></pre>
</div>
<div class="third">
<h4 id="qr-test-code-label" style="display: none;">Test QR</h4>
<canvas id="qr-test-code"></canvas><br/>
<h4 id="qr-test-pdf-label" style="display: none;">PDF 417 Format</h4>
<canvas id="qr-test-pdf"></canvas><br/>
<pre id="qr-test-result"></pre>
</div>
<div class="third">
<h4 id="qr-recov-code-label" style="display: none;">Recovery QR</h4>
<canvas id="qr-recov-code"></canvas><br/>
<h4 id="qr-recov-pdf-label" style="display: none;">PDF 417 Format</h4>
<canvas id="qr-recov-pdf"></canvas><br/>
<pre id="qr-recov-result"></pre>
</div>
<div class="quarter xs-hidden">
<label for="verify">Verify a QR Code</label>
<textarea id="qr-verify" rows="10" cols="33" placeholder="cred:type:version:signature:pubkey:payload"></textarea>
<br><br>
<button class="qr-btn" onclick="verifyQRCode()">Verify</button>
<br><br>
<pre id="qr-verify-result"></pre>
<pre id="qr-verify-verified"></pre>
</div>
</div>
<div class="four-quarter">
<h2>Original EU CBOR COSE ZLIB Base45 URI</h2>
</div>
<div class="full-div">
<div class="third">
<h4 id="qr-vax-orig-code-label" style="display: none;">Immunization QR</h4>
<canvas id="qr-vax-orig-code"></canvas><br/>
<h4 id="qr-vax-orig-pdf-label" style="display: none;">PDF 417 Format</h4>
<canvas id="qr-vax-orig-pdf"></canvas><br/>
<pre id="qr-vax-orig-result"></pre>
</div>
<div class="third">
<h4 id="qr-test-orig-code-label" style="display: none;">Test QR</h4>
<canvas id="qr-test-orig-code"></canvas><br/>
<h4 id="qr-test-orig-pdf-label" style="display: none;">PDF 417 Format</h4>
<canvas id="qr-test-orig-pdf"></canvas><br/>
<pre id="qr-test-orig-result"></pre>
</div>
<div class="third">
<h4 id="qr-recov-orig-code-label" style="display: none;">Recovery QR</h4>
<canvas id="qr-recov-orig-code"></canvas><br/>
<h4 id="qr-recov-orig-pdf-label" style="display: none;">PDF 417 Format</h4>
<canvas id="qr-recov-orig-pdf"></canvas><br/>
<pre id="qr-recov-orig-result"></pre>
</div>
<div class="quarter">
</div>
</div>
<div class="four-quarter">
<h2>Modified EU CBOR COSE ZLIB Base32 URI</h2>
</div>
<div class="full-div">
<div class="third">
<h4 id="qr-vax-orig32-code-label" style="display: none;">Immunization QR</h4>
<canvas id="qr-vax-orig32-code"></canvas><br/>
<h4 id="qr-vax-orig32-pdf-label" style="display: none;">PDF 417 Format</h4>
<canvas id="qr-vax-orig32-pdf"></canvas><br/>
<pre id="qr-vax-orig32-result"></pre>
</div>
<div class="third">
<h4 id="qr-test-orig32-code-label" style="display: none;">Test QR</h4>
<canvas id="qr-test-orig32-code"></canvas><br/>
<h4 id="qr-test-orig32-pdf-label" style="display: none;">PDF 417 Format</h4>
<canvas id="qr-test-orig32-pdf"></canvas><br/>
<pre id="qr-test-orig32-result"></pre>
</div>
<div class="third">
<h4 id="qr-recov-orig32-code-label" style="display: none;">Recovery QR</h4>
<canvas id="qr-recov-orig32-code"></canvas><br/>
<h4 id="qr-recov-orig32-pdf-label" style="display: none;">PDF 417 Format</h4>
<canvas id="qr-recov-orig32-pdf"></canvas><br/>
<pre id="qr-recov-orig32-result"></pre>
</div>
<div class="quarter xs-hidden">
</div>
</div>
<div class="four-quarter">
<h2>Modified Date As Integers EU CBOR COSE ZLIB Base45 URI</h2>
</div>
<div class="full-div">
<div class="third">
<h4 id="qr-vax-orig45DInt-code-label" style="display: none;">Immunization QR</h4>
<canvas id="qr-vax-orig45DInt-code"></canvas><br/>
<h4 id="qr-vax-orig45DInt-pdf-label" style="display: none;">PDF 417 Format</h4>
<canvas id="qr-vax-orig45DInt-pdf"></canvas><br/>
<pre id="qr-vax-orig45DInt-result"></pre>
</div>
<div class="third">
<h4 id="qr-test-orig45DInt-code-label" style="display: none;">Test QR</h4>
<canvas id="qr-test-orig45DInt-code"></canvas><br/>
<h4 id="qr-test-orig45DInt-pdf-label" style="display: none;">PDF 417 Format</h4>
<canvas id="qr-test-orig45DInt-pdf"></canvas><br/>
<pre id="qr-test-orig45DInt-result"></pre>
</div>
<div class="third">
<h4 id="qr-recov-orig45DInt-code-label" style="display: none;">Recovery QR</h4>
<canvas id="qr-recov-orig45DInt-code"></canvas><br/>
<h4 id="qr-recov-orig45DInt-pdf-label" style="display: none;">PDF 417 Format</h4>
<canvas id="qr-recov-orig45DInt-pdf"></canvas><br/>
<pre id="qr-recov-orig45DInt-result"></pre>
</div>
<div class="quarter xs-hidden">
</div>
</div>
<div class="four-quarter">
<h2>Comparison Tables</h2>
<h4>URI Size (in A/N bytes and in chars) and Time (in milliseconds)</h4>
</div>
<div class="full-div">
<div class="third">
<h4 style="text-align: center;">Immunization QR</h4>
<table class="comparison">
<tr>
<th style="text-align: right;">Tech</th>
<th style="text-align: right;">URI Bytes</th>
<th style="text-align: right;">URI Chars</th>
<th style="text-align: right;">Sign Time</th>
<th style="text-align: right;">Verify Time</th>
</th>
<tr>
<td style="text-align: right;">CRED</td>
<td style="text-align: right;" id="qr-vax-time-uri"></td>
<td style="text-align: right;" id="qr-vax-time-json"></td>
<td style="text-align: right;" id="qr-vax-time-sign"></td>
<td style="text-align: right;" id="qr-vax-time-verify"></td>
</tr>
<tr>
<td style="text-align: right;">HC1</td>
<td style="text-align: right;" id="qr-vax-orig-time-uri"></td>
<td style="text-align: right;" id="qr-vax-orig-time-json"></td>
<td style="text-align: right;" id="qr-vax-orig-time-sign"></td>
<td style="text-align: right;" id="qr-vax-orig-time-verify"></td>
</tr>
<tr>
<td style="text-align: right;">HC1<small><small><small>B32</small></small></small></td>
<td style="text-align: right;" id="qr-vax-orig32-time-uri"></td>
<td style="text-align: right;" id="qr-vax-orig32-time-json"></td>
<td style="text-align: right;" id="qr-vax-orig32-time-sign"></td>
<td style="text-align: right;" id="qr-vax-orig32-time-verify"></td>
</tr>
<tr><td style="text-align: right;">HC1<small><small><small>DInt</small></small></small></td>
<td style="text-align: right;" id="qr-vax-orig45DInt-time-uri"></td>
<td style="text-align: right;" id="qr-vax-orig45DInt-time-json"></td>
<td style="text-align: right;" id="qr-vax-orig45DInt-time-sign"></td>
<td style="text-align: right;" id="qr-vax-orig45DInt-time-verify"></td>
</tr>
</table>
</div>
<div class="third">
<h4 style="text-align: center;">Test QR</h4>
<table class="comparison">
<tr>
<th style="text-align: right;">Tech</th>
<th style="text-align: right;">URI Bytes</th>
<th style="text-align: right;">URI Chars</th>
<th style="text-align: right;">Sign Time</th>
<th style="text-align: right;">Verify Time</th>
</th>
<tr>
<td style="text-align: right;" >CRED</td>
<td style="text-align: right;" id="qr-test-time-uri"></td>
<td style="text-align: right;" id="qr-test-time-json"></td>
<td style="text-align: right;" id="qr-test-time-sign"></td>
<td style="text-align: right;" id="qr-test-time-verify"></td>
</tr>
<tr>
<td style="text-align: right;">HC1</td>
<td style="text-align: right;" id="qr-test-orig-time-uri"></td>
<td style="text-align: right;" id="qr-test-orig-time-json"></td>
<td style="text-align: right;" id="qr-test-orig-time-sign"></td>
<td style="text-align: right;" id="qr-test-orig-time-verify"></td>
</tr>
<tr>
<td style="text-align: right;">HC1<small><small><small>B32</small></small></small></td>
<td style="text-align: right;" id="qr-test-orig32-time-uri"></td>
<td style="text-align: right;" id="qr-test-orig32-time-json"></td>
<td style="text-align: right;" id="qr-test-orig32-time-sign"></td>
<td style="text-align: right;" id="qr-test-orig32-time-verify"></td>
</tr>
<tr><td style="text-align: right;">HC1<small><small><small>DInt</small></small></small></td>
<td style="text-align: right;" id="qr-test-orig45DInt-time-uri"></td>
<td style="text-align: right;" id="qr-test-orig45DInt-time-json"></td>
<td style="text-align: right;" id="qr-test-orig45DInt-time-sign"></td>
<td style="text-align: right;" id="qr-test-orig45DInt-time-verify"></td>
</tr>
</table>
</div>
<div class="third">
<h4 style="text-align: center;">Recovery QR</h4>
<table class="comparison">
<tr>
<th style="text-align: right;">Tech</th>
<th style="text-align: right;">URI Bytes</th>
<th style="text-align: right;">URI Chars</th>
<th style="text-align: right;">Sign Time</th>
<th style="text-align: right;">Verify Time</th>
</th>
<tr>
<td style="text-align: right;">CRED</td>
<td style="text-align: right;" id="qr-recov-time-uri"></td>
<td style="text-align: right;" id="qr-recov-time-json"></td>
<td style="text-align: right;" id="qr-recov-time-sign"></td>
<td style="text-align: right;" id="qr-recov-time-verify"></td>
</tr>
<tr>
<td style="text-align: right;">HC1</td>
<td style="text-align: right;" id="qr-recov-orig-time-uri"></td>
<td style="text-align: right;" id="qr-recov-orig-time-json"></td>
<td style="text-align: right;" id="qr-recov-orig-time-sign"></td>
<td style="text-align: right;" id="qr-recov-orig-time-verify"></td>
</tr>
<tr>
<td style="text-align: right;">HC1<small><small><small>B32</small></small></small></td>
<td style="text-align: right;" id="qr-recov-orig32-time-uri"></td>
<td style="text-align: right;" id="qr-recov-orig32-time-json"></td>
<td style="text-align: right;" id="qr-recov-orig32-time-sign"></td>
<td style="text-align: right;" id="qr-recov-orig32-time-verify"></td>
</tr>
<tr><td style="text-align: right;">HC1<small><small><small>DInt</small></small></small></td>
<td style="text-align: right;" id="qr-recov-orig45DInt-time-uri"></td>
<td style="text-align: right;" id="qr-recov-orig45DInt-time-json"></td>
<td style="text-align: right;" id="qr-recov-orig45DInt-time-sign"></td>
<td style="text-align: right;" id="qr-recov-orig45DInt-time-verify"></td>
</tr>
</table>
</div>
</div>
<div class="four-quarter">
<h4>QR Size in Bytes (bits * bits / 8)</h4>
</div>
<div class="full-div">
<div class="third">
<h4 style="text-align: center;">Immunization QR</h4>
<table class="comparison">
<tr>
<th style="text-align: right;">Tech</th>
<th style="text-align: right;">ECC 7%</th>
<th style="text-align: right;">ECC 15%</th>
<th style="text-align: right;">ECC 25%</th>
<th style="text-align: right;">ECC 30%</th>
</th>
<tr>
<td style="text-align: right;" id="qr-vax-comp-uri">CRED</td>
<td style="text-align: right;" id="qr-vax-comp-eccl"></td>
<td style="text-align: right;" id="qr-vax-comp-eccm"></td>
<td style="text-align: right;" id="qr-vax-comp-eccq"></td>
<td style="text-align: right;" id="qr-vax-comp-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-vax-orig-comp-uri">HC1</td>
<td style="text-align: right;" id="qr-vax-orig-comp-eccl"></td>
<td style="text-align: right;" id="qr-vax-orig-comp-eccm"></td>
<td style="text-align: right;" id="qr-vax-orig-comp-eccq"></td>
<td style="text-align: right;" id="qr-vax-orig-comp-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-vax-orig32-comp-uri">HC1<small><small><small>B32</small></small></small></td>
<td style="text-align: right;" id="qr-vax-orig32-comp-eccl"></td>
<td style="text-align: right;" id="qr-vax-orig32-comp-eccm"></td>
<td style="text-align: right;" id="qr-vax-orig32-comp-eccq"></td>
<td style="text-align: right;" id="qr-vax-orig32-comp-ecch"></td>
</tr>
<tr><td style="text-align: right;">HC1<small><small><small>DInt</small></small></small></td>
<td style="text-align: right;" id="qr-vax-orig45DInt-comp-eccl"></td>
<td style="text-align: right;" id="qr-vax-orig45DInt-comp-eccm"></td>
<td style="text-align: right;" id="qr-vax-orig45DInt-comp-eccq"></td>
<td style="text-align: right;" id="qr-vax-orig45DInt-comp-ecch"></td>
</tr>
</table>
</div>
<div class="third">
<h4 style="text-align: center;">Test QR</h4>
<table class="comparison">
<tr>
<th style="text-align: right;">Tech</th>
<th style="text-align: right;">ECC 7%</th>
<th style="text-align: right;">ECC 15%</th>
<th style="text-align: right;">ECC 25%</th>
<th style="text-align: right;">ECC 30%</th>
</th>
<tr>
<td style="text-align: right;" id="qr-test-comp-uri">CRED</td>
<td style="text-align: right;" id="qr-test-comp-eccl"></td>
<td style="text-align: right;" id="qr-test-comp-eccm"></td>
<td style="text-align: right;" id="qr-test-comp-eccq"></td>
<td style="text-align: right;" id="qr-test-comp-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-test-orig-comp-uri">HC1</td>
<td style="text-align: right;" id="qr-test-orig-comp-eccl"></td>
<td style="text-align: right;" id="qr-test-orig-comp-eccm"></td>
<td style="text-align: right;" id="qr-test-orig-comp-eccq"></td>
<td style="text-align: right;" id="qr-test-orig-comp-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-test-orig32-comp-uri">HC1<small><small><small>B32</small></small></small></td>
<td style="text-align: right;" id="qr-test-orig32-comp-eccl"></td>
<td style="text-align: right;" id="qr-test-orig32-comp-eccm"></td>
<td style="text-align: right;" id="qr-test-orig32-comp-eccq"></td>
<td style="text-align: right;" id="qr-test-orig32-comp-ecch"></td>
</tr>
<tr><td style="text-align: right;">HC1<small><small><small>DInt</small></small></small></td>
<td style="text-align: right;" id="qr-test-orig45DInt-comp-eccl"></td>
<td style="text-align: right;" id="qr-test-orig45DInt-comp-eccm"></td>
<td style="text-align: right;" id="qr-test-orig45DInt-comp-eccq"></td>
<td style="text-align: right;" id="qr-test-orig45DInt-comp-ecch"></td>
</tr>
</table>
</div>
<div class="third">
<h4 style="text-align: center;">Recovery QR</h4>
<table class="comparison">
<tr>
<th style="text-align: right;">Tech</th>
<th style="text-align: right;">ECC 7%</th>
<th style="text-align: right;">ECC 15%</th>
<th style="text-align: right;">ECC 25%</th>
<th style="text-align: right;">ECC 30%</th>
</th>
<tr>
<td style="text-align: right;" id="qr-recov-comp-uri">CRED</td>
<td style="text-align: right;" id="qr-recov-comp-eccl"></td>
<td style="text-align: right;" id="qr-recov-comp-eccm"></td>
<td style="text-align: right;" id="qr-recov-comp-eccq"></td>
<td style="text-align: right;" id="qr-recov-comp-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-recov-orig-comp-uri">HC1</td>
<td style="text-align: right;" id="qr-recov-orig-comp-eccl"></td>
<td style="text-align: right;" id="qr-recov-orig-comp-eccm"></td>
<td style="text-align: right;" id="qr-recov-orig-comp-eccq"></td>
<td style="text-align: right;" id="qr-recov-orig-comp-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-recov-orig32-comp-uri">HC1<small><small><small>B32</small></small></small></td>
<td style="text-align: right;" id="qr-recov-orig32-comp-eccl"></td>
<td style="text-align: right;" id="qr-recov-orig32-comp-eccm"></td>
<td style="text-align: right;" id="qr-recov-orig32-comp-eccq"></td>
<td style="text-align: right;" id="qr-recov-orig32-comp-ecch"></td>
</tr>
<tr><td style="text-align: right;">HC1<small><small><small>DInt</small></small></small></td>
<td style="text-align: right;" id="qr-recov-orig45DInt-comp-eccl"></td>
<td style="text-align: right;" id="qr-recov-orig45DInt-comp-eccm"></td>
<td style="text-align: right;" id="qr-recov-orig45DInt-comp-eccq"></td>
<td style="text-align: right;" id="qr-recov-orig45DInt-comp-ecch"></td>
</tr>
</table>
</div>
</div>
<div class="four-quarter">
<h4>QR Size (bits x bits)</h4>
</div>
<div class="full-div">
<div class="third">
<h4 style="text-align: center;">Immunization QR</h4>
<table class="comparison">
<tr>
<th style="text-align: right;">Tech</th>
<th style="text-align: right;">ECC 7%</th>
<th style="text-align: right;">ECC 15%</th>
<th style="text-align: right;">ECC 25%</th>
<th style="text-align: right;">ECC 30%</th>
</th>
<tr>
<td style="text-align: right;" id="qr-vax-bits-uri">CRED</td>
<td style="text-align: right;" id="qr-vax-bits-eccl"></td>
<td style="text-align: right;" id="qr-vax-bits-eccm"></td>
<td style="text-align: right;" id="qr-vax-bits-eccq"></td>
<td style="text-align: right;" id="qr-vax-bits-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-vax-orig-bits-uri">HC1</td>
<td style="text-align: right;" id="qr-vax-orig-bits-eccl"></td>
<td style="text-align: right;" id="qr-vax-orig-bits-eccm"></td>
<td style="text-align: right;" id="qr-vax-orig-bits-eccq"></td>
<td style="text-align: right;" id="qr-vax-orig-bits-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-vax-orig32-bits-uri">HC1<small><small><small>B32</small></small></small></td>
<td style="text-align: right;" id="qr-vax-orig32-bits-eccl"></td>
<td style="text-align: right;" id="qr-vax-orig32-bits-eccm"></td>
<td style="text-align: right;" id="qr-vax-orig32-bits-eccq"></td>
<td style="text-align: right;" id="qr-vax-orig32-bits-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-vax-orig45DInt-bits-uri">HC1<small><small><small>DInt</small></small></small></td>
<td style="text-align: right;" id="qr-vax-orig45DInt-bits-eccl"></td>
<td style="text-align: right;" id="qr-vax-orig45DInt-bits-eccm"></td>
<td style="text-align: right;" id="qr-vax-orig45DInt-bits-eccq"></td>
<td style="text-align: right;" id="qr-vax-orig45DInt-bits-ecch"></td>
</tr>
</table>
</div>
<div class="third">
<h4 style="text-align: center;">Test QR</h4>
<table class="comparison">
<tr>
<th style="text-align: right;">Tech</th>
<th style="text-align: right;">ECC 7%</th>
<th style="text-align: right;">ECC 15%</th>
<th style="text-align: right;">ECC 25%</th>
<th style="text-align: right;">ECC 30%</th>
</th>
<tr>
<td style="text-align: right;" id="qr-test-bits-uri">CRED</td>
<td style="text-align: right;" id="qr-test-bits-eccl"></td>
<td style="text-align: right;" id="qr-test-bits-eccm"></td>
<td style="text-align: right;" id="qr-test-bits-eccq"></td>
<td style="text-align: right;" id="qr-test-bits-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-test-orig-bits-uri">HC1</td>
<td style="text-align: right;" id="qr-test-orig-bits-eccl"></td>
<td style="text-align: right;" id="qr-test-orig-bits-eccm"></td>
<td style="text-align: right;" id="qr-test-orig-bits-eccq"></td>
<td style="text-align: right;" id="qr-test-orig-bits-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-test-orig32-bits-uri">HC1<small><small><small>B32</small></small></small></td>
<td style="text-align: right;" id="qr-test-orig32-bits-eccl"></td>
<td style="text-align: right;" id="qr-test-orig32-bits-eccm"></td>
<td style="text-align: right;" id="qr-test-orig32-bits-eccq"></td>
<td style="text-align: right;" id="qr-test-orig32-bits-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-test-orig45DInt-bits-uri">HC1<small><small><small>DInt</small></small></small></td>
<td style="text-align: right;" id="qr-test-orig45DInt-bits-eccl"></td>
<td style="text-align: right;" id="qr-test-orig45DInt-bits-eccm"></td>
<td style="text-align: right;" id="qr-test-orig45DInt-bits-eccq"></td>
<td style="text-align: right;" id="qr-test-orig45DInt-bits-ecch"></td>
</tr>
</table>
</div>
<div class="third">
<h4 style="text-align: center;">Recovery QR</h4>
<table class="comparison">
<tr>
<th style="text-align: right;">Tech</th>
<th style="text-align: right;">ECC 7%</th>
<th style="text-align: right;">ECC 15%</th>
<th style="text-align: right;">ECC 25%</th>
<th style="text-align: right;">ECC 30%</th>
</th>
<tr>
<td style="text-align: right;" id="qr-recov-bits-uri">CRED</td>
<td style="text-align: right;" id="qr-recov-bits-eccl"></td>
<td style="text-align: right;" id="qr-recov-bits-eccm"></td>
<td style="text-align: right;" id="qr-recov-bits-eccq"></td>
<td style="text-align: right;" id="qr-recov-bits-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-recov-orig-bits-uri">HC1</td>
<td style="text-align: right;" id="qr-recov-orig-bits-eccl"></td>
<td style="text-align: right;" id="qr-recov-orig-bits-eccm"></td>
<td style="text-align: right;" id="qr-recov-orig-bits-eccq"></td>
<td style="text-align: right;" id="qr-recov-orig-bits-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-recov-orig32-bits-uri">HC1<small><small><small>B32</small></small></small></td>
<td style="text-align: right;" id="qr-recov-orig32-bits-eccl"></td>
<td style="text-align: right;" id="qr-recov-orig32-bits-eccm"></td>
<td style="text-align: right;" id="qr-recov-orig32-bits-eccq"></td>
<td style="text-align: right;" id="qr-recov-orig32-bits-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-recov-orig45DInt-bits-uri">HC1<small><small><small>DInt</small></small></small></td>
<td style="text-align: right;" id="qr-recov-orig45DInt-bits-eccl"></td>
<td style="text-align: right;" id="qr-recov-orig45DInt-bits-eccm"></td>
<td style="text-align: right;" id="qr-recov-orig45DInt-bits-eccq"></td>
<td style="text-align: right;" id="qr-recov-orig45DInt-bits-ecch"></td>
</tr>
</table>
</div>
</div>
<div class="four-quarter">
<h4>Minimum Printed Size (in millimiters at 150 DPI)</h4>
</div>
<div class="full-div">
<div class="third">
<h4 style="text-align: center;">Immunization QR</h4>
<table class="comparison">
<tr>
<th style="text-align: right;">Tech</th>
<th style="text-align: right;">ECC 7%</th>
<th style="text-align: right;">ECC 15%</th>
<th style="text-align: right;">ECC 25%</th>
<th style="text-align: right;">ECC 30%</th>
</th>
<tr>
<td style="text-align: right;" id="qr-vax-size-uri">CRED</td>
<td style="text-align: right;" id="qr-vax-size-eccl"></td>
<td style="text-align: right;" id="qr-vax-size-eccm"></td>
<td style="text-align: right;" id="qr-vax-size-eccq"></td>
<td style="text-align: right;" id="qr-vax-size-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-vax-orig-size-uri">HC1</td>
<td style="text-align: right;" id="qr-vax-orig-size-eccl"></td>
<td style="text-align: right;" id="qr-vax-orig-size-eccm"></td>
<td style="text-align: right;" id="qr-vax-orig-size-eccq"></td>
<td style="text-align: right;" id="qr-vax-orig-size-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-vax-orig32-size-uri">HC1<small><small><small>B32</small></small></small></td>
<td style="text-align: right;" id="qr-vax-orig32-size-eccl"></td>
<td style="text-align: right;" id="qr-vax-orig32-size-eccm"></td>
<td style="text-align: right;" id="qr-vax-orig32-size-eccq"></td>
<td style="text-align: right;" id="qr-vax-orig32-size-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-vax-orig45DInt-size-uri">HC1<small><small><small>DInt</small></small></small></td>
<td style="text-align: right;" id="qr-vax-orig45DInt-size-eccl"></td>
<td style="text-align: right;" id="qr-vax-orig45DInt-size-eccm"></td>
<td style="text-align: right;" id="qr-vax-orig45DInt-size-eccq"></td>
<td style="text-align: right;" id="qr-vax-orig45DInt-size-ecch"></td>
</tr>
</table>
</div>
<div class="third">
<h4 style="text-align: center;">Test QR</h4>
<table class="comparison">
<tr>
<th style="text-align: right;">Tech</th>
<th style="text-align: right;">ECC 7%</th>
<th style="text-align: right;">ECC 15%</th>
<th style="text-align: right;">ECC 25%</th>
<th style="text-align: right;">ECC 30%</th>
</th>
<tr>
<td style="text-align: right;" id="qr-test-size-uri">CRED</td>
<td style="text-align: right;" id="qr-test-size-eccl"></td>
<td style="text-align: right;" id="qr-test-size-eccm"></td>
<td style="text-align: right;" id="qr-test-size-eccq"></td>
<td style="text-align: right;" id="qr-test-size-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-test-orig-size-uri">HC1</td>
<td style="text-align: right;" id="qr-test-orig-size-eccl"></td>
<td style="text-align: right;" id="qr-test-orig-size-eccm"></td>
<td style="text-align: right;" id="qr-test-orig-size-eccq"></td>
<td style="text-align: right;" id="qr-test-orig-size-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-test-orig32-size-uri">HC1<small><small><small>B32</small></small></small></td>
<td style="text-align: right;" id="qr-test-orig32-size-eccl"></td>
<td style="text-align: right;" id="qr-test-orig32-size-eccm"></td>
<td style="text-align: right;" id="qr-test-orig32-size-eccq"></td>
<td style="text-align: right;" id="qr-test-orig32-size-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-test-orig45DInt-size-uri">HC1<small><small><small>DInt</small></small></small></td>
<td style="text-align: right;" id="qr-test-orig45DInt-size-eccl"></td>
<td style="text-align: right;" id="qr-test-orig45DInt-size-eccm"></td>
<td style="text-align: right;" id="qr-test-orig45DInt-size-eccq"></td>
<td style="text-align: right;" id="qr-test-orig45DInt-size-ecch"></td>
</tr>
</table>
</div>
<div class="third">
<h4 style="text-align: center;">Recovery QR</h4>
<table class="comparison">
<tr>
<th style="text-align: right;">Tech</th>
<th style="text-align: right;">ECC 7%</th>
<th style="text-align: right;">ECC 15%</th>
<th style="text-align: right;">ECC 25%</th>
<th style="text-align: right;">ECC 30%</th>
</th>
<tr>
<td style="text-align: right;" id="qr-recov-size-uri">CRED</td>
<td style="text-align: right;" id="qr-recov-size-eccl"></td>
<td style="text-align: right;" id="qr-recov-size-eccm"></td>
<td style="text-align: right;" id="qr-recov-size-eccq"></td>
<td style="text-align: right;" id="qr-recov-size-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-recov-orig-size-uri">HC1</td>
<td style="text-align: right;" id="qr-recov-orig-size-eccl"></td>
<td style="text-align: right;" id="qr-recov-orig-size-eccm"></td>
<td style="text-align: right;" id="qr-recov-orig-size-eccq"></td>
<td style="text-align: right;" id="qr-recov-orig-size-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-recov-orig32-size-uri">HC1<small><small><small>B32</small></small></small></td>
<td style="text-align: right;" id="qr-recov-orig32-size-eccl"></td>
<td style="text-align: right;" id="qr-recov-orig32-size-eccm"></td>
<td style="text-align: right;" id="qr-recov-orig32-size-eccq"></td>
<td style="text-align: right;" id="qr-recov-orig32-size-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-recov-orig45DInt-size-uri">HC1<small><small><small>DInt</small></small></small></td>
<td style="text-align: right;" id="qr-recov-orig45DInt-size-eccl"></td>
<td style="text-align: right;" id="qr-recov-orig45DInt-size-eccm"></td>
<td style="text-align: right;" id="qr-recov-orig45DInt-size-eccq"></td>
<td style="text-align: right;" id="qr-recov-orig45DInt-size-ecch"></td>
</tr>
</table>
</div>
</div>
<div class="four-quarter">
<h4>Minimum Printed Size (in millimiters at 300 DPI)</h4>
</div>
<div class="full-div">
<div class="third">
<h4 style="text-align: center;">Immunization QR</h4>
<table class="comparison">
<tr>
<th style="text-align: right;">Tech</th>
<th style="text-align: right;">ECC 7%</th>
<th style="text-align: right;">ECC 15%</th>
<th style="text-align: right;">ECC 25%</th>
<th style="text-align: right;">ECC 30%</th>
</th>
<tr>
<td style="text-align: right;" id="qr-vax-size300-uri">CRED</td>
<td style="text-align: right;" id="qr-vax-size300-eccl"></td>
<td style="text-align: right;" id="qr-vax-size300-eccm"></td>
<td style="text-align: right;" id="qr-vax-size300-eccq"></td>
<td style="text-align: right;" id="qr-vax-size300-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-vax-orig-size300-uri">HC1</td>
<td style="text-align: right;" id="qr-vax-orig-size300-eccl"></td>
<td style="text-align: right;" id="qr-vax-orig-size300-eccm"></td>
<td style="text-align: right;" id="qr-vax-orig-size300-eccq"></td>
<td style="text-align: right;" id="qr-vax-orig-size300-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-vax-orig32-size300-uri">HC1<small><small><small>B32</small></small></small></td>
<td style="text-align: right;" id="qr-vax-orig32-size300-eccl"></td>
<td style="text-align: right;" id="qr-vax-orig32-size300-eccm"></td>
<td style="text-align: right;" id="qr-vax-orig32-size300-eccq"></td>
<td style="text-align: right;" id="qr-vax-orig32-size300-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-vax-orig45DInt-size300-uri">HC1<small><small><small>DInt</small></small></small></td>
<td style="text-align: right;" id="qr-vax-orig45DInt-size300-eccl"></td>
<td style="text-align: right;" id="qr-vax-orig45DInt-size300-eccm"></td>
<td style="text-align: right;" id="qr-vax-orig45DInt-size300-eccq"></td>
<td style="text-align: right;" id="qr-vax-orig45DInt-size300-ecch"></td>
</tr>
</table>
</div>
<div class="third">
<h4 style="text-align: center;">Test QR</h4>
<table class="comparison">
<tr>
<th style="text-align: right;">Tech</th>
<th style="text-align: right;">ECC 7%</th>
<th style="text-align: right;">ECC 15%</th>
<th style="text-align: right;">ECC 25%</th>
<th style="text-align: right;">ECC 30%</th>
</th>
<tr>
<td style="text-align: right;" id="qr-test-size300-uri">CRED</td>
<td style="text-align: right;" id="qr-test-size300-eccl"></td>
<td style="text-align: right;" id="qr-test-size300-eccm"></td>
<td style="text-align: right;" id="qr-test-size300-eccq"></td>
<td style="text-align: right;" id="qr-test-size300-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-test-orig-size300-uri">HC1</td>
<td style="text-align: right;" id="qr-test-orig-size300-eccl"></td>
<td style="text-align: right;" id="qr-test-orig-size300-eccm"></td>
<td style="text-align: right;" id="qr-test-orig-size300-eccq"></td>
<td style="text-align: right;" id="qr-test-orig-size300-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-test-orig32-size300-uri">HC1<small><small><small>B32</small></small></small></td>
<td style="text-align: right;" id="qr-test-orig32-size300-eccl"></td>
<td style="text-align: right;" id="qr-test-orig32-size300-eccm"></td>
<td style="text-align: right;" id="qr-test-orig32-size300-eccq"></td>
<td style="text-align: right;" id="qr-test-orig32-size300-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-test-orig45DInt-size300-uri">HC1<small><small><small>DInt</small></small></small></td>
<td style="text-align: right;" id="qr-test-orig45DInt-size300-eccl"></td>
<td style="text-align: right;" id="qr-test-orig45DInt-size300-eccm"></td>
<td style="text-align: right;" id="qr-test-orig45DInt-size300-eccq"></td>
<td style="text-align: right;" id="qr-test-orig45DInt-size300-ecch"></td>
</tr>
</table>
</div>
<div class="third">
<h4 style="text-align: center;">Recovery QR</h4>
<table class="comparison">
<tr>
<th style="text-align: right;">Tech</th>
<th style="text-align: right;">ECC 7%</th>
<th style="text-align: right;">ECC 15%</th>
<th style="text-align: right;">ECC 25%</th>
<th style="text-align: right;">ECC 30%</th>
</th>
<tr>
<td style="text-align: right;" id="qr-recov-size300-uri">CRED</td>
<td style="text-align: right;" id="qr-recov-size300-eccl"></td>
<td style="text-align: right;" id="qr-recov-size300-eccm"></td>
<td style="text-align: right;" id="qr-recov-size300-eccq"></td>
<td style="text-align: right;" id="qr-recov-size300-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-recov-orig-size300-uri">HC1</td>
<td style="text-align: right;" id="qr-recov-orig-size300-eccl"></td>
<td style="text-align: right;" id="qr-recov-orig-size300-eccm"></td>
<td style="text-align: right;" id="qr-recov-orig-size300-eccq"></td>
<td style="text-align: right;" id="qr-recov-orig-size300-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-recov-orig32-size300-uri">HC1<small><small><small>B32</small></small></small></td>
<td style="text-align: right;" id="qr-recov-orig32-size300-eccl"></td>
<td style="text-align: right;" id="qr-recov-orig32-size300-eccm"></td>
<td style="text-align: right;" id="qr-recov-orig32-size300-eccq"></td>
<td style="text-align: right;" id="qr-recov-orig32-size300-ecch"></td>
</tr>
<tr>
<td style="text-align: right;" id="qr-recov-orig45DInt-size300-uri">HC1<small><small><small>DInt</small></small></small></td>
<td style="text-align: right;" id="qr-recov-orig45DInt-size300-eccl"></td>
<td style="text-align: right;" id="qr-recov-orig45DInt-size300-eccm"></td>
<td style="text-align: right;" id="qr-recov-orig45DInt-size300-eccq"></td>
<td style="text-align: right;" id="qr-recov-orig45DInt-size300-ecch"></td>
</tr>
</table>
</div>
</div>
</div>
<script src="js/qrcode.min.js"></script>
<script src="js/libbcmath.js" type="text/javascript"></script>
<script src="js/bcmath.js" type="text/javascript"></script>
<script src="js/pdf417.js" type="text/javascript"></script>
<script src="js/pcf.sdk.min.js"></script>
<script src="js/eudgc.sdk.min.js"></script>
<script src="js/he.js"></script>
<script src="js/ajv7.min.js"></script>
<script src="js/json-beautify.min.js"></script>
<script src="js/pcf-utils.js"></script>
<script src="js/ui-utils.js"></script>
<script>
function e(elem) { return document.getElementById(elem); }
function replacer(key, value) {
if(value instanceof Map) {
return {
dataType: 'Map',
value: Array.from(value.entries()), // or with spread: value: [...value]
};
} else {
return value;
}
}
function reviver(key, value) {
if(typeof value === 'object' && value !== null) {
if (value.Map) {
return new Map(value.Map);
}
}
return value;
}
function getValueArray(elemArray) {
const fields = elemArray.map(function(elemId) {
if (elemId.endsWith('-date')) {
// Sends dates always in seconds since epoch
return convertDate(e(elemId).value).toString();
}
return e(elemId).value;
})
return fields;
}
function convertDate(str) {
return new Date(str).getTime()/1000;
}
function clearQR(elemPrefix) {
e(elemPrefix+'-code').getContext('2d').clearRect(0, 0, e(elemPrefix+'-code').width, e(elemPrefix+'-code').height);
e(elemPrefix+'-result').innerHTML = "";
}
async function clear() {
clearQR('qr-vax');
clearQR('qr-test');
clearQR('qr-recov');
}
function signAndDisplayQR(elemPref, _type, _version, priKeyPEM, pubKeyId, payloadValueArray) {
const t0 = performance.now();
const uri = PCF.signAndPack(_type, _version, priKeyPEM, pubKeyId, payloadValueArray).then(uri => {
const t1 = performance.now();
PCFUtils.debugURI(uri).then( debugInfo => {
const params = { margin:0, width:e(elemPref+'-code').scrollWidth, errorCorrectionLevel: 'L', color: {dark: '#3654DD' }};
// Builds QR Element
QRCode.toCanvas(e(elemPref+'-code'), uri, params, function (error) {})
PDF417.draw(uri, e(elemPref+"-pdf"));
e(elemPref+"-code-label").style.display = '';
e(elemPref+"-pdf-label").style.display = '';
// Updates screen elements.
e(elemPref+"-result").innerHTML= debugInfo;
e(elemPref+"-time-sign").innerHTML = Math.round(t1-t0);
e(elemPref+"-time-uri").innerHTML = Math.round(uri.length * 5.5/8);
e(elemPref+"-time-json").innerHTML = Math.round(uri.length);
studyQR(uri, elemPref);
const v0 = performance.now();
PCF.unpackAndVerify(uri).then(result => {
const v1 = performance.now();
e(elemPref+"-time-verify").innerHTML=Math.round(v1-v0);
UIUtils.drawVerifiedSymbol(elemPref+'-code',result);
});
});
});
}
function signAndDisplayEUQR(elemPref, json, priKeyPEM, pubKeyPem) {
const t0 = performance.now();
EUDGC.makeCWT(json).then(cwt => {
EUDGC.signAndPack(cwt, pubKeyPem, priKeyPEM).then(uri => {
const t1 = performance.now();
displayEUQR(uri, elemPref, t1-t0, pubKeyPem)
});
});
}
function sign32AndDisplayEUQR(elemPref, json, priKeyPEM, pubKeyPem) {
const t0 = performance.now();
EUDGC.makeCWT(json).then(cwt => {
EUDGC.signAndPack32(cwt, pubKeyPem, priKeyPEM).then(uri => {
const t1 = performance.now();
displayEUQR(uri, elemPref, t1-t0, pubKeyPem);
});
});
}
function displayEUQR(uri, elemPref, deltaTime, pubKeyPem) {
const params = { margin:0, width:e(elemPref+'-code').scrollWidth, errorCorrectionLevel: 'L', color: {dark: '#3654DD' }};
// Builds QR Element
QRCode.toCanvas(e(elemPref+'-code'), uri, params, function (error) {})
PDF417.draw(uri, e(elemPref+"-pdf"));
e(elemPref+"-code-label").style.display = '';
e(elemPref+"-pdf-label").style.display = '';
// Updates screen elements.
e(elemPref+"-result").innerHTML=
"<span class='schema'>" + uri.substring(0,3) + "</span></a>:" +
"<span class='message'>" + uri.substring(4) + "</span><br>";
e(elemPref+"-result").innerHTML +=
"<pre>HC1:<span class='message'>Payload</span></pre>"
studyQR(uri, elemPref);
e(elemPref+"-time-sign").innerHTML=Math.round(deltaTime);
e(elemPref+"-time-uri").innerHTML = Math.round(uri.length * 5.5/8);
e(elemPref+"-time-json").innerHTML = Math.round(uri.length);
const v0 = performance.now();
EUDGC.unpackAndVerify(uri, pubKeyPem).then(verified => {
const v1 = performance.now();
e(elemPref+"-time-verify").innerHTML=Math.round(v1-v0);
UIUtils.drawVerifiedSymbol(elemPref+'-code',verified);
});
}
function studyQR(uri, elemPref) {
let qrQ = QRCode.create(uri, { margin:0, width:275, errorCorrectionLevel: 'Q', color: {dark: '#3654DD' }});
let qrH = QRCode.create(uri, { margin:0, width:275, errorCorrectionLevel: 'H', color: {dark: '#3654DD' }});
let qrM = QRCode.create(uri, { margin:0, width:275, errorCorrectionLevel: 'M', color: {dark: '#3654DD' }});
let qrL = QRCode.create(uri, { margin:0, width:275, errorCorrectionLevel: 'L', color: {dark: '#3654DD' }});
if (e(elemPref+"-comp-eccl")) {
e(elemPref+"-comp-eccl").innerHTML = qrSizeBytes(qrL);
e(elemPref+"-comp-eccm").innerHTML = qrSizeBytes(qrM);
e(elemPref+"-comp-eccq").innerHTML = qrSizeBytes(qrQ);
e(elemPref+"-comp-ecch").innerHTML = qrSizeBytes(qrH);
}
if (e(elemPref+"-bits-eccl")) {
e(elemPref+"-bits-eccl").innerHTML = qrSizeBits(qrL);
e(elemPref+"-bits-eccm").innerHTML = qrSizeBits(qrM);
e(elemPref+"-bits-eccq").innerHTML = qrSizeBits(qrQ);
e(elemPref+"-bits-ecch").innerHTML = qrSizeBits(qrH);
}
if (e(elemPref+"-size-eccl")) {
e(elemPref+"-size-eccl").innerHTML = qrSizeMillimiters(qrL, 150);
e(elemPref+"-size-eccm").innerHTML = qrSizeMillimiters(qrM, 150);
e(elemPref+"-size-eccq").innerHTML = qrSizeMillimiters(qrQ, 150);
e(elemPref+"-size-ecch").innerHTML = qrSizeMillimiters(qrH, 150);
}
if (e(elemPref+"-size300-eccl")) {
e(elemPref+"-size300-eccl").innerHTML = qrSizeMillimiters(qrL, 300);
e(elemPref+"-size300-eccm").innerHTML = qrSizeMillimiters(qrM, 300);
e(elemPref+"-size300-eccq").innerHTML = qrSizeMillimiters(qrQ, 300);
e(elemPref+"-size300-ecch").innerHTML = qrSizeMillimiters(qrH, 300);
}
}
function describe(qr) {
return qr.modules.size + "x" + qr.modules.size + " " + qrSizeBytes(qr) + " bytes ";
}
function qrSizeBytes(qr) {
return Math.round((qr.modules.size*qr.modules.size)/8)
}
function qrSizeBits(qr) {
return qr.modules.size + "x" + qr.modules.size;
}
function qrSizeMillimiters(qr, dpi) {
// 150 DPI Printer
// 3x3 printer dots per QR bit.
const side = Math.round(qr.modules.size * (25.4/(dpi/3)));
return side + "x" + side;
}
function generateQRCodes() {
clear();
// Where to Download the public key
const pubKeyLink = e("qr-link").value.trim().replace("http://","");
// PEM code of the private key
const priKeyPEM = e('privkey').value;
const vaccineArray = getValueArray(["qr-vax-nam-fn", "qr-vax-nam-gn", "qr-vax-nam-fnt", "qr-vax-nam-gnt", "qr-vax-dob-date", "qr-vax-tg", "qr-vax-vp", "qr-vax-mp", "qr-vax-ma", "qr-vax-dn", "qr-vax-sd", "qr-vax-dt-date", "qr-vax-co", "qr-vax-is", "qr-vax-ci"]);
signAndDisplayQR("qr-vax", "eu.dgc.vax","1", priKeyPEM, pubKeyLink, vaccineArray);
const testArray = getValueArray(["qr-test-nam-fn", "qr-test-nam-gn", "qr-test-nam-fnt", "qr-test-nam-gnt", "qr-test-dob-date", "qr-test-tg", "qr-test-tt", "qr-test-nm", "qr-test-ma", "qr-test-sc-date", "qr-test-dr-date", "qr-test-tr", "qr-test-tc", "qr-test-co", "qr-test-is", "qr-test-ci"]);
signAndDisplayQR("qr-test", "eu.dgc.test","1", priKeyPEM, pubKeyLink, testArray);
const recoveryArray = getValueArray(["qr-recov-nam-fn", "qr-recov-nam-gn", "qr-recov-nam-fnt", "qr-recov-nam-gnt", "qr-recov-dob-date", "qr-recov-tg", "qr-recov-fr-date", "qr-recov-df-date", "qr-recov-du-date", "qr-recov-co", "qr-recov-is", "qr-recov-ci"]);
signAndDisplayQR("qr-recov", "eu.dgc.recv","1", priKeyPEM, pubKeyLink, recoveryArray);
// PEM code of the private key
const priKeyEUPEM = e('privkeyEU').value;
const pubKeyEUPEM = e('pubkeyEU').value;
let vaxEU = {
"ver": "1.0.0",
"nam": {
"fn": e('qr-vax-nam-fn').value,
"gn": e('qr-vax-nam-gn').value,
"fnt": e('qr-vax-nam-fnt').value,
"gnt": e('qr-vax-nam-gnt').value,
},
"dob": e('qr-vax-dob-date').value,
"v": [
{
"tg": e('qr-vax-tg').value,
"vp": e('qr-vax-vp').value,
"mp": e('qr-vax-mp').value,
"ma": e('qr-vax-ma').value,
"dn": parseInt(e('qr-vax-dn').value),
"sd": parseInt(e('qr-vax-sd').value),
"dt": e('qr-vax-dt-date').value,
"co": e('qr-vax-co').value,
"is": e('qr-vax-is').value,
"ci": "urn:uvci:"+e('qr-vax-ci').value
}
]
};
let vaxEUDInt = {
"ver": "1.0.0",
"nam": {
"fn": e('qr-vax-nam-fn').value,
"gn": e('qr-vax-nam-gn').value,
"fnt": e('qr-vax-nam-fnt').value,
"gnt": e('qr-vax-nam-gnt').value,
},
"dob": convertDate(e('qr-vax-dob-date').value),
"v": [
{
"tg": e('qr-vax-tg').value,
"vp": e('qr-vax-vp').value,
"mp": e('qr-vax-mp').value,
"ma": e('qr-vax-ma').value,
"dn": parseInt(e('qr-vax-dn').value),
"sd": parseInt(e('qr-vax-sd').value),
"dt": convertDate(e('qr-vax-dt-date').value),
"co": e('qr-vax-co').value,
"is": e('qr-vax-is').value,
"ci": "urn:uvci:"+e('qr-vax-ci').value
}
]
};
signAndDisplayEUQR("qr-vax-orig", vaxEU, priKeyEUPEM, pubKeyEUPEM);
sign32AndDisplayEUQR("qr-vax-orig32", vaxEU, priKeyEUPEM, pubKeyEUPEM);
signAndDisplayEUQR("qr-vax-orig45DInt", vaxEUDInt, priKeyEUPEM, pubKeyEUPEM);
let testEU = {
"ver": "1.0.0",
"nam": {
"fn": e('qr-test-nam-fn').value,
"gn": e('qr-test-nam-gn').value,
"fnt": e('qr-test-nam-fnt').value,
"gnt": e('qr-test-nam-gnt').value,
},
"dob": e('qr-test-dob-date').value,
"t": [
{
"tg": e('qr-test-tg').value,
"tt": e('qr-test-tt').value,
"tr": e('qr-test-tr').value,
"ma": e('qr-test-ma').value,
"sc": e('qr-test-sc-date').value,
"dr": e('qr-test-dr-date').value,
"tc": e('qr-test-tc').value,
"co": e('qr-test-co').value,
"is": e('qr-test-is').value,
"ci": "urn:uvci:"+e('qr-test-ci').value
}
]
};
let testEUDInt = {
"ver": "1.0.0",
"nam": {
"fn": e('qr-test-nam-fn').value,
"gn": e('qr-test-nam-gn').value,
"fnt": e('qr-test-nam-fnt').value,
"gnt": e('qr-test-nam-gnt').value,
},
"dob": convertDate(e('qr-test-dob-date').value),
"t": [
{
"tg": e('qr-test-tg').value,
"tt": e('qr-test-tt').value,
"tr": e('qr-test-tr').value,
"ma": e('qr-test-ma').value,
"sc": convertDate(e('qr-test-sc-date').value),
"dr": convertDate(e('qr-test-dr-date').value),
"tc": e('qr-test-tc').value,
"co": e('qr-test-co').value,
"is": e('qr-test-is').value,
"ci": "urn:uvci:"+e('qr-test-ci').value
}
]
};
signAndDisplayEUQR("qr-test-orig", testEU, priKeyEUPEM, pubKeyEUPEM);
sign32AndDisplayEUQR("qr-test-orig32", testEU, priKeyEUPEM, pubKeyEUPEM);
signAndDisplayEUQR("qr-test-orig45DInt", testEUDInt, priKeyEUPEM, pubKeyEUPEM);
let recovEU = {
"ver": "1.0.0",
"nam": {
"fn": e('qr-recov-nam-fn').value,
"gn": e('qr-recov-nam-gn').value,
"fnt": e('qr-recov-nam-fnt').value,
"gnt": e('qr-recov-nam-gnt').value,
},
"dob": e('qr-recov-dob-date').value,
"r": [
{
"tg": e('qr-recov-tg').value,
"fr": e('qr-recov-fr-date').value,
"df": e('qr-recov-df-date').value,
"du": e('qr-recov-du-date').value,
"co": e('qr-recov-co').value,
"is": e('qr-recov-is').value,
"ci": "urn:uvci:"+e('qr-recov-ci').value
}
]
};
let recovEUDInt = {
"ver": "1.0.0",
"nam": {
"fn": e('qr-recov-nam-fn').value,
"gn": e('qr-recov-nam-gn').value,
"fnt": e('qr-recov-nam-fnt').value,
"gnt": e('qr-recov-nam-gnt').value,
},
"dob": convertDate(e('qr-recov-dob-date').value),
"r": [
{
"tg": e('qr-recov-tg').value,
"fr": convertDate(e('qr-recov-fr-date').value),
"df": convertDate(e('qr-recov-df-date').value),
"du": convertDate(e('qr-recov-du-date').value),
"co": e('qr-recov-co').value,
"is": e('qr-recov-is').value,
"ci": "urn:uvci:"+e('qr-recov-ci').value
}
]
};
signAndDisplayEUQR("qr-recov-orig", recovEU, priKeyEUPEM, pubKeyEUPEM);
sign32AndDisplayEUQR("qr-recov-orig32", recovEU, priKeyEUPEM, pubKeyEUPEM);
signAndDisplayEUQR("qr-recov-orig45DInt", recovEUDInt, priKeyEUPEM, pubKeyEUPEM);
}
function getEUPayload(cwt) {
if (cwt instanceof Map) {
return cwt.get(-260).get(1);
}
return cwt;
}
function schemaValidator() {
var ajv = new ajv7.default({strict: "log", validateFormats: false});
let client = new XMLHttpRequest();
client.open('GET', 'https://raw.githubusercontent.com/ehn-digital-green-development/ehn-dgc-schema/main/DGC.combined-schema.json', false);
client.setRequestHeader("Accept", "application/vnd.github.v3+json");
client.send();
const schema = JSON.parse(client.response);
delete schema['$schema'];
return ajv.compile(schema);
}
function verifyQRCode() {
if (e("qr-verify").value.startsWith('CRED:')) {
PCFUtils.debugParseURI(e("qr-verify").value).then(result => {
e("qr-verify-result").innerHTML = result;
});
PCFUtils.debugVerify(e("qr-verify").value).then(debug => {
e('qr-verify-verified').innerHTML = debug;
});
} else {
e("qr-verify-result").innerHTML = "Checking";
EUDGC.unpackAndVerify(e("qr-verify").value, e('pubkeyEU').value).then(json => {
const validator = schemaValidator();
const valid = validator(getEUPayload(json));
if (json) {
e("qr-verify-result").innerHTML = "Data: " + he.encode(beautify(json, replacer, 2, 80));
e('qr-verify-verified').innerHTML = "Signature Verified " + (valid? " and Schema is Valid" : " but Schema has errors " + JSON.stringify(validator.errors));
} else {
e('qr-verify-verified').innerHTML = "Could not Verify";
}
});
}
}
</script>
<script>
function fillTo(str, toSize) {
let missing = toSize - str.length;
if (missing == 0) return str;
return fillTo(str + Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, missing), toSize);
}
function loadDemo() {
e("qr-vax-nam-fn").value = "d'Arsøns - van Halen";
e("qr-vax-nam-gn").value = "François-Joan";
e("qr-vax-nam-fnt").value = "DARSONS<VAN<HALEN";
e("qr-vax-nam-gnt").value = "FRANCOIS<JOAN";
e("qr-vax-dob-date").value = "2009-02-28";
e("qr-vax-tg").value = "840539006";
e("qr-vax-vp").value = "1119349007";
e("qr-vax-mp").value = "EU/1/20/1528";
e("qr-vax-ma").value = "ORG-100030215";
e("qr-vax-dn").value = "2";
e("qr-vax-sd").value = "2";
e("qr-vax-dt-date").value = new Date().toJSON().slice(0, 10);
e("qr-vax-co").value = "NL";
e("qr-vax-is").value = "Ministry of VWS";
e("qr-vax-ci").value = "01:NL:PlA8UWS60Z4RZXVALl6GAZ";
e("qr-test-nam-fn").value = "d'Arsøns - van Halen";
e("qr-test-nam-gn").value = "François-Joan";
e("qr-test-nam-fnt").value = "DARSONS<VAN<HALEN";
e("qr-test-nam-gnt").value = "FRANCOIS<JOAN";
e("qr-test-dob-date").value = "2009-02-28";
e("qr-test-tg").value = "840539006";
e("qr-test-tt").value = "LP217198-3";
e("qr-test-nm").value = "COVID PCR";
e("qr-test-ma").value = "1232";
e("qr-test-sc-date").value = "2021-04-13T14:20:00+00:00";
e("qr-test-dr-date").value = "2021-04-13T14:40:01+00:00";
e("qr-test-tr").value = "260415000";
e("qr-test-tc").value = "GGD Fryslân, L-Heliconweg";
e("qr-test-co").value = "NL";
e("qr-test-is").value = "Ministry of VWS";
e("qr-test-ci").value = "01:NL:GGD/81AAH16AZ";
e("qr-recov-nam-fn").value = "d'Arsøns - van Halen";
e("qr-recov-nam-gn").value = "François-Joan";
e("qr-recov-nam-fnt").value = "DARSONS<VAN<HALEN";
e("qr-recov-nam-gnt").value = "FRANCOIS<JOAN";
e("qr-recov-dob-date").value = "2009-02-28";
e("qr-recov-tg").value = "840539006";
e("qr-recov-fr-date").value = "2021-04-21";
e("qr-recov-df-date").value = "2021-05-01";
e("qr-recov-du-date").value = "2021-10-21";
e("qr-recov-co").value = "NL";
e("qr-recov-is").value = "Ministry of VWS";
e("qr-recov-ci").value = "01:NL:LSP/REC/1289821";
}
function loadMax() {
e("qr-vax-nam-fn").value = fillTo("d'Arsøns - van Halen", 50);
e("qr-vax-nam-gn").value = fillTo("François-Joan", 50);
e("qr-vax-nam-fnt").value = fillTo("DARSONS<VAN<HALEN", 50);
e("qr-vax-nam-gnt").value = fillTo("FRANCOIS<JOAN", 50);
e("qr-vax-dob-date").value = "2009-02-28";
e("qr-vax-tg").value = "840539006";
e("qr-vax-vp").value = "1119349007";
e("qr-vax-mp").value = "EU/1/20/1528";
e("qr-vax-ma").value = "ORG-100030215";
e("qr-vax-dn").value = "2";
e("qr-vax-sd").value = "2";
e("qr-vax-dt-date").value = new Date().toJSON().slice(0, 10);
e("qr-vax-co").value = "NL";
e("qr-vax-is").value = fillTo("Ministry of VWS", 50);
e("qr-vax-ci").value = fillTo("01:NL:PlA8UWS60Z4RZXVALl6GAZ", 50);
e("qr-test-nam-fn").value = fillTo("d'Arsøns - van Halen", 50);
e("qr-test-nam-gn").value = fillTo("François-Joan", 50);
e("qr-test-nam-fnt").value = fillTo("DARSONS<VAN<HALEN", 50);
e("qr-test-nam-gnt").value = fillTo("FRANCOIS<JOAN", 50);
e("qr-test-dob-date").value = "2009-02-28";
e("qr-test-tg").value = "840539006";
e("qr-test-tt").value = "LP217198-3";
e("qr-test-nm").value = fillTo("COVID PCR", 50);
e("qr-test-ma").value = "1232";
e("qr-test-sc-date").value = "2021-04-13T14:20:00+00:00";
e("qr-test-dr-date").value = "2021-04-13T14:40:01+00:00";
e("qr-test-tr").value = "260415000";
e("qr-test-tc").value = fillTo("GGD Fryslân, L-Heliconweg", 50);
e("qr-test-co").value = "NL";
e("qr-test-is").value = fillTo("Ministry of VWS", 50);
e("qr-test-ci").value = fillTo("01:NL:GGD/81AAH16AZ", 50);
e("qr-recov-nam-fn").value = fillTo("d'Arsøns - van Halen", 50);
e("qr-recov-nam-gn").value = fillTo("François-Joan", 50);
e("qr-recov-nam-fnt").value = fillTo("DARSONS<VAN<HALEN", 50);
e("qr-recov-nam-gnt").value = fillTo("FRANCOIS<JOAN", 50);
e("qr-recov-dob-date").value = "2009-02-28";
e("qr-recov-tg").value = "840539006";
e("qr-recov-fr-date").value = "2021-04-21";
e("qr-recov-df-date").value = "2021-05-01";
e("qr-recov-du-date").value = "2021-10-21";
e("qr-recov-co").value = "NL";
e("qr-recov-is").value = fillTo("Ministry of VWS", 50);
e("qr-recov-ci").value = fillTo("01:NL:LSP/REC/1289821", 50);
}
loadDemo();
</script>
<script>
async function preloadKey() {
PCF.resolveKey(e("qr-link").value);
}
window.onload = function() {
preloadKey();
}
</script>
</body>
</html>