@ldclabs/cose-ts
Version:
Implemented Keys, Algorithms (RFC9053), COSE (RFC9052) and CWT (RFC8392) in TypeScript.
80 lines • 3.37 kB
JavaScript
// (c) 2023-present, LDC Labs. All rights reserved.
// See the file LICENSE for licensing terms.
import { Header } from './header';
import * as iana from './iana';
import { decodeCBOR, encodeCBOR, compareBytes } from './utils';
import { skipTag, withTag, CwtPrefix, Mac0MessagePrefix, CBORSelfPrefix } from './tag';
// Mac0Message represents a COSE_Mac0 object.
//
// Reference https://datatracker.ietf.org/doc/html/rfc9052#name-signing-with-one-signer.
export class Mac0Message {
payload;
// protected header parameters: iana.HeaderParameterAlg, iana.HeaderParameterCrit.
protected = null;
// Other header parameters.
unprotected = null;
static macBytes(payload, protectedHeader, externalData) {
return encodeCBOR([
'MAC0',
protectedHeader,
externalData ?? new Uint8Array(),
payload
]);
}
static fromBytes(key, coseData, externalData) {
const data = skipTag(Mac0MessagePrefix, skipTag(CwtPrefix, skipTag(CBORSelfPrefix, coseData)));
const [protectedBytes, unprotected, payload, tag] = decodeCBOR(data);
const protectedHeader = Header.fromBytes(protectedBytes);
const unprotectedHeader = new Header(unprotected);
if (protectedHeader.has(iana.HeaderParameterAlg)) {
const alg = protectedHeader.getInt(iana.HeaderParameterAlg);
if (alg !== key.alg) {
throw new Error(`cose-ts: Mac0Message.fromBytes: alg mismatch, expected ${alg}, got ${key.alg}`);
}
}
const t = key.mac(Mac0Message.macBytes(payload, protectedBytes, externalData));
if (compareBytes(tag, t) !== 0) {
throw new Error('cose-ts: Mac0Message.fromBytes: tag mismatch');
}
return new Mac0Message(payload, protectedHeader, unprotectedHeader);
}
static withTag(coseData) {
return withTag(Mac0MessagePrefix, coseData);
}
constructor(payload, protectedHeader, unprotected) {
this.payload = payload;
this.protected = protectedHeader
? new Header(protectedHeader.toRaw())
: null;
this.unprotected = unprotected ? new Header(unprotected.toRaw()) : null;
}
toBytes(key, externalData) {
if (this.protected == null) {
this.protected = new Header();
if (key.has(iana.KeyParameterAlg)) {
this.protected.setParam(iana.HeaderParameterAlg, key.alg);
}
}
else if (this.protected.has(iana.HeaderParameterAlg)) {
const alg = this.protected.getInt(iana.HeaderParameterAlg);
if (alg !== key.alg) {
throw new Error(`cose-ts: Mac0Message.toBytes: alg mismatch, expected ${alg}, got ${key.alg}`);
}
}
if (this.unprotected == null) {
this.unprotected = new Header();
if (key.has(iana.KeyParameterKid)) {
this.unprotected.setParam(iana.HeaderParameterKid, key.kid);
}
}
const protectedBytes = this.protected.toBytes();
const tag = key.mac(Mac0Message.macBytes(this.payload, protectedBytes, externalData));
return encodeCBOR([
protectedBytes,
this.unprotected.toRaw(),
this.payload,
tag
]);
}
}
//# sourceMappingURL=mac0.js.map