UNPKG

covid-certificate

Version:

Parse and verify a european digital covid certificate (dcc)

106 lines (105 loc) 3.48 kB
import { TestResult, } from "../health-certificate/HealthCertificate"; import { decode } from "cbor"; import { schema } from "../validate/dcc/DCC-json-schema"; import ChainValidator from "../validate/ChainValidator"; import PayloadValidator from "../validate/dcc/PayloadValidator"; import DccJsonValidator from "../validate/dcc/DccJsonValidator"; import { TestResultJSON } from "../health-certificate/jsonTypes"; import { extractAlgorithm, extractKid } from "../cose/header/headers"; import { translateAlgorithm, translateTarget, translateVaccineType, } from "./translate"; /** * Parse COSE message * * @param message */ export var parseCoseMessage = function (message) { // should be data as specified in https://github.com/ehn-dcc-development/hcert-spec var data = decode(message.getPayload()); // validate data in cose message var validator = new ChainValidator([ new PayloadValidator(), new DccJsonValidator(schema), ]); var validationResult = validator.validate(data); if (!validationResult.isValid()) { throw new Error("Data in COSE message not valid: " + validationResult.getMessage()); } var hcertData = data.get(-260).get(1); return { alg: translateAlgorithm(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: extractKid(message.getProtectedHeaders(), message.getUnprotectedHeaders()), recovered: convertRecoveredData(hcertData), tests: convertTestData(hcertData), vaccinations: convertVaccinationData(hcertData), version: hcertData.ver, }; }; /** * Convert recovered data into an array of RecoveredCertificate's * * @param data */ var convertRecoveredData = function (data) { if (!data.r) { return []; } return data.r.map(function (r) { return { id: r.ci, target: translateTarget(r.tg), firstDetectedDate: new Date(r.fr), countryOfTest: r.co, issuer: r.is, dateValidFrom: new Date(r.df), dateValidUntil: new Date(r.du), }; }); }; var convertVaccinationData = function (data) { if (!data.v) { return []; } return data.v.map(function (v) { return { target: translateTarget(v.tg), vaccineType: 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, }; }); }; var convertTestData = function (data) { if (!data.t) { return []; } return data.t.map(function (t) { return { target: translateTarget(t.tg), testType: t.tt, name: t.nm || "", manufacturer: t.ma || "", date: new Date(t.sc), result: t.tr === TestResultJSON.Detected ? TestResult.Detected : TestResult.Undetected, testingCentre: t.tc || "", country: t.co, issuer: t.is, id: t.ci, }; }); };