cose-kit
Version:
This is an early prototype of a RFC8152 COSE library for node.js.
110 lines (109 loc) • 4.91 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Signature = exports.Sign = void 0;
const SignatureBase_js_1 = require("./SignatureBase.js");
const WithHeaders_js_1 = require("./WithHeaders.js");
const verify_js_1 = __importDefault(require("#runtime/verify.js"));
const headers_js_1 = require("../headers.js");
const sign_js_1 = __importDefault(require("#runtime/sign.js"));
const cbor_js_1 = require("../cbor.js");
class Sign extends WithHeaders_js_1.WithHeaders {
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
]),
];
}
encode() {
return cbor_js_1.encoder.encode(this);
}
async verify(keys) {
const results = await Promise.all(this.signatures.map(async (signature, index) => {
const keyToUse = Array.isArray(keys) ? keys[index] : keys;
return signature.verify(keyToUse, this.encodedProtectedHeaders, this.payload);
}));
return results.every(Boolean);
}
async verifyX509(roots) {
const results = await Promise.all(this.signatures.map(async (signature) => {
const { publicKey } = await signature.verifyX509Chain(roots);
return signature.verify(publicKey, this.encodedProtectedHeaders, this.payload);
}));
return results.every(Boolean);
}
static async sign(bodyProtectedHeader, unprotectedHeaders, payload, signers) {
const encodedProtectedHeaders = (0, headers_js_1.encodeProtectedHeaders)(bodyProtectedHeader);
const unprotectedHeadersMap = (0, headers_js_1.mapUnprotectedHeaders)(unprotectedHeaders);
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);
}
}
exports.Sign = Sign;
class Signature extends SignatureBase_js_1.SignatureBase {
constructor(protectedHeaders, unprotectedHeaders, signature) {
super(protectedHeaders, unprotectedHeaders, signature);
this.unprotectedHeaders = unprotectedHeaders;
this.signature = signature;
}
static Signature(bodyProtectedHeaders, protectedHeaders, applicationHeaders, payload) {
return cbor_js_1.encoder.encode([
'Signature',
bodyProtectedHeaders || new Uint8Array(),
protectedHeaders || new Uint8Array(),
applicationHeaders || new Uint8Array(),
payload,
]);
}
async verify(key, bodyProtectedHeaders, payload) {
if (typeof key === 'function') {
key = await key(this);
}
if (!key) {
throw new Error('key not found');
}
const toBeSigned = Signature.Signature(bodyProtectedHeaders, this.encodedProtectedHeaders, new Uint8Array(), payload);
if (!this.algName) {
throw new Error('unknown algorithm: ' + this.alg);
}
return (0, verify_js_1.default)(this.algName, key, this.signature, toBeSigned);
}
static async sign(bodyProtectedHeaders, protectedHeaders, unprotectedHeaders, payload, key) {
const { alg } = protectedHeaders;
const encodedProtectedHeaders = (0, headers_js_1.encodeProtectedHeaders)(protectedHeaders);
const unprotectedHeadersMapped = (0, headers_js_1.mapUnprotectedHeaders)(unprotectedHeaders);
const toBeSigned = Signature.Signature(bodyProtectedHeaders, encodedProtectedHeaders, new Uint8Array(), payload);
if (!alg) {
throw new Error('The alg header must be set.');
}
const signature = await (0, sign_js_1.default)(alg, key, toBeSigned);
return new Signature(encodedProtectedHeaders, unprotectedHeadersMapped, signature);
}
}
exports.Signature = Signature;
(0, cbor_js_1.addExtension)({
Class: Sign,
tag: 98,
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);
}
});