@majikah/majik-signature-client 1.0.0 → 1.0.2
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.
|
@@ -207,6 +207,7 @@ export declare class MajikSignatureClient extends MajikKeyClient<MajikContact, M
|
|
|
207
207
|
private _history;
|
|
208
208
|
/** User activity log manager used for non-blocking activity records. */
|
|
209
209
|
private _activity;
|
|
210
|
+
private _signingSessionDepth;
|
|
210
211
|
/**
|
|
211
212
|
* Creates a Majik Signature client with the supplied managers and storage adapters.
|
|
212
213
|
*
|
|
@@ -967,6 +968,7 @@ export declare class MajikSignatureClient extends MajikKeyClient<MajikContact, M
|
|
|
967
968
|
priorSignedFile?: Blob;
|
|
968
969
|
/** Optional note attached to this specific revision. */
|
|
969
970
|
message?: string;
|
|
971
|
+
saveHistory?: boolean;
|
|
970
972
|
}, source?: HistorySource): Promise<Awaited<ReturnType<typeof MajikSignature.signFile>>>;
|
|
971
973
|
/**
|
|
972
974
|
* Sign a file with a detached signature envelope.
|
|
@@ -1006,8 +1008,15 @@ export declare class MajikSignatureClient extends MajikKeyClient<MajikContact, M
|
|
|
1006
1008
|
timestamp?: string;
|
|
1007
1009
|
mimeType?: string;
|
|
1008
1010
|
validUntil?: string;
|
|
1011
|
+
/** Pre-stamp original, when the current file's embedded envelope was
|
|
1012
|
+
* destroyed by a wholesale re-encode (PDF flatten, image re-render,
|
|
1013
|
+
* audio re-mux). Lets the prior signature chain be recovered. */
|
|
1014
|
+
priorSignedFile?: Blob;
|
|
1009
1015
|
}>, options?: {
|
|
1010
1016
|
accountId?: string;
|
|
1017
|
+
expectedSigners?: ExpectedSigner[];
|
|
1018
|
+
/** Optional note attached to this specific revision. */
|
|
1019
|
+
message?: string;
|
|
1011
1020
|
}, source?: HistorySource): Promise<Array<{
|
|
1012
1021
|
blob: Blob | null;
|
|
1013
1022
|
signature: MajikSignature | null;
|
|
@@ -1377,6 +1386,7 @@ export declare class MajikSignatureClient extends MajikKeyClient<MajikContact, M
|
|
|
1377
1386
|
mimeType?: string;
|
|
1378
1387
|
timestamp?: string;
|
|
1379
1388
|
accountId?: string;
|
|
1389
|
+
saveHistory?: boolean;
|
|
1380
1390
|
}, source?: HistorySource): Promise<Awaited<ReturnType<typeof MajikSignature.seal>>>;
|
|
1381
1391
|
/**
|
|
1382
1392
|
* Verify the seal hash against the current signatories and seal timestamp.
|
|
@@ -1695,6 +1705,13 @@ export declare class MajikSignatureClient extends MajikKeyClient<MajikContact, M
|
|
|
1695
1705
|
* @throws {Error} When validation fails, required local data is unavailable, or the underlying operation cannot be completed.
|
|
1696
1706
|
*/
|
|
1697
1707
|
private _withSigningKey;
|
|
1708
|
+
/**
|
|
1709
|
+
* Unlock once, run `fn` (which may call signFile/seal/etc. any number of
|
|
1710
|
+
* times), then re-lock once at the end if one-time unlock is disabled.
|
|
1711
|
+
*/
|
|
1712
|
+
withSigningSession<T>(accountId: string | undefined, fn: () => Promise<T>): Promise<T>;
|
|
1713
|
+
get isSigningSessionActive(): boolean;
|
|
1714
|
+
forceEndSigningSession(): void;
|
|
1698
1715
|
/**
|
|
1699
1716
|
* Computes a SHA-256 digest and encodes it as base64.
|
|
1700
1717
|
* @param bytes - Value used by the _sha256 base64 operation.
|
|
@@ -70,6 +70,7 @@ export class MajikSignatureClient extends MajikKeyClient {
|
|
|
70
70
|
_history;
|
|
71
71
|
/** User activity log manager used for non-blocking activity records. */
|
|
72
72
|
_activity;
|
|
73
|
+
_signingSessionDepth = 0;
|
|
73
74
|
/**
|
|
74
75
|
* Creates a Majik Signature client with the supplied managers and storage adapters.
|
|
75
76
|
*
|
|
@@ -1439,6 +1440,7 @@ export class MajikSignatureClient extends MajikKeyClient {
|
|
|
1439
1440
|
message: options?.message,
|
|
1440
1441
|
});
|
|
1441
1442
|
const signedBytes = new Uint8Array(await signedResponse.blob.arrayBuffer());
|
|
1443
|
+
const recordHistory = options?.saveHistory ?? true;
|
|
1442
1444
|
this._recordHistory(key.fingerprint, {
|
|
1443
1445
|
reference_id: signedResponse.signature.contentHash,
|
|
1444
1446
|
historyType: HistoryTypes.SIGN,
|
|
@@ -1450,8 +1452,8 @@ export class MajikSignatureClient extends MajikKeyClient {
|
|
|
1450
1452
|
sealed: false,
|
|
1451
1453
|
tsa: false,
|
|
1452
1454
|
},
|
|
1453
|
-
signerCount:
|
|
1454
|
-
data: signedBytes,
|
|
1455
|
+
signerCount: signedResponse.envelope.signatures.length,
|
|
1456
|
+
data: recordHistory ? signedBytes : undefined,
|
|
1455
1457
|
identity: this._identityFromKey(key),
|
|
1456
1458
|
}).catch((err) => console.warn(err));
|
|
1457
1459
|
return signedResponse;
|
|
@@ -1510,13 +1512,16 @@ export class MajikSignatureClient extends MajikKeyClient {
|
|
|
1510
1512
|
* @returns The result of the batch sign files operation (`Promise< Array<{ blob: Blob | null; signature: MajikSignature | null; serialized: string | null; handler: string | null; mimeType: string | null; error: Error | null; }> >`).
|
|
1511
1513
|
*/
|
|
1512
1514
|
async batchSignFiles(files, options, source = HistorySources.SYSTEM) {
|
|
1513
|
-
return this._withSigningKey(options?.accountId, "batchSignFiles", (key) => Promise.all(files.map(async ({ file, contentType, timestamp, mimeType, validUntil }) => {
|
|
1515
|
+
return this._withSigningKey(options?.accountId, "batchSignFiles", (key) => Promise.all(files.map(async ({ file, contentType, timestamp, mimeType, validUntil, priorSignedFile, }) => {
|
|
1514
1516
|
try {
|
|
1515
1517
|
const result = await MajikSignature.signFile(file, key, {
|
|
1516
1518
|
contentType,
|
|
1517
1519
|
timestamp,
|
|
1518
1520
|
mimeType,
|
|
1519
1521
|
validUntil,
|
|
1522
|
+
priorSignedFile,
|
|
1523
|
+
expectedSigners: options?.expectedSigners,
|
|
1524
|
+
message: options?.message,
|
|
1520
1525
|
});
|
|
1521
1526
|
this._recordHistory(key.fingerprint, {
|
|
1522
1527
|
reference_id: result.signature.contentHash,
|
|
@@ -2317,6 +2322,7 @@ export class MajikSignatureClient extends MajikKeyClient {
|
|
|
2317
2322
|
timestamp: options?.timestamp,
|
|
2318
2323
|
});
|
|
2319
2324
|
const sealedBytes = new Uint8Array(await sealResult.blob.arrayBuffer());
|
|
2325
|
+
const recordHistory = options?.saveHistory ?? true;
|
|
2320
2326
|
this._recordHistory(key.fingerprint, {
|
|
2321
2327
|
reference_id: sealResult.sealInfo.sealHash,
|
|
2322
2328
|
historyType: HistoryTypes.SEAL,
|
|
@@ -2328,7 +2334,7 @@ export class MajikSignatureClient extends MajikKeyClient {
|
|
|
2328
2334
|
sealed: true,
|
|
2329
2335
|
tsa: false,
|
|
2330
2336
|
},
|
|
2331
|
-
data: sealedBytes,
|
|
2337
|
+
data: recordHistory ? sealedBytes : undefined,
|
|
2332
2338
|
identity: this._identityFromKey(key),
|
|
2333
2339
|
}).catch((err) => console.warn(err));
|
|
2334
2340
|
return sealResult;
|
|
@@ -3065,7 +3071,9 @@ export class MajikSignatureClient extends MajikKeyClient {
|
|
|
3065
3071
|
throw new Error(`Account "${id}" has no signing keys. ` +
|
|
3066
3072
|
`Re-import via importAccountFromMnemonicBackup() to enable signing.`);
|
|
3067
3073
|
}
|
|
3068
|
-
shouldRelock =
|
|
3074
|
+
shouldRelock =
|
|
3075
|
+
this._signingSessionDepth === 0 &&
|
|
3076
|
+
!(await this.isOnetimeUnlockEnabled());
|
|
3069
3077
|
return await fn(key);
|
|
3070
3078
|
}
|
|
3071
3079
|
catch (err) {
|
|
@@ -3077,6 +3085,42 @@ export class MajikSignatureClient extends MajikKeyClient {
|
|
|
3077
3085
|
key?.lock();
|
|
3078
3086
|
}
|
|
3079
3087
|
}
|
|
3088
|
+
/**
|
|
3089
|
+
* Unlock once, run `fn` (which may call signFile/seal/etc. any number of
|
|
3090
|
+
* times), then re-lock once at the end if one-time unlock is disabled.
|
|
3091
|
+
*/
|
|
3092
|
+
async withSigningSession(accountId, fn) {
|
|
3093
|
+
const id = accountId ?? this.getActiveAccount()?.id;
|
|
3094
|
+
if (!id)
|
|
3095
|
+
throw new Error("No active account — call setActiveAccount() first");
|
|
3096
|
+
await this._keys.ensureUnlocked(id);
|
|
3097
|
+
this._signingSessionDepth++;
|
|
3098
|
+
try {
|
|
3099
|
+
return await fn();
|
|
3100
|
+
}
|
|
3101
|
+
finally {
|
|
3102
|
+
this._signingSessionDepth = Math.max(0, this._signingSessionDepth - 1);
|
|
3103
|
+
if (this._signingSessionDepth === 0) {
|
|
3104
|
+
try {
|
|
3105
|
+
if (!(await this.isOnetimeUnlockEnabled())) {
|
|
3106
|
+
this._keys.get(id)?.lock();
|
|
3107
|
+
}
|
|
3108
|
+
}
|
|
3109
|
+
catch (err) {
|
|
3110
|
+
// Fail closed: if we can't read the preference, lock anyway.
|
|
3111
|
+
this._keys.get(id)?.lock();
|
|
3112
|
+
console.warn("withSigningSession: relock check failed", err);
|
|
3113
|
+
}
|
|
3114
|
+
}
|
|
3115
|
+
}
|
|
3116
|
+
}
|
|
3117
|
+
get isSigningSessionActive() {
|
|
3118
|
+
return this._signingSessionDepth > 0;
|
|
3119
|
+
}
|
|
3120
|
+
forceEndSigningSession() {
|
|
3121
|
+
this._signingSessionDepth = 0;
|
|
3122
|
+
return;
|
|
3123
|
+
}
|
|
3080
3124
|
/**
|
|
3081
3125
|
* Computes a SHA-256 digest and encodes it as base64.
|
|
3082
3126
|
* @param bytes - Value used by the _sha256 base64 operation.
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@majikah/majik-signature-client",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"description": "Majik Signature Client is a hybrid post-quantum content signing and verification library for the Majikah ecosystem. Built on top of Majik Key Client, it provides tamper-proof, forgery-resistant digital signatures for any content format — using a dual-algorithm architecture that combines classical Ed25519 with post-quantum ML-DSA-87 (FIPS-204).",
|
|
5
|
-
"version": "1.0.
|
|
5
|
+
"version": "1.0.2",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"author": "Zelijah",
|
|
8
8
|
"main": "./dist/index.js",
|