Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
Samuele Locatelli
2021-10-25 14:36:44 +02:00
21 changed files with 21550 additions and 0 deletions
Vendored
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
node_modules
+15
View File
@@ -0,0 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "pwa-chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:8080",
"webRoot": "${workspaceFolder}"
}
]
}
+11
View File
@@ -0,0 +1,11 @@
# qrcodegenerator
This utility is for generating QR Code for any text / url.
## clonning and Installation
```
git clone https://github.com/developedbysom/qrcodegenerator.git
cd qrcodegenerator
npm install
npm run start
```
+74
View File
@@ -0,0 +1,74 @@
const express = require("express");
const axios = require('axios');
const ejs = require("ejs");
const path = require("path");
const qrcode = require("qrcode");
const exp = require("constants");
const html5QrcodeScanner = require("html5-qrcode");
const { DCC } = require('dcc-utils/src');
const app = express();
const port = process.env.port || 3000;
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.set("view engine", "ejs");
app.set("views", path.join(__dirname, "view"));
app.use(express.static("public"));
app.get("/", (req, res, next) => {
res.render("index");
});
app.post("/scan", (req, res, next) => {
const input_text = req.body.cert;
DCC.fromRaw(input_text).then((dcc) => {
console.log(dcc.payload)
//console.log(dcc.raw)
res.status(200);
res.send(dcc.payload);
//console.log(dcc);
})
.catch(error =>{
res.status(500);
res.send('Error: invalid data');
});
});
app.post("/sendc19", (req, res, next) => {
const output_text = req.body.contenuto;
console.log(output_text);
const optionsf2 = {
method: 'POST',
// mode: 'no-cors',
body: output_text,
headers: {
'Content-Type': 'application/json'
}
};
axios
.post('https://ufficio.egalware.com/GPW/Api/api/VC19', output_text)
.then(res => {
console.log(`statusCode: ${res.status}`)
console.log(res)
})
.catch(error => {
console.error(error)
})
res.status(200);
res.send('Recorded');
});
app.listen(port, console.log(`Listening on port ${port}`));
+20987
View File
File diff suppressed because it is too large Load Diff
+24
View File
@@ -0,0 +1,24 @@
{
"name": "qrcodeapp",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index"
},
"keywords": [],
"author": "",
"proxy": "http://localhost:3000",
"license": "ISC",
"dependencies": {
"axios": "^0.23.0",
"dcc-utils": "^0.3.0",
"ejs": "^3.1.6",
"express": "^4.17.1",
"html5-qrcode": "^2.1.0",
"qrcode": "^1.4.4"
},
"devDependencies": {
"prettier": "2.4.1"
}
}
Binary file not shown.
+98
View File
@@ -0,0 +1,98 @@
const fs = require('fs');
const zlib = require('zlib');
const Jimp = require('jimp');
const jsQR = require('jsqr');
const base45 = require('base45');
const cbor = require('cbor');
const cose = require('cose-js');
const rs = require('jsrsasign');
const { verify, webcrypto, SignatureMismatchError } = require('cosette/build/sign');
class DCC {
static async fromRaw(certificateRaw) {
const dcc = new DCC();
dcc._raw = certificateRaw;
const base45Data = base45.decode(certificateRaw.slice(4));
dcc._coseRaw = zlib.inflateSync(base45Data);
const cborPayload = cbor.decodeFirstSync(dcc._coseRaw).value[2];
const jsonCBOR = cbor.decodeFirstSync(cborPayload);
dcc._payload = jsonCBOR.get(-260).get(1);
return dcc;
}
static async fromImage(certificateImagePath) {
const buffer = fs.readFileSync(certificateImagePath);
const image = await Jimp.read(buffer);
const code = jsQR(image.bitmap.data, image.bitmap.width, image.bitmap.height);
return DCC.fromRaw(code.data);
}
get raw() {
return this._raw;
}
get payload() {
return this._payload;
}
async checkSignature(signatureKey) {
const verifier = {
key: signatureKey,
};
return cose.sign.verify(this._coseRaw, verifier);
}
async checkSignatureWithCertificate(certificate) {
const key = rs.KEYUTIL.getKey(certificate);
let verifier;
if (key.type === 'EC') {
verifier = key.getPublicKeyXYHex();
} else if (key.type === 'RSA') {
const jwk = rs.KEYUTIL.getJWKFromKey(key);
verifier = {
n: Buffer.from(jwk.n, 'base64'),
e: Buffer.from(jwk.e, 'base64'),
};
} else {
throw new Error('Certificate not supported');
}
return cose.sign.verify(this._coseRaw, { key: verifier });
}
/**
*
* @param keys associative array of keys, [kid => {key}]
* @returns {Promise<boolean|*>} return a promise, if the certificate is validly signed with
* a listed key, return the key with infos about authority that signed it. If the certificate
* is not validly signed, return false. If the keys is not in list, throw Error.
*/
async checkSignatureWithKeysList(keys) {
let cert;
try {
await verify(this._coseRaw, async (kid) => {
cert = keys[kid.toString('base64')];
return {
key: await webcrypto.subtle.importKey(
'spki',
Buffer.from(cert.publicKeyPem, 'base64'),
cert.publicKeyAlgorithm,
true, ['verify'],
),
};
});
return cert;
} catch (e) {
if (e instanceof SignatureMismatchError) {
return false;
}
if (typeof cert === 'undefined') {
throw new Error('Cannot verify signature: the key that signed the certificate is not listed',
{ cause: e });
}
throw e;
}
}
}
module.exports = DCC;
+121
View File
@@ -0,0 +1,121 @@
function docReady(fn) {
// see if DOM is already available
if (document.readyState === "complete" || document.readyState === "interactive") {
// call on next available tick
setTimeout(fn, 1);
} else {
document.addEventListener("DOMContentLoaded", fn);
}
}
certClass = function(rawVal) {
this.cert = rawVal;
};
docReady(function() {
var resultContainer = document.getElementById('qr-reader-results');
var lastResult, countResults = 0;
var html5QrcodeScanner = new Html5QrcodeScanner(
"qr-reader", { fps: 20, qrbox: 250 });
function onScanSuccess(decodedText, decodedResult) {
if (decodedText !== lastResult) {
++countResults;
lastResult = decodedText;
input_text = 'HC1:6BFOXN%TS3DHPVO13J /G-/2YRVA.QKW8SFBXG4CH23IRM*4Z8EHLTKQC:3DCV4*XUA2PSGH.+HIMIBRU SITK292W7*RBT1KCGTHQSEQBKLP64-HQ/HQ3IRE+QJDO-B5ET42HPPEPHCR6W9FDON95U/3-58 KE2+GKHG:3D6JK9+GFKMWKN7JJEHGRHHIUJR.KL.KR+G/IKM*G1JJ*KMO-K3OM.IA.C8KRDL4O54O4IGUJKAHIYIABGEX3E1.BLEE$JDG2OFI9L+93NKF9E3-9TC90JA4E15IAXMFU*GZEG-8A%FGSKE MCTPI8%MDPIW7CR5KBBQFZMD11-97S75JWTE.S$7K0:JSCCV7J$%25I3HC31835AL5:4A93OHBIFT.EJDG3L*8B89T3CT7WJI4WCW9WQ$LNU3OU72CWQIU7JBW.22S+5WIA%5RR-ND6RBTE-*6LYQN440Q82TPS2PH1S4%7+V0Q3S0C70T6J3V3VH3Y4430G*5B0';
//console.log(input_text);
const myBody = new certClass(input_text);
const jsonBody= JSON.stringify(myBody);
// console.log(jsonBody);
// request options
const options = {
method: 'POST',
body: jsonBody,
headers: {
'Content-Type': 'application/json'
}
}
var obj='';
fetch('/scan', options).then(function (res) {
if (res.ok) {
return res.json();
// res => res.json();
// risposta = res.json();
// html5QrcodeScanner.clear();
// console.log(risposta);
// resultContainer.innerHTML += `<div style="background-color:green;text-align:center;padding:20px"><h1>Scansione corretta</h1> <h3> ${risposta.nam.fn} ${risposta.nam.gn} ${risposta.dob}</h3></div>`;
} else {
return Promise.reject(res);
}
})
.then(function (risposta)
{
html5QrcodeScanner.clear();
// console.log(risposta);
resultContainer.innerHTML += `<div style="background-color:green;text-align:center;padding:20px"><h1>Scansione corretta</h1> <h3> ${risposta.nam.fn} ${risposta.nam.gn} ${risposta.dob}</h3></div>`;
return risposta;
}
)
.then(function (data) {
// Store the post data to a variable
// post = data;
// contenuto = data;
var myObject = new Object();
myObject.contenuto = data;
const jsonBodyv2 = JSON.stringify(myObject);
const data2 = {
method: 'POST',
body: jsonBodyv2,
headers: {
'Content-Type': 'application/json'
}
}
// log 01
console.log('log1');
console.log(data2);
// log 02
console.log('log2');
console.log(jsonBodyv2);
// .then(res => console.log(data2));
// Fetch another API
return fetch('/sendc19', data2);
// .then(res => console.log(res));
}).then(function (response) {
if (response.ok) {
window.setTimeout(function(){location.reload()},5000);
return response;
} else {
return Promise.reject(response);
}
// }).then(function (data) {
// console.log(post, data);
}).catch(function (error) {
console.warn(error);
});
// fetch('/scan', options)
// .then(res => res.json())
// .then(res =>
// {
// html5QrcodeScanner.clear();
// console.log(res);
// resultContainer.innerHTML += `<div style="background-color:green;text-align:center;padding:20px"><h1>Scansione corretta</h1> <h3> ${res.nam.fn} ${res.nam.gn} ${res.dob}</h3></div>`;
// return fetch('/sendc19',res);
// //
// // this.dccress = res;
// })
// .catch(err => console.error(err));
}
}
// Optional callback for error, can be ignored.
function onScanError(qrCodeError) {
// This callback would be called in case of qr code scan error or setup error.
// You can avoid this callback completely, as it can be very verbose in nature.
}
html5QrcodeScanner.render(onScanSuccess, onScanError);
});
File diff suppressed because one or more lines are too long
+6
View File
@@ -0,0 +1,6 @@
const DCC = require('./dcc');
const Rule = require('./rule');
module.exports = {
DCC, Rule,
};
+60
View File
@@ -0,0 +1,60 @@
function docReady(fn) {
// see if DOM is already available
if (document.readyState === "complete" || document.readyState === "interactive") {
// call on next available tick
setTimeout(fn, 1);
} else {
document.addEventListener("DOMContentLoaded", fn);
}
}
certClass = function(rawVal) {
this.cert = rawVal;
};
docReady(function() {
var resultContainer = document.getElementById('qr-reader-results');
var lastResult, countResults = 0;
var html5QrcodeScanner = new Html5QrcodeScanner(
"qr-reader", { fps: 20, qrbox: 250 });
function onScanSuccess(decodedText, decodedResult) {
if (decodedText !== lastResult) {
++countResults;
lastResult = decodedText;
input_text = 'HC1:6BFOXN%TS3DHPVO13J /G-/2YRVA.QKW8SFBXG4CH23IRM*4Z8EHLTKQC:3DCV4*XUA2PSGH.+HIMIBRU SITK292W7*RBT1KCGTHQSEQBKLP64-HQ/HQ3IRE+QJDO-B5ET42HPPEPHCR6W9FDON95U/3-58 KE2+GKHG:3D6JK9+GFKMWKN7JJEHGRHHIUJR.KL.KR+G/IKM*G1JJ*KMO-K3OM.IA.C8KRDL4O54O4IGUJKAHIYIABGEX3E1.BLEE$JDG2OFI9L+93NKF9E3-9TC90JA4E15IAXMFU*GZEG-8A%FGSKE MCTPI8%MDPIW7CR5KBBQFZMD11-97S75JWTE.S$7K0:JSCCV7J$%25I3HC31835AL5:4A93OHBIFT.EJDG3L*8B89T3CT7WJI4WCW9WQ$LNU3OU72CWQIU7JBW.22S+5WIA%5RR-ND6RBTE-*6LYQN440Q82TPS2PH1S4%7+V0Q3S0C70T6J3V3VH3Y4430G*5B0';
//console.log(input_text);
const myBody = new certClass(input_text);
const jsonBody= JSON.stringify(myBody);
// console.log(jsonBody);
// request options
const options = {
method: 'POST',
body: jsonBody,
headers: {
'Content-Type': 'application/json'
}
}
var obj='';
fetch('/scan', options)
.then(res => res.json())
// .then(res => console.log(res))
.then(res =>
{
html5QrcodeScanner.clear();
console.log(res);
resultContainer.innerHTML += `<div style="background-color:green;text-align:center;padding:20px"><h1>Scansione corretta</h1> <h3> ${res.nam.fn} ${res.nam.gn} ${res.dob}</h3></div>`;
//window.setTimeout(function(){location.reload()},15000);
// this.dccress = res;
})
.catch(err => console.error(err));
}
}
// Optional callback for error, can be ignored.
function onScanError(qrCodeError) {
// This callback would be called in case of qr code scan error or setup error.
// You can avoid this callback completely, as it can be very verbose in nature.
}
html5QrcodeScanner.render(onScanSuccess, onScanError);
});
+34
View File
@@ -0,0 +1,34 @@
const fs = require('fs');
const certLogicJs = require('certlogic-js');
class Rule {
static fromFile(filePath, external = {}) {
return Rule.fromJSON(JSON.parse(fs.readFileSync(filePath)), external);
}
static fromJSON(ruleJSON, external = {}) {
const rule = new Rule();
rule._external = external;
rule._payload = ruleJSON;
return rule;
}
get payload() {
return this._payload;
}
getDescription(language = 'en') {
const description = this._payload.Description.find((element) => element.lang === language);
return description ? description.desc : null;
}
evaluateDCC(dcc, external = {}) {
const options = { ...this._external, ...external };
return certLogicJs.evaluate(this.payload.Logic, {
payload: dcc.payload,
external: options,
});
}
}
module.exports = Rule;
+3
View File
@@ -0,0 +1,3 @@
body {
background-color: rgb(66, 159, 235);
}
+3
View File
@@ -0,0 +1,3 @@
body {
background-color: rgb(13, 141, 9);
}
+29
View File
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Response scan</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="/styleok.css" type="text/css">
</head>
<body>
<script>
setTimeout(function(){
window.location.href = 'http://localhost:3000';
}, 5000);
</script>
<div class="container">
<h1>Scansione corretta</h1>
<h3><%=jsonBody%></h3>
<!-- <img src=<%=qr_code %> alt="QR Code"> -->
<br>
<!-- <a href="/" role="button" class="btn btn-primary">Back</a> -->
</div>
</body>
</html>
+33
View File
@@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>QR Code Reader Green Pass Check</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="/style.css" type="text/css">
<script src="/html5-qrcode.min.js"></script>
<script src="/html5-qrcode-demo.js"></script>
</head>
<body>
<div class="container">
<h1>QR Code Reader Green Pass Check</h1>
<hr>
<div style="width: 500px" id="qr-reader"></div>
<br>
<!-- <form action="/scan" method="POST" class="form">
<textarea name="text" id="text" cols="120" rows="10" placeholder="Enter URL or Text" required></textarea>
<button type="submit" class="btn btn-primary">Check QR Code</button>
</form> -->
<div id="qr-reader-results"></div>
</div>
</body>
</html>
+22
View File
@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>QR Code</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<div class="container">
<img src=<%=qr_code %> alt="QR Code">
<br>
<a href="/" role="button" class="btn btn-primary">Back</a>
</div>
</body>
</html>
+22
View File
@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>QR Code</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<div class="container">
<img src=<%=qr_code %> alt="QR Code">
<br>
<a href="/" role="button" class="btn btn-primary">Back</a>
</div>
</body>
</html>