cose-kit
Version:
This is an early prototype of a RFC8152 COSE library for node.js.
83 lines (82 loc) • 2.94 kB
JavaScript
import verify from "#runtime/verify.js";
import { algsToValue, headers } from '../headers.js';
import sign from '#runtime/sign.js';
import { fromUTF8 } from '../lib/buffer_utils.js';
import { SignatureBase } from './SignatureBase.js';
import { encoder, addExtension } from '../cbor.js';
export class Sign1 extends SignatureBase {
constructor(protectedHeaders, unprotectedHeaders, payload, signature) {
super(protectedHeaders, unprotectedHeaders, signature);
this.payload = payload;
}
getContentForEncoding() {
return [
this.encodedProtectedHeaders,
this.unprotectedHeaders,
this.payload,
this.signature,
];
}
encode() {
return encoder.encode(this);
}
static Signature1(protectedHeaders, applicationHeaders, payload) {
return encoder.encode([
'Signature1',
protectedHeaders,
applicationHeaders,
payload,
]);
}
async verify(key, externalAAD = new Uint8Array()) {
if (typeof key === 'function') {
key = await key(this);
}
if (!key) {
throw new Error('key not found');
}
const toBeSigned = Sign1.Signature1(this.encodedProtectedHeaders || new Uint8Array(), externalAAD, this.payload);
if (!this.algName) {
throw new Error('unknown algorithm: ' + this.alg);
}
return verify(this.algName, key, this.signature, toBeSigned);
}
async verifyX509(roots) {
const { publicKey } = await this.verifyX509Chain(roots);
return this.verify(publicKey);
}
static async sign(protectedHeaders, unprotectedHeaders, payload, key) {
const { alg } = protectedHeaders;
const encodedProtectedHeaders = encoder.encode(new Map(Object.entries(protectedHeaders).map(([k, v]) => {
if (k === 'alg') {
v = algsToValue.get(v);
}
else if (typeof v === 'string') {
v = fromUTF8(v);
}
return [headers[k], v];
})));
const unprotectedHeadersMap = new Map(Object.entries(unprotectedHeaders || {}).map(([k, v]) => {
if (typeof v === 'string') {
v = fromUTF8(v);
}
return [headers[k], v];
}));
const toBeSigned = Sign1.Signature1(encodedProtectedHeaders, new Uint8Array(), payload);
if (!alg) {
throw new Error('The alg header must be set.');
}
const signature = await sign(alg, key, toBeSigned);
return new Sign1(encodedProtectedHeaders, unprotectedHeadersMap, payload, signature);
}
}
addExtension({
Class: Sign1,
tag: 18,
encode(instance, encodeFn) {
return encodeFn(instance.getContentForEncoding());
},
decode: (data) => {
return new Sign1(data[0], data[1], data[2], data[3]);
}
});