eudgc
Version:
EuDGC (European Digital Green Certificate) handling in Javascript and Typescript
139 lines (115 loc) • 4.48 kB
HTML
<html lang="en">
<head>
<title>EuDGC Parser Sample</title>
<meta charset="utf-8" />
<style>
h1 {
margin: 2px;
}
body {
display: flex;
flex-direction: column;
margin: 2px;
font-family: Helvetica, sans-serif;
}
#info {
font-family: 'Courier New', Courier, monospace;
background-color: #eeeeee;
padding: 0.5rem;
margin-top: 1rem;
font-size: 11px;
overflow: auto;
}
</style>
</head>
<body>
<h1>EuDGC Parser Demo</h1>
<p>Scan your EuDGC Covid Vaccination QR-Code
<br>Demo for <a href="https://github.com/Scopevisio/eudgc">https://github.com/Scopevisio/eudgc</a>
/ Apache 2.0 licensed free javascript library by Scopevisio AG
</p>
<div>
<canvas id="canvas" style="width: 480px; height: 360px;"></canvas>
</div>
<pre id="info">
</div>
<script src="https://cdn.jsdelivr.net/npm/jsqr@1.4.0/dist/jsQR.min.js"></script>
<script src="eudgc.js"></script>
<script>
const canvas = document.getElementById("canvas")
const ctx = canvas.getContext("2d")
const video = document.createElement("video")
video.setAttribute("width", 400)
video.setAttribute("height", 300)
navigator.mediaDevices.getUserMedia({
video: { facingMode: "environment" }
}).then((stream) => {
video.srcObject = stream
video.setAttribute("playsinline", true) // for safari
video.play()
requestAnimationFrame(frame)
})
let payload = "" // the qrcode will end up here
const frame = async () => {
requestAnimationFrame(frame)
if (video.readyState != video.HAVE_ENOUGH_DATA) {
return
}
canvas.height = video.videoHeight
canvas.width = video.videoWidth
ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
const size = Math.min(canvas.width, canvas.height) / 1.6
const x = .5 * (canvas.width - size)
const y = .5 * (canvas.height - size)
const imageData = ctx.getImageData(x, y, size, size)
let code = jsQR(
imageData.data,
imageData.width,
imageData.height, {
inversionAttempts: "dontInvert",
})
const DEBUG_MANUALLY = false
if (DEBUG_MANUALLY && !code) {
code = {
// the italian test-certficate in textual form
data: "HC1:6BFOXN%TS3DHPVO13J /G-/2YRVA.Q/R82JD2FCJG96V75DOW%IY17EIHY P8L6IWM$S4U45P84HW6U/4:84LC6 YM::QQHIZC4.OI1RM8ZA.A5:S9MKN4NN3F85QNCY0O%0VZ001HOC9JU0D0HT0HB2PL/IB*09B9LW4T*8+DCMH0LDK2%KI*V AQ2%KYZPQV6YP8722XOE7:8IPC2L4U/6H1D31BLOETI0K/4VMA/.6LOE:/8IL882B+SGK*R3T3+7A.N88J4R$F/MAITHW$P7S3-G9++9-G9+E93ZM$96TV6QRR 1JI7JSTNCA7G6MXYQYYQQKRM64YVQB95326FW4AJOMKMV35U:7-Z7QT499RLHPQ15O+4/Z6E 6U963X7$8Q$HMCP63HU$*GT*Q3-Q4+O7F6E%CN4D74DWZJ$7K+ CZEDB2M$9C1QD7+2K3475J%6VAYCSP0VSUY8WU9SG43A-RALVMO8+-VD2PRPTB7S015SSFW/BE1S1EV*2Q396Q*4TVNAZHJ7N471FPL-CA+2KG-6YPPB7C%40F18N4"
}
}
if (code && code.data && payload != code.data) {
payload = code.data
// now the qrcode is inside the payload variable and we can show
// the contents of the eudgc certificate and also of the validation
// make a result structure
let result = {}
result.qrcode = payload
// try to parse the EuDGC Vaccination Qr-Code
try {
const certificate = await EuDgc_parse(payload?.trim())
result.eudgc = certificate
} catch (error) {
console.error("no eudgc certificate found: " + error)
result.eudgc = "No Vaccination Datastructure"
}
// "hacky" filter to only use DE certs
const exampleCertFilter = (certInfo) => { return certInfo.subject && certInfo.subject.match(/O.?=.?Robert Koch-Institut/) }
// try to validate the EuDGC Vaccination Qr-Code
try {
const certificate = await EuDgc_validate(payload?.trim())
/*
const certifcate = await EuDgc_validate(payload?.trim(), {
certFilter: (certInfo) => { return true; },
explicitCerts: explicitCerts,
});
*/
result.validationCertificate = certificate
} catch (error) {
console.error("no eudgc signed certificate found: " + error)
result.validation = "Invalid Signature"
}
// format into a buffer and print out the buffer
let buffer = JSON.stringify(result, null, 4)
document.getElementById("info").textContent = buffer
}
}
</script>
</html>