digital-covid-certificate-lib
Version:
A library to parse and verify Digital Covid Certificates (DCC)
82 lines • 3.74 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ChKeyStore = void 0;
const pvtsutils_1 = require("pvtsutils");
const x509_1 = require("@peculiar/x509");
class ChKeyStore {
constructor() {
}
verifyCertificateChain(args) {
return __awaiter(this, void 0, void 0, function* () {
const { jwt, rootCertificate } = args;
const trustChain = jwt.header.x5c.map(cert => new x509_1.X509Certificate(cert));
if (rootCertificate) {
trustChain.push(new x509_1.X509Certificate(rootCertificate));
}
for (let i = 0; i < trustChain.length; i++) {
const valid = yield trustChain[i].verify({ date: new Date(), publicKey: trustChain[i + 1] });
if (!valid) {
throw new Error("Invalid certificate.");
}
}
});
}
getKey(keyId) {
const keyData = this.keys.filter(key => key.keyId === keyId).pop();
return this.mapToCryptoKey(keyData);
}
loadKeys(loadingArgs) {
return __awaiter(this, void 0, void 0, function* () {
if (loadingArgs.verifySignature) {
yield this.verifyCertificateChain(loadingArgs);
yield this.verifyJwtSignature(loadingArgs);
}
this.keys = loadingArgs.jwt.payload.certs;
});
}
mapToCryptoKey(keyData) {
const format = "jwk";
keyData.kty = "RSA";
keyData.ext = true;
keyData.alg = keyData.alg === 'RS256' ? "PS256" : keyData.alg;
// RS256 is not known to WebCrypto Api
const toBase64Url = (str) => pvtsutils_1.Convert.ToBase64Url(pvtsutils_1.Convert.FromBase64(str));
keyData.e = toBase64Url(keyData.e);
keyData.n = toBase64Url(keyData.n);
const algorithm = {
name: "RSA-PSS",
// can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
hash: { name: "SHA-256" },
};
// whether the key is extractable (i.e. can be used in exportKey)
const extractable = false;
// "verify" for public key import, "sign" for private key imports
const keyUsages = ["verify"];
return crypto.subtle.importKey(format, keyData, algorithm, extractable, keyUsages);
}
verifyJwtSignature(arg) {
return __awaiter(this, void 0, void 0, function* () {
const { jwt } = arg;
const certificate = jwt.header.x5c.map(cert => new x509_1.X509Certificate(cert))[0];
const public_key = yield certificate.publicKey.export(crypto);
const valid = yield crypto.subtle.verify(public_key.algorithm, public_key, //from generateKey or importKey above
jwt.signature, //ArrayBuffer of the signature
jwt.toBeSigned //ArrayBuffer of the data
);
if (!valid) {
throw new Error("Invalid JWT.");
}
});
}
}
exports.ChKeyStore = ChKeyStore;
//# sourceMappingURL=ChKeyStore.js.map