covid-certificate
Version:
Parse and verify a european digital covid certificate (dcc)
113 lines (112 loc) • 4.03 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseCoseCertificate = void 0;
const HealthCertificate_1 = require("../health-certificate/HealthCertificate");
const cbor_1 = require("cbor");
const DCC_json_schema_1 = require("../validate/dcc/DCC-json-schema");
const ChainValidator_1 = __importDefault(require("../validate/ChainValidator"));
const PayloadValidator_1 = __importDefault(require("../validate/dcc/PayloadValidator"));
const DccJsonValidator_1 = __importDefault(require("../validate/dcc/DccJsonValidator"));
const jsonTypes_1 = require("../health-certificate/jsonTypes");
const headers_1 = require("../cose/header/headers");
const translate_1 = require("./translate");
/**
* Parse a single signed COSE message
*
* @param message
*/
const parseCoseCertificate = (message) => {
// should be data as specified in https://github.com/ehn-dcc-development/hcert-spec
const data = (0, cbor_1.decode)(message.getPayload());
// validate data in cose message
const validator = new ChainValidator_1.default([
new PayloadValidator_1.default(),
new DccJsonValidator_1.default(DCC_json_schema_1.schema),
]);
const validationResult = validator.validate(data);
if (!validationResult.isValid()) {
throw new Error("Data in COSE message not valid: " + validationResult.getMessage());
}
const hcertData = data.get(-260).get(1);
return {
alg: (0, translate_1.translateAlgorithm)((0, headers_1.extractAlgorithm)(message.getProtectedHeaders(), message.getUnprotectedHeaders())),
expirationDate: new Date(data.get(4) * 1000),
issuedAt: new Date(data.get(6) * 1000),
dateOfBirth: hcertData.dob,
name: {
surname: hcertData.nam.fnt,
givenName: hcertData.nam.gnt,
},
issuer: data.get(1),
kid: (0, headers_1.extractKid)(message.getProtectedHeaders(), message.getUnprotectedHeaders()),
recovered: convertRecoveredData(hcertData),
tests: convertTestData(hcertData),
vaccinations: convertVaccinationData(hcertData),
version: hcertData.ver,
};
};
exports.parseCoseCertificate = parseCoseCertificate;
/**
* Convert recovered data into an array of RecoveredCertificate's
*
* @param data
*/
const convertRecoveredData = (data) => {
if (!data.r) {
return [];
}
return data.r.map((r) => {
return {
id: r.ci,
target: (0, translate_1.translateTarget)(r.tg),
firstDetectedDate: new Date(r.fr),
countryOfTest: r.co,
issuer: r.is,
dateValidFrom: new Date(r.df),
dateValidUntil: new Date(r.du),
};
});
};
const convertVaccinationData = (data) => {
if (!data.v) {
return [];
}
return data.v.map((v) => {
return {
target: (0, translate_1.translateTarget)(v.tg),
vaccineType: (0, translate_1.translateVaccineType)(v.vp),
medicinalProduct: v.mp,
manufacturer: v.ma,
doseNumber: v.dn,
totalDoses: v.sd,
date: new Date(v.dt),
country: v.co,
issuer: v.is,
id: v.ci,
};
});
};
const convertTestData = (data) => {
if (!data.t) {
return [];
}
return data.t.map((t) => {
return {
target: (0, translate_1.translateTarget)(t.tg),
testType: t.tt,
name: t.nm || "",
manufacturer: t.ma || "",
date: new Date(t.sc),
result: t.tr === jsonTypes_1.TestResultJSON.Detected
? HealthCertificate_1.TestResult.Detected
: HealthCertificate_1.TestResult.Undetected,
testingCentre: t.tc || "",
country: t.co,
issuer: t.is,
id: t.ci,
};
});
};