signify-ts
Version:
Signing at the edge for KERI, ACDC, and KERIA
102 lines (101 loc) • 3.54 kB
JavaScript
import { desiginput, HEADER_SIG_INPUT, HEADER_SIG_TIME, normalize, siginput, } from "./httping.js";
import { Signage, signature, designature } from "../end/ending.js";
export class Authenticater {
constructor(csig, verfer) {
this._csig = csig;
this._verfer = verfer;
}
verify(headers, method, path) {
const siginput = headers.get(HEADER_SIG_INPUT);
if (siginput == null) {
return false;
}
const signature = headers.get('Signature');
if (signature == null) {
return false;
}
let inputs = desiginput(siginput);
inputs = inputs.filter((input) => input.name == 'signify');
if (inputs.length == 0) {
return false;
}
inputs.forEach((input) => {
const items = new Array();
input.fields.forEach((field) => {
if (field.startsWith('@')) {
if (field == '@method') {
items.push(`"${field}": ${method}`);
}
else if (field == '@path') {
items.push(`"${field}": ${path}`);
}
}
else {
if (headers.has(field)) {
const value = normalize(headers.get(field));
items.push(`"${field}": ${value}`);
}
}
});
const values = new Array();
values.push(`(${input.fields.join(' ')})`);
values.push(`created=${input.created}`);
if (input.expires != undefined) {
values.push(`expires=${input.expires}`);
}
if (input.nonce != undefined) {
values.push(`nonce=${input.nonce}`);
}
if (input.keyid != undefined) {
values.push(`keyid=${input.keyid}`);
}
if (input.context != undefined) {
values.push(`context=${input.context}`);
}
if (input.alg != undefined) {
values.push(`alg=${input.alg}`);
}
const params = values.join(';');
items.push(`"@signature-params: ${params}"`);
const ser = items.join('\n');
const signage = designature(signature);
const markers = signage[0].markers;
const cig = markers.get(input.name);
if (!cig || !this._verfer.verify(cig.raw, ser)) {
throw new Error(`Signature for ${input.keyid} invalid.`);
}
});
return true;
}
sign(headers, method, path, fields) {
if (fields == undefined) {
fields = Authenticater.DefaultFields;
}
const [header, sig] = siginput(this._csig, {
name: 'signify',
method,
path,
headers,
fields,
alg: 'ed25519',
keyid: this._csig.verfer.qb64,
});
header.forEach((value, key) => {
headers.append(key, value);
});
const markers = new Map();
markers.set('signify', sig);
const signage = new Signage(markers, false);
const signed = signature([signage]);
signed.forEach((value, key) => {
headers.append(key, value);
});
return headers;
}
}
Authenticater.DefaultFields = [
'@method',
'@path',
'signify-resource',
HEADER_SIG_TIME.toLowerCase(),
];