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.
 
 
 
 
 
 

342 lines
15 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>Vaccine Distribution Certificates Generator</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 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 class="active" 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>OpenCerta Credential</h1>
<div class="full-div">
<div class="third">
<h4>VC Overhead</h4>
<table>
<tr><td>Context</td><td><input id="qr-head-context" type="text" placeholder="https://www.w3.org/2018/credentials/v1"/></td></tr>
<tr><td>IssueDate</td><td><input id="qr-head-issuance-date" type="text" placeholder="Last Name ..."/></td></tr>
<tr><td>Type</td><td><input id="qr-head-type" type="text" placeholder="VerifiableCredential, Immunization"/></td></tr>
</table>
<h4>FHIR Overhead</h4>
<table>
<tr><td>Type</td><td><input id="qr-fhir-type" type="text" placeholder="fhir:Immunization"/></td></tr>
<tr><td>Context</td><td><input id="qr-fhir-context" type="text" placeholder="https://opencerta.org/certificate/v1/"></td></tr>
<tr><td>Status</td><td><input id="qr-fhir-status" type="text" placeholder="Completed"/></td></tr>
<tr><td>NotGiven</td><td><input id="qr-fhir-not-given" type="text" placeholder="false"/></td></tr>
<tr><td>VaxCode</td><td><input id="qr-fhir-vax-code" type="text" placeholder="AZD1222"/></td></tr>
<tr><td>VaxText</td><td><input id="qr-fhir-vax-code-text" type="text" placeholder="SARS-CoV-2"/></td></tr>
</table>
</div>
<div class="third">
<h4>Patient</h4>
<table>
<tr><td>FirstName</td><td><input id="qr-pat-firstname" type="text" placeholder="First Name ..."/></td></tr>
<tr><td>LastName</td><td><input id="qr-pat-lastname" type="text" placeholder="Last Name ..."/></td></tr>
<tr><td>Gender</td><td><input id="qr-pat-gender" type="text" placeholder="Gender ..."/></td></tr>
</table>
<h4>Location</h4>
<table>
<tr><td>City</td><td><input id="qr-location-city" type="text" placeholder="Somerville"/></td></tr>
<tr><td>State</td><td><input id="qr-location-state" type="text" placeholder="MA"/></td></tr>
<tr><td>Country</td><td><input id="qr-location-country" type="text" placeholder="USA"/></td></tr>
</table>
</div>
<div class="third">
<h4>Immunization</h4>
<table>
<tr><td>Date</td><td><input id="qr-immunization-date" type="text" placeholder=""/></td></tr>
<tr><td>Manuf</td><td><input id="qr-immunization-manuf" type="text" placeholder="AstraZeneca, ..."/></td></tr>
<tr><td>Product</td><td><input id="qr-immunization-product" type="text" placeholder="SARS-CoV-2"/></td></tr>
<tr><td>Lot#</td><td><input id="qr-immunization-lot" type="text" placeholder="012L20A, ..."/></td></tr>
<tr><td>Expiration</td><td><input id="qr-immunization-expiration" type="text" placeholder=""/></td></tr>
<tr><td>Pri Src</td><td><input id="qr-immunization-primary-source" type="text" placeholder="true"/></td></tr>
</table>
<h4>Practitioner</h4>
<table>
<tr><td>FirstName</td><td><input id="qr-practitioner-firstname" type="text" placeholder="First Name ..."/></td></tr>
<tr><td>LastName</td><td><input id="qr-practitioner-lastname" type="text" placeholder="Last Name ..."/></td></tr>
<tr><td>Prefix</td><td><input id="qr-practitioner-prefix" type="text" placeholder="Dr."/></td></tr>
</table>
</div>
<div class="quarter">
<h4>Credentials</h4>
<label for="privkey">Private Key</label><br/>
<textarea id="privkey" rows="10" cols="30">-----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">keys.pathcheck.org</textarea>
</div>
</div>
<div class="four-quarter">
<br>
<button class="qr-btn" onclick="generateQRCodes()">Generate Certificates</button>
<br>
</div>
<div class="full-div">
<div class="two-quarter">
<h4>PCF's Format</h4>
<canvas id="qr-certa-code"></canvas><br/>
<pre id="qr-certa-result"></pre>
<pre id="qr-certa-bytes" class="xs-hidden"></pre>
</div>
<div class="two-quarter">
<h4>Original OpenCerta Format</h4>
<img id="qr-certa-orig-code" width="100%" src='img/open-certa-original.png' style="display: none;"/>
<pre id="qr-certa-orig-result" style="display: none;">
{
"@context": "https://www.w3.org/2018/credentials/v1",
"type": ["VerifiableCredential", "Immunization"],
"issuanceDate": "2020-07-10T19:23:24Z",
"credentialSubject": {
"type": "fhir:Immunization",
"@context": "https://opencerta.org/certificate/v1",
"role": "fhir:treeRoot",
"Immunization.status": {
"value": "completed"
},
"Immunization.notGiven": {
"boolean": false
},
"Immunization.vaccineCode": {
"CodeableConcept.coding": [{
"index": 0,
"Coding.display": {
"value": "AZD1222"
}
}],
"CodeableConcept.text": {
"value": "SARS-CoV-2"
}
},
"Immunization.patient": {
"Patient.name": [{
"index": 0,
"HumanName.family": {
"value": "Donald"
},
"HumanName.given": [{
"index": 0,
"value": "Daisy"
}]
}],
"Patient.gender": {
"value": "female"
}
},
"Immunization.date": {
"date": "2020-07-10"
},
"Immunization.primarySource": {
"boolean": true
},
"Immunization.manufacturer": {
"Organization.name": {
"value": "AstraZeneca; The University of Oxford; IQVIA"
}
},
"Immunization.lotNumber": {
"value": "AAJN11K"
},
"Immunization.expirationDate": {
"date": "2021-07-09"
},
"Immunization.location": {
"Location.address": {
"Address.city": {
"value": "Houston"
},
"Address.state": {
"value": "TX"
},
"Address.country": {
"value": "US"
}
}
},
"Immunization.practitioner": [{
"index": 0,
"Practitioner.name": [{
"index": 0,
"HumanName.family": {
"value": "Careful"
},
"HumanName.given": [{
"index": 0,
"value": "Adam"
}],
"HumanName.prefix": [{
"index": 0,
"value": "Dr"
}]
}]
}]
},
"proof": {...
}
}
</pre>
<pre id="qr-certa-bytes" class="xs-hidden"></pre>
</div>
<div class="quarter xs-hidden">
<label for="verify">Verify a QR Code</small></label><br/>
<textarea id="qr-verify" rows="10" cols="30" 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>
<script src="js/qrcode.min.js"></script>
<script src="js/pcf-utils.js"></script>
<script src="js/ui-utils.js"></script>
<script src="js/pcf.sdk.min.js"></script>
<script>
function e(elem) { return document.getElementById(elem); }
function getValueArray(elemArray) {
const fields = elemArray.map(function(elemId) {
return e(elemId).value;
})
return fields;
}
function signAndDisplayQR(elemPref, _type, _version, priKeyPEM, pubKeyId, payloadValueArray) {
PCF.signAndPack(_type, _version, priKeyPEM, pubKeyId, payloadValueArray).then(uri => {
PCFUtils.debugURI(uri).then( debugInfo => {
UIUtils.drawsQR(elemPref, uri, debugInfo);
PCF.unpackAndVerify(uri).then(result => {
UIUtils.drawVerifiedSymbol(elemPref+'-code',result);
});
});
});
}
function generateQRCodes() {
// 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;
// Coupon QR
const certaArray = [
"qr-pat-firstname", "qr-pat-lastname", "qr-pat-gender",
"qr-immunization-date", "qr-immunization-manuf", "qr-immunization-product", "qr-immunization-lot", "qr-immunization-expiration", "qr-immunization-primary-source",
"qr-location-city", "qr-location-state", "qr-location-country",
"qr-practitioner-firstname", "qr-practitioner-lastname", "qr-practitioner-prefix",
"qr-head-context", "qr-head-issuance-date", "qr-head-type",
"qr-fhir-type", "qr-fhir-context", "qr-fhir-not-given", "qr-fhir-status", "qr-fhir-vax-code", "qr-fhir-vax-code-text"
];
signAndDisplayQR("qr-certa", "certa", "1", priKeyPEM, pubKeyLink, getValueArray(certaArray));
e("qr-certa-orig-code").style.display='block';
e("qr-certa-orig-result").style.display='block';
}
function verifyQRCode() {
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;
});
}
</script>
<script>
// Defaults
e("qr-immunization-date").value = new Date().toJSON().slice(0, 10).replaceAll("-","");
function loadDemo() {
e("qr-head-context").value = "https://www.w3.org/2018/credentials/v1";
e("qr-head-issuance-date").value = new Date().toJSON().slice(0, 10).replaceAll("-","");
e("qr-head-type").value = "VerifiableCredential, Immunization";
e("qr-fhir-type").value = "fhir:Immunization";
e("qr-fhir-context").value = "https://opencerta.org/certificate/v1/";
e("qr-fhir-not-given").value = "false";
e("qr-fhir-status").value = "Completed";
e("qr-fhir-vax-code").value = "AZD1222";
e("qr-fhir-vax-code-text").value = "SARS-CoV-2";
e("qr-pat-firstname").value = "Daisy";
e("qr-pat-lastname").value = "Donald";
e("qr-pat-gender").value = "Female";
e("qr-immunization-manuf").value = "AstraZeneca; The University of Oxford; IQVIA";
e("qr-immunization-product").value = "COVID19";
e("qr-immunization-lot").value = "AAJN11K";
e("qr-immunization-expiration").value = "20210709";
e("qr-immunization-primary-source").value = "true";
e("qr-location-city").value = "Houston";
e("qr-location-state").value = "TX";
e("qr-location-country").value = "USA";
e("qr-practitioner-firstname").value = "Adam";
e("qr-practitioner-lastname").value = "Careful";
e("qr-practitioner-prefix").value = "Dr.";
}
loadDemo();
</script>
<script>
async function preloadKey() {
PCF.resolveKey(e("qr-link").value);
}
window.onload = function() {
preloadKey();
}
</script>
</body>
</html>