cose-kit
Version:
**DEPRECATED:** Use [@auth0/cose](https://www.npmjs.com/package/@auth0/cose).
77 lines (76 loc) • 3.16 kB
JavaScript
import verify from "#runtime/verify.js";
import { importX509 } from 'jose';
import { pkijs } from '#runtime/pkijs.js';
import { decodeBase64 } from '#runtime/base64.js';
import { X509InvalidCertificateChain, X509NoMatchingCertificate } from '../util/errors.js';
import { certToPEM, pemToCert } from '../util/cert.js';
import { AlgorithmNames, Headers } from '../headers.js';
import { COSEBase } from './COSEBase.js';
import * as errors from "../util/errors.js";
import validateAlgorithms from '../lib/validate_algorithms.js';
export class SignatureBase extends COSEBase {
constructor(protectedHeaders, unprotectedHeaders, signature) {
super(protectedHeaders, unprotectedHeaders);
this.signature = signature;
}
get alg() {
return this.protectedHeaders.get(Headers.Algorithm) ||
this.unprotectedHeaders.get(Headers.Algorithm);
}
get algName() {
return this.alg ? AlgorithmNames.get(this.alg) : undefined;
}
get kid() {
return this.protectedHeaders.get(Headers.KeyID) ||
this.unprotectedHeaders.get(Headers.KeyID);
}
get x5bag() {
const x5bag = this.protectedHeaders.get(Headers.X5Bag) ||
this.unprotectedHeaders.get(Headers.X5Bag);
if (!x5bag) {
return;
}
return Array.isArray(x5bag) ? x5bag : [x5bag];
}
get x5chain() {
const x5chain = this.protectedHeaders.get(Headers.X5Chain) ||
this.unprotectedHeaders.get(Headers.X5Chain);
if (!x5chain) {
return;
}
return Array.isArray(x5chain) ? x5chain : [x5chain];
}
async verifyX509Chain(caRoots) {
const { x5chain } = this;
if (!x5chain || x5chain.length === 0) {
throw new X509NoMatchingCertificate();
}
const chainEngine = new pkijs.CertificateChainValidationEngine({
certs: x5chain.map((c) => pkijs.Certificate.fromBER(c)),
trustedCerts: caRoots.map((c) => pkijs.Certificate.fromBER(decodeBase64(pemToCert(c)))),
});
const chain = await chainEngine.verify();
if (!chain.result) {
throw new X509InvalidCertificateChain(chain.resultMessage);
}
const x509Cert = certToPEM(x5chain[0]);
const publicKey = await importX509(x509Cert, this.algName);
return { publicKey, raw: x5chain[0] };
}
async internalVerify(payload, key, options) {
if (!this.alg || !this.algName || !AlgorithmNames.has(this.alg)) {
throw new errors.COSEInvalid(`Unsupported algorithm ${this.alg}`);
}
const algorithms = options && validateAlgorithms('algorithms', options.algorithms);
if (algorithms && !algorithms.has(this.alg)) {
throw new errors.COSEAlgNotAllowed(`[${Headers.Algorithm}] (algorithm) Header Parameter not allowed`);
}
if (typeof key === 'function') {
key = await key(this);
}
const isValid = await verify(this.algName, key, this.signature, payload);
if (!isValid) {
throw new errors.COSESignatureVerificationFailed();
}
}
}