cose-kit
Version:
**DEPRECATED:** Use [@auth0/cose](https://www.npmjs.com/package/@auth0/cose).
103 lines (102 loc) • 4.45 kB
JavaScript
import { SignatureBase } from './SignatureBase.js';
import { COSEBase } from './COSEBase.js';
import { UnprotectedHeaders, ProtectedHeaders, AlgorithmNames, Headers } from '../headers.js';
import sign from '#runtime/sign.js';
import { encoder, addExtension } from '../cbor.js';
import { decode } from './decode.js';
import * as errors from "../util/errors.js";
export class Sign extends COSEBase {
constructor(protectedHeaders, unprotectedHeaders, payload, signatures) {
super(protectedHeaders, unprotectedHeaders);
this.payload = payload;
this.signatures = signatures;
}
getContentForEncoding() {
return [
this.encodedProtectedHeaders,
this.unprotectedHeaders,
this.payload,
this.signatures.map((signature) => [
signature.protectedHeaders,
signature.unprotectedHeaders,
signature.signature
]),
];
}
async verify(key, options) {
for (const signature of this.signatures) {
try {
await signature.verify(key, this.encodedProtectedHeaders, this.payload, options);
return;
}
catch (err) { }
}
throw new errors.COSESignatureVerificationFailed();
}
async verifyX509(roots, options) {
for (const signature of this.signatures) {
try {
const { publicKey } = await signature.verifyX509Chain(roots);
await signature.verify(publicKey, this.encodedProtectedHeaders, this.payload, options);
return;
}
catch (err) { }
}
throw new errors.COSESignatureVerificationFailed();
}
static async sign(bodyProtectedHeader, unprotectedHeaders, payload, signers) {
const encodedProtectedHeaders = ProtectedHeaders.from(bodyProtectedHeader).encode();
const unprotectedHeadersMap = UnprotectedHeaders.from(unprotectedHeaders).esMap;
const signatures = await Promise.all(signers.map(async ({ key, protectedHeaders, unprotectedHeaders }) => {
return Signature.sign(encodedProtectedHeaders, protectedHeaders, unprotectedHeaders, payload, key);
}));
return new Sign(encodedProtectedHeaders, unprotectedHeadersMap, payload, signatures);
}
static decode(cose) {
return decode(cose, Sign);
}
}
Sign.tag = 98;
export class Signature extends SignatureBase {
constructor(protectedHeaders, unprotectedHeaders, signature) {
super(protectedHeaders, unprotectedHeaders, signature);
this.unprotectedHeaders = unprotectedHeaders;
this.signature = signature;
}
static Signature(bodyProtectedHeaders, protectedHeaders, applicationHeaders, payload) {
return encoder.encode([
'Signature',
bodyProtectedHeaders || new Uint8Array(),
protectedHeaders || new Uint8Array(),
applicationHeaders || new Uint8Array(),
payload,
]);
}
async verify(key, bodyProtectedHeaders, payload, options) {
const toBeSigned = Signature.Signature(bodyProtectedHeaders, this.encodedProtectedHeaders, new Uint8Array(), payload);
await this.internalVerify(toBeSigned, key, options);
}
static async sign(bodyProtectedHeaders, protectedHeaders, unprotectedHeaders, payload, key) {
const wProtectedHeaders = ProtectedHeaders.from(protectedHeaders);
const alg = AlgorithmNames.get(wProtectedHeaders.get(Headers.Algorithm));
const encodedProtectedHeaders = wProtectedHeaders.encode();
const unprotectedHeadersMapped = UnprotectedHeaders.from(unprotectedHeaders).esMap;
const toBeSigned = Signature.Signature(bodyProtectedHeaders, encodedProtectedHeaders, new Uint8Array(), payload);
if (!alg) {
throw new Error('The alg header must be set.');
}
const signature = await sign(alg, key, toBeSigned);
return new Signature(encodedProtectedHeaders, unprotectedHeadersMapped, signature);
}
}
addExtension({
Class: Sign,
tag: Sign.tag,
encode(instance, encode) {
return encode(instance.getContentForEncoding());
},
decode: (data) => {
const signatures = data[3].map(signature => new Signature(signature[0], signature[1], signature[2]));
return new Sign(data[0], data[1], data[2], signatures);
}
});