eimzo-sign-core 0.1.0

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.
package/src/types.ts ADDED
@@ -0,0 +1,112 @@
1
+ import type { EimzoErrorCode } from './errors'
2
+
3
+ /** Sertifikat turi. `idcard` — ID-karta (alohida oqim, `loadKey` chaqirilmaydi). */
4
+ export type CertType = 'pfx' | 'ftjc' | 'idcard'
5
+
6
+ /**
7
+ * Normallashtirilgan sertifikat. `raw` — vendor xom obyekti, `loadKey` ga
8
+ * o'zgarishsiz uzatiladi (undan tashqarida foydalanmang).
9
+ */
10
+ export interface Cert {
11
+ serialNumber: string
12
+ /** CN — egasi (F.I.Sh yoki tashkilot rahbari). */
13
+ CN: string
14
+ /** STIR / JSHSHIR. */
15
+ TIN: string
16
+ UID: string
17
+ /** Tashkilot nomi (jismoniy shaxs kalitida bo'sh). */
18
+ O: string
19
+ T: string
20
+ validFrom: Date
21
+ validTo: Date
22
+ type: CertType
23
+ /** @internal vendor xom obyekti */
24
+ raw: unknown
25
+ }
26
+
27
+ export interface EimzoVersion {
28
+ major: number
29
+ minor: number
30
+ }
31
+
32
+ export interface EimzoClientOptions {
33
+ /**
34
+ * Domen API kalitlari: `[[domen, kalit], ...]`.
35
+ * E-IMZO tomonidan har domen uchun beriladi.
36
+ *
37
+ * MUHIM: kutubxonada default YO'Q. Ilova (consumer) o'z kalitlarini
38
+ * shu yerda beradi; prod kalitlari kutubxona kodiga yozilmaydi.
39
+ */
40
+ apiKeys: ReadonlyArray<readonly [domain: string, key: string]>
41
+
42
+ /** Har bir CAPIWS chaqiruvi uchun timeout, ms. Default: 30000. */
43
+ timeoutMs?: number
44
+
45
+ /**
46
+ * Kalit yuklash (parol kiritish) uchun alohida, uzunroq timeout, ms.
47
+ * Default: 120000.
48
+ */
49
+ keyLoadTimeoutMs?: number
50
+
51
+ /** Minimal talab qilinadigan E-IMZO versiyasi. Default: 3.37. */
52
+ minVersion?: EimzoVersion
53
+
54
+ /**
55
+ * Audit hook. Kutubxona HECH QACHON `console` ga yozmaydi — barcha
56
+ * kuzatuv shu yerdan o'tadi. Ilova buni o'z jurnaliga / SIEM'ga yozadi.
57
+ * Hook'dagi istisno kutubxonani buzmaydi (yutiladi).
58
+ *
59
+ * DIQQAT: `AuditEvent` ataylab minimal — faqat `serial` va `docId`.
60
+ * CN / TIN / JSHSHIR / imzo bloblari uzatilmaydi.
61
+ */
62
+ onAudit?: (event: AuditEvent) => void
63
+ }
64
+
65
+ /** Imzolanadigan bitta hujjat. */
66
+ export interface SignDoc {
67
+ /** Ilova ichidagi barqaror identifikator (natijani hujjatga bog'lash uchun). */
68
+ id: string
69
+ /** Imzolanadigan XOM kontent (matn / XML / base64). Base64 kodlashni kutubxona bajaradi. */
70
+ content: string
71
+ }
72
+
73
+ /** Bitta hujjat bo'yicha imzo natijasi. */
74
+ export interface SignResult {
75
+ id: string
76
+ pkcs7_64: string
77
+ signature_hex: string
78
+ signer_serial_number: string
79
+ }
80
+
81
+ /** Partiyadagi bitta element — muvaffaqiyat yoki xato. */
82
+ export type BatchSignItem =
83
+ | ({ id: string; ok: true } & Omit<SignResult, 'id'>)
84
+ | { id: string; ok: false; error: import('./errors').EimzoError }
85
+
86
+ export interface BatchProgress {
87
+ /** Tugagan hujjatlar soni. */
88
+ done: number
89
+ /** Jami hujjatlar. */
90
+ total: number
91
+ /** Hozir imzolanayotgan hujjat id'si (tugagach — undefined). */
92
+ currentId?: string
93
+ }
94
+
95
+ export interface SignBatchOptions {
96
+ /** Tashqi bekor qilish signali (idle-taymer, modal yopilishi). */
97
+ signal?: AbortSignal
98
+ /** Har bir hujjatdan oldin/keyin chaqiriladi. */
99
+ onProgress?: (progress: BatchProgress) => void
100
+ }
101
+
102
+ /**
103
+ * Audit hodisalari. Ataylab minimal maydonlar — shaxsiy ma'lumot yo'q.
104
+ */
105
+ export type AuditEvent =
106
+ | { type: 'version_checked'; ts: string; major: number; minor: number }
107
+ | { type: 'certs_listed'; ts: string; count: number }
108
+ | { type: 'key_loaded'; ts: string; serial: string }
109
+ | { type: 'sign_started'; ts: string; serial: string; docId: string }
110
+ | { type: 'sign_ok'; ts: string; serial: string; docId: string }
111
+ | { type: 'sign_failed'; ts: string; docId: string; code: EimzoErrorCode }
112
+ | { type: 'session_ended'; ts: string; serial: string; signed: number; failed: number }
package/src/util.ts ADDED
@@ -0,0 +1,69 @@
1
+ import { EimzoError } from './errors'
2
+
3
+ export function nowIso(): string {
4
+ return new Date().toISOString()
5
+ }
6
+
7
+ /** Seriya raqamlarini solishtirish uchun normallashtirish (registr + bo'shliqlar). */
8
+ export function normalizeSerial(value: unknown): string {
9
+ return String(value ?? '')
10
+ .toUpperCase()
11
+ .replace(/\s+/g, '')
12
+ }
13
+
14
+ export function throwIfAborted(signal?: AbortSignal): void {
15
+ if (signal?.aborted) {
16
+ throw new EimzoError('E_CANCELLED', 'Amal bekor qilindi')
17
+ }
18
+ }
19
+
20
+ /**
21
+ * Callback uslubidagi vendor chaqiruvini timeout bilan Promise'ga o'raydi.
22
+ * `settle` bir martagina ishlaydi (double-resolve himoyasi).
23
+ */
24
+ export function withTimeout<T>(
25
+ timeoutMs: number,
26
+ timeoutError: () => EimzoError,
27
+ executor: (
28
+ resolve: (value: T) => void,
29
+ reject: (error: unknown) => void,
30
+ ) => void,
31
+ signal?: AbortSignal,
32
+ ): Promise<T> {
33
+ return new Promise<T>((resolve, reject) => {
34
+ let settled = false
35
+
36
+ const cleanup = (): void => {
37
+ clearTimeout(timer)
38
+ signal?.removeEventListener('abort', onAbort)
39
+ }
40
+ const settleResolve = (value: T): void => {
41
+ if (settled) return
42
+ settled = true
43
+ cleanup()
44
+ resolve(value)
45
+ }
46
+ const settleReject = (error: unknown): void => {
47
+ if (settled) return
48
+ settled = true
49
+ cleanup()
50
+ reject(error)
51
+ }
52
+
53
+ const onAbort = (): void =>
54
+ settleReject(new EimzoError('E_CANCELLED', 'Amal bekor qilindi'))
55
+ const timer = setTimeout(() => settleReject(timeoutError()), timeoutMs)
56
+
57
+ if (signal?.aborted) {
58
+ settleReject(new EimzoError('E_CANCELLED', 'Amal bekor qilindi'))
59
+ return
60
+ }
61
+ signal?.addEventListener('abort', onAbort)
62
+
63
+ try {
64
+ executor(settleResolve, settleReject)
65
+ } catch (error) {
66
+ settleReject(error)
67
+ }
68
+ })
69
+ }
@@ -0,0 +1,59 @@
1
+ # Vendored E-IMZO SDK fayllari
2
+
3
+ Bu papkadagi fayllar **E-IMZO'ning rasmiy brauzer SDK'sidan** olingan.
4
+ Ta'minot zanjiri (supply-chain) xavfsizligi uchun ular repozitoriyga qo'lda kiritilgan,
5
+ `npm` orqali emas.
6
+
7
+ | Fayl | Manba | Versiya | Holati | SHA-256 |
8
+ |---|---|---|---|---|
9
+ | `e-imzo.js` | https://e-imzo.uz | `< to'ldiring >` | 4 qatorlik patch (pastga qarang) | `751b0ca8592db0e37bd6f095161b1766651a47951e01cf13a4c68e1373fb1cc3` |
10
+ | `e-imzo-client.js` | https://e-imzo.uz | `< to'ldiring >` | O'zgartirilmagan | `b02a60e05854d305081affcf69785d4f185b130aadc2506d7de62a9d873b120c` |
11
+
12
+ ## `e-imzo.js` ga kiritilgan patch
13
+
14
+ Sabab: rasmiy fayl klassik `<script>` sifatida yozilgan — top-level `this` global
15
+ obyekt deb faraz qiladi, `CAPIWS` ni **implicit global** deб e'lon qiladi va modul
16
+ yuklanganda `window.location` ni o'qiydi. ESM bundler (tsup/esbuild) ichida
17
+ `this === undefined`, implicit global taqiqlangan, SSR/Node'da esa `window` yo'q.
18
+ Quyidagi 4 ta o'zgarish kiritildi. **Xatti-harakat brauzerda o'zgarmaydi**,
19
+ `eval` / `new Function` ishlatilmaydi.
20
+
21
+ ```diff
22
+ - 375: window.Base64 = global.Base64;
23
+ + 375: if (typeof window !== 'undefined') window.Base64 = global.Base64;
24
+
25
+ - 376: })(this);
26
+ + 376: })(typeof globalThis !== 'undefined' ? globalThis : this);
27
+
28
+ - 378: CAPIWS = (typeof EIMZOEXT !== 'undefined') ? EIMZOEXT : {
29
+ + 378: globalThis.CAPIWS = (typeof EIMZOEXT !== 'undefined') ? EIMZOEXT : {
30
+
31
+ 379: URL: (
32
+ - window.location.protocol.toLowerCase() === "https:"
33
+ + (typeof window !== 'undefined' ? window.location.protocol : '').toLowerCase() === "https:"
34
+ ? "wss://127.0.0.1:64443" : "ws://127.0.0.1:64646") + "/service/cryptapi",
35
+ ```
36
+
37
+ ## Yangilash tartibi
38
+
39
+ 1. Rasmiy SDK'dan yangi faylni yuklab oling.
40
+ 2. `git diff` bilan o'zgarishlarni ko'zdan kechiring (yangi tarmoq manzillari,
41
+ `eval` / `Function` / `innerHTML` / `document.write` paydo bo'lmaganini tekshiring).
42
+ 3. Yuqoridagi 3 patchни qayta qo'llang.
43
+ 4. `shasum -a 256 e-imzo.js e-imzo-client.js` — jadvalни yangilang.
44
+ 5. `pnpm --filter eimzo-sign-core test` — kontrakt testlari o'tishини tasdiqlang.
45
+ 6. Alohida commit: `chore(vendor): E-IMZO SDK x.y.z ga yangilash`.
46
+
47
+ CI `verify-vendor` bosqichi jadvaldagi SHA-256 bilan haqiqiy fayлларни solиштиради —
48
+ mos kelmаса build to'xtаyди.
49
+
50
+ ## Ma'lum xususiyatlar (audit uchun)
51
+
52
+ - `e-imzo-client.js` `Date.prototype` va `String.prototype` ga metod qo'shади
53
+ (`yyyymmdd`, `ddmmyyyy`, `splitKeep`). Bu rasmiy SDK xatti-harakати.
54
+ - `e-imzo.js` global `CAPIWS` va `window.Base64` ni o'rnатади.
55
+ - Tashqи tarmoqqа chiqмайди; faqat lokal soket:
56
+ `ws://127.0.0.1:64646` (http) / `wss://127.0.0.1:64443` (https).
57
+ - `eval` / `new Function` / `document.write` / `innerHTML` ishlатилмайди.
58
+ - SSR eslатма: `e-imzo.js` modul yuklанганда `window.location.protocol` ni o'qийди —
59
+ paketни faqat brauzер muhitида import qiling (Vue qatlами buni ta'минлайди).