itrm-tools 1.4.5 → 1.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -8,6 +8,9 @@ export interface ApiSignValues {
|
|
|
8
8
|
encryptedBody?: string;
|
|
9
9
|
}
|
|
10
10
|
export declare class ApiKeySigner implements Signer<ApiSignValues, IKey, string> {
|
|
11
|
+
private readonly windowMilliseconds;
|
|
12
|
+
/** `windowSeconds` decides how old a nonce may be; without it, five minutes. */
|
|
13
|
+
constructor(windowSeconds?: number);
|
|
11
14
|
sign(input: ApiSignValues, keys: IKey): string;
|
|
12
15
|
verify(input: ApiSignValues, keys: IKey, signature: string): boolean;
|
|
13
16
|
private buildSignature;
|
|
@@ -2,17 +2,32 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ApiKeySigner = void 0;
|
|
4
4
|
const crypto_js_1 = require("crypto-js");
|
|
5
|
+
/** Five minutes: enough for the clock skew between stations, short enough to bound a replay. */
|
|
6
|
+
const DEFAULT_NONCE_WINDOW_SECONDS = 300;
|
|
5
7
|
class ApiKeySigner {
|
|
8
|
+
windowMilliseconds;
|
|
9
|
+
/** `windowSeconds` decides how old a nonce may be; without it, five minutes. */
|
|
10
|
+
constructor(windowSeconds) {
|
|
11
|
+
const usable = windowSeconds !== undefined && Number.isFinite(windowSeconds) && windowSeconds > 0;
|
|
12
|
+
this.windowMilliseconds = (usable ? windowSeconds : DEFAULT_NONCE_WINDOW_SECONDS) * 1000;
|
|
13
|
+
}
|
|
6
14
|
sign(input, keys) {
|
|
15
|
+
// Milliseconds, as always: two stations may sign in the same millisecond and the verifier
|
|
16
|
+
// accepts both, because it no longer requires the nonce to grow.
|
|
7
17
|
let nonce = Date.now();
|
|
8
18
|
return `${keys.publicKey}:${nonce}:${this.buildSignature(input, nonce, keys.signKey)}`;
|
|
9
19
|
}
|
|
10
20
|
verify(input, keys, signature) {
|
|
11
|
-
|
|
12
|
-
if (values
|
|
13
|
-
|
|
21
|
+
const values = this.extractSignatureDetails(signature);
|
|
22
|
+
if (values !== undefined) {
|
|
23
|
+
// Inside the window and with a matching signature; the nonce need not grow, so two
|
|
24
|
+
// stations share a key without a race, and outside the window a captured request is old.
|
|
25
|
+
const age = Date.now() - values.nonce;
|
|
26
|
+
const matches = Math.abs(age) <= this.windowMilliseconds
|
|
27
|
+
&& this.buildSignature(input, values.nonce, keys.signKey) === values.signature;
|
|
14
28
|
if (matches) {
|
|
15
|
-
|
|
29
|
+
// `lastNonce` is kept for the records, never to reject a request.
|
|
30
|
+
keys.lastNonce = Math.max(keys.lastNonce ?? 0, values.nonce);
|
|
16
31
|
return true;
|
|
17
32
|
}
|
|
18
33
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApiKeySigner.js","sourceRoot":"","sources":["../../../src/cryptography/sign/ApiKeySigner.ts"],"names":[],"mappings":";;;AAEA,yCAA4C;AAU5C,MAAa,YAAY;
|
|
1
|
+
{"version":3,"file":"ApiKeySigner.js","sourceRoot":"","sources":["../../../src/cryptography/sign/ApiKeySigner.ts"],"names":[],"mappings":";;;AAEA,yCAA4C;AAU5C,gGAAgG;AAChG,MAAM,4BAA4B,GAAG,GAAG,CAAC;AAEzC,MAAa,YAAY;IACJ,kBAAkB,CAAS;IAE5C,gFAAgF;IAChF,YAAY,aAAsB;QAC9B,MAAM,MAAM,GAAG,aAAa,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,aAAa,GAAG,CAAC,CAAC;QAElG,IAAI,CAAC,kBAAkB,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,4BAA4B,CAAC,GAAG,IAAI,CAAC;IAC7F,CAAC;IAEM,IAAI,CAAC,KAAoB,EAAE,IAAU;QACxC,0FAA0F;QAC1F,iEAAiE;QACjE,IAAI,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,OAAO,GAAG,IAAI,CAAC,SAAS,IAAI,KAAK,IAAI,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,OAAQ,CAAC,EAAE,CAAC;IAC5F,CAAC;IAEM,MAAM,CAAC,KAAoB,EAAE,IAAU,EAAE,SAAiB;QAC7D,MAAM,MAAM,GAAG,IAAI,CAAC,uBAAuB,CAAC,SAAS,CAAC,CAAC;QAEvD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACvB,mFAAmF;YACnF,yFAAyF;YACzF,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC;YACtC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,kBAAkB;mBACjD,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,OAAQ,CAAC,KAAK,MAAM,CAAC,SAAS,CAAC;YAEpF,IAAI,OAAO,EAAE,CAAC;gBACV,kEAAkE;gBAClE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC7D,OAAO,IAAI,CAAC;YAChB,CAAC;QACL,CAAC;QAED,OAAO,KAAK,CAAC;IACjB,CAAC;IAEO,cAAc,CAAC,KAAoB,EAAE,KAAa,EAAE,OAAe;QACvE,IAAI,OAAO,GAAG,KAAK,GAAG,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACxH,MAAM,IAAI,GAAG,IAAA,sBAAU,EAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC1C,OAAO,eAAG,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAEO,uBAAuB,CAAC,SAAiB;QAC7C,IAAI,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAClB,OAAO;gBACH,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;gBACnB,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBACzB,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;aACtB,CAAC;QACN,OAAO,SAAS,CAAC;IACrB,CAAC;CACJ;AArDD,oCAqDC"}
|
package/package.json
CHANGED