npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

eimzo-client

v0.2.0

Published

Modern, typed, framework-agnostic E-IMZO (O'zbekiston ERI) client for the web. Vue 3 + React adapters, inline WebSocket transport, mobile detection.

Readme

eimzo-client

Zamonaviy, TypeScript bilan to'liq typed, framework-agnostik E-IMZO (O'zbekiston ERI) klienti — web ilovalar uchun. Vue 3, React, Angular va Nuxt 3 adapterlari ham ichida.

npm install eimzo-client
import { createEimzo } from 'eimzo-client'

const eimzo = createEimzo()
await eimzo.install()                       // 1. E-IMZO'ga ulanish
const certs = await eimzo.listKeys()        // 2. Sertifikatlar ro'yxati
const { pkcs7 } = await eimzo.sign(certs[0], 'Imzolanadigan matn')  // 3. Imzolash

Asosiy imkoniyatlar

  • 100% mustaqil — tashqi e-imzo.js skript yuklanmaydi (ichki WebSocket transport)
  • Promise-asosli API (callback-hell yo'q), to'liq TypeScript typed
  • ✅ E-IMZO v5 va v6 bilan mos (v6 da API-key avtomatik)
  • ✅ PFX sertifikatlar + ID-card / BAIK / CKC qurilmalari
  • ✅ PKCS#7 imzolash + Timestamp (TST) ulash + katta fayllar uchun SHA-256 hash imzolash
  • Mobil ID-card QR / deeplink (eimzo-client/mobile-idcard)
  • ✅ Vue 3 plugin + composable, React Provider + hook, Angular Signal'lar, Nuxt module
  • ✅ ESM + CJS, tree-shake mos, 32 MB hujjatgacha imzolash (v6 limiti)
  • ✅ Xavfsizlik: SRI, prototype-pollution himoyasi, AbortSignal bilan bekor qilish

Mundarija

  1. E-IMZO qanday ishlaydi? — avval shu yerni o'qing
  2. O'rnatish va talablar
  3. Tezkor boshlash (vanilla)
  4. Hayotiy sikl: 4 qadam
  5. Framework adapterlari — Vue / Nuxt / React / Angular
  6. Imzolash holatlari
  7. Qurilma orqali kirish (ID-card / BAIK / CKC)
  8. Mobil ID-card (QR + deeplink)
  9. Timestamp (TST) qo'shish
  10. Transport rejimi
  11. API ma'lumotnomasi
  12. Xavfsizlik
  13. E-IMZO v6 yangiliklari

E-IMZO qanday ishlaydi?

E-IMZO — foydalanuvchi kompyuteriga o'rnatiladigan ERI (elektron raqamli imzo) dasturi. U fonda localhost'da WebSocket server sifatida ishlaydi (wss://127.0.0.1:64443). Brauzer shu serverga ulanib, kalitlar ro'yxatini oladi va imzolash buyruqlarini yuboradi.

eimzo-client — aynan shu WebSocket aloqasining toza, tipli o'ramidir. Maxsus tashqi skript yuklamaydi (ichki transport).

Tipik oqim har doim 2 tomonda ketadi — frontend imzolaydi, backend tekshiradi:

┌──────────┐   1. install / listKeys / sign   ┌─────────────────┐
│ Brauzer  │ ───────────────────────────────► │  E-IMZO daemon  │
│ (sizning │ ◄─────────────────────────────── │ (localhost WS)  │
│   sayt)  │        PKCS#7 imzo                └─────────────────┘
└────┬─────┘
     │ 2. PKCS#7 ni backendga yuborasiz
     ▼
┌──────────┐   imzoni tekshirish (e-imzo-server)
│ Backend  │ ──────────────────────────────────►  vpn.e-imzo.uz
└──────────┘

⚠️ Muhim: bu paket faqat frontend qismini bajaradi (imzo hosil qilish). Imzo haqiqiyligini, sertifikat statusini va challenge mosligini backend tekshirishi shart (e-imzo-server). Qarang: Xavfsizlik.

Uchta ishchi muhit bor:

| Muhit | Nima ishlatiladi | Qanday | |---|---|---| | Desktop | PFX sertifikatlar | localhost WebSocket orqali to'g'ridan-to'g'ri | | Desktop qurilma | ID-card / BAIK / CKC | xuddi shu, daemon PIN'ni o'zi so'raydi | | Mobil | E-IMZO ID-CARD ilovasi | QR / deeplink + backend polling (pastga) |


O'rnatish va talablar

npm install eimzo-client
# yoki
pnpm add eimzo-client
# yoki
yarn add eimzo-client

Talab: foydalanuvchi kompyuterida E-IMZO dasturi o'rnatilgan va ishga tushirilgan bo'lishi kerak. Aks holda install() EimzoNotInstalledError tashlaydi.


Tezkor boshlash (vanilla)

import { createEimzo } from 'eimzo-client'

const eimzo = createEimzo({
  // v5 uchun API-key'lar (v6 da kerak emas — E-IMZO o'zi o'rnatadi):
  apiKeys: {
    'localhost': '96D0C1491615C82B...',
    'mysite.uz': 'C691454C3DBAC565...',
  },
})

await eimzo.install()                  // skript/version/apikey
const certs = await eimzo.listKeys()   // PFX sertifikatlari
const result = await eimzo.sign(certs[0], 'Imzolanadigan matn')
console.log(result.pkcs7)              // base64 PKCS#7

v6: apiKeys opsiyasi e'tiborga olinmaydi — E-IMZO domenni o'zi avtomatik aniqlaydi.


Hayotiy sikl: 4 qadam

Deyarli har bir oqim shu to'rt qadamdan iborat. Tartibni saqlash muhim.

// 1. ULANISH — E-IMZO'ni topadi, versiyani aniqlaydi, API-key o'rnatadi
await eimzo.install()

// 2. RO'YXAT — mavjud PFX sertifikatlarni oladi (rol flag'lari avtomatik qo'shiladi)
const certs = await eimzo.listKeys()

// 3. TANLASH — foydalanuvchi UI'dan bittasini tanlaydi
const cert = certs[0]

// 4a. KIRISH (auth) — backend bergan challenge'ni imzolaydi
const challenge = await fetch('/api/auth/challenge').then(r => r.text())
const pkcs7 = await eimzo.authenticate(challenge, cert)
await fetch('/api/auth/login', { method: 'POST', body: pkcs7 })

// 4b. yoki HUJJAT IMZOLASH
const { pkcs7: signed } = await eimzo.sign(cert, JSON.stringify({ orderId: 12345 }))
  • authenticate() — kirish (login) uchun: backend tasodifiy challenge beradi, foydalanuvchi uni imzolaydi, backend imzoni tekshirib sessiya ochadi.
  • sign() — hujjat imzolash uchun: natija backendda arxivlanadi / tekshiriladi.

Framework adapterlari

Core API (createEimzo()) har bir metodga sertifikatni argument sifatida beradi. Adapter'larda esa (useEimzo() / EimzoService) sertifikat ichki state'da saqlanadi — qarang: Adapter API qoidalari.

Vue 3

// main.ts
import { createApp } from 'vue'
import { EimzoVuePlugin } from 'eimzo-client/vue'
import App from './App.vue'

createApp(App)
  .use(EimzoVuePlugin, { apiKeys: { 'localhost': '96D0C1491615C82B...' } })
  .mount('#app')
<!-- KeySelector.vue -->
<script setup lang="ts">
import { onMounted } from 'vue'
import { useEimzo } from 'eimzo-client/vue'

const { certificates, selected, loading, error, loadCertificates, select, sign } = useEimzo()

onMounted(loadCertificates)

async function onSign() {
  const result = await sign('Hujjat matni')
  console.log(result.pkcs7)
}
</script>

<template>
  <div v-if="loading">Yuklanmoqda...</div>
  <div v-else-if="error">{{ error.message }}</div>

  <ul>
    <li v-for="c in certificates" :key="c.serialNumber" @click="select(c)">
      {{ c.CN }} ({{ c.TIN || c.PINFL }})
    </li>
  </ul>

  <button :disabled="!selected" @click="onSign">Imzolash</button>
</template>

Nuxt 3

Module sifatida ulang — useEimzo() avto-import bo'ladi:

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['eimzo-client/nuxt'],
  eimzo: {
    apiKeys: { 'mysite.uz': process.env.NUXT_PUBLIC_EIMZO_KEY ?? '' },
    transport: 'inline',   // 'inline' (default) | 'external'
    onMobile: 'throw',     // 'throw' (default) | 'warn' | 'ignore'
  },
})
<!-- pages/sign.vue -->
<script setup lang="ts">
const { certificates, selected, error, install, loadCertificates, select, sign } = useEimzo()

onMounted(async () => {
  await install()
  await loadCertificates()
})

async function onSign() {
  if (!selected.value) return
  const result = await sign('Imzolanadigan matn')
  await $fetch('/api/sign', { method: 'POST', body: { pkcs7: result.pkcs7 } })
}
</script>

SSR: plugin faqat brauzerda ishlaydi (E-IMZO daemon localhost'da bo'lgani uchun). install() va boshqa metodlarni onMounted() ichida (yoki <client-only> blokida) chaqiring.

React

// main.tsx
import { EimzoProvider } from 'eimzo-client/react'

ReactDOM.createRoot(root).render(
  <EimzoProvider options={{ apiKeys: { 'localhost': '96D0C1...' } }} autoInstall>
    <App />
  </EimzoProvider>
)
// KeySelector.tsx
import { useEffect } from 'react'
import { useEimzo } from 'eimzo-client/react'

export function KeySelector() {
  const { certificates, selected, loading, error, loadCertificates, select, sign } = useEimzo()

  useEffect(() => { loadCertificates() }, [loadCertificates])

  if (loading) return <div>Yuklanmoqda...</div>
  if (error) return <div>{error.message}</div>

  return (
    <>
      <ul>
        {certificates.map(c => (
          <li key={c.serialNumber} onClick={() => select(c)}>
            {c.CN} ({c.TIN || c.PINFL})
          </li>
        ))}
      </ul>
      <button disabled={!selected} onClick={() => sign('Hujjat matni')}>Imzolash</button>
    </>
  )
}

Angular (≥16)

Standalone API + Signal'lar bilan. provideEimzo() orqali sozlanadi:

// app.config.ts
import { provideEimzo } from 'eimzo-client/angular'

export const appConfig = {
  providers: [provideEimzo({ apiKeys: { 'mysite.uz': '...' } })],
}
// key-selector.component.ts
import { Component, inject, OnInit } from '@angular/core'
import { EimzoService } from 'eimzo-client/angular'

@Component({ standalone: true, selector: 'app-key-selector', template: `...` })
export class KeySelectorComponent implements OnInit {
  readonly eimzo = inject(EimzoService)

  async ngOnInit() {
    await this.eimzo.install()
    await this.eimzo.loadCertificates()
  }

  async onSign() {
    const result = await this.eimzo.sign('Hujjat matni')
    console.log(result.pkcs7)
  }
}

EimzoService reaktiv field'lari (Signal): certificates(), selected(), loading(), error(), version().

Tayyor EimzoClient'ni ham berish mumkin (test / shared client uchun):

import { provideEimzoClient } from 'eimzo-client/angular'
import { createEimzo } from 'eimzo-client'

providers: [provideEimzoClient(createEimzo({ apiKeys: { /* ... */ } }))]

Adapter API qoidalari

Adapter'larda imzolash metodlaridan oldin selected'ga sertifikat qo'yilishi shart, aks holda Error("Sertifikat tanlanmagan") qaytariladi.

Sertifikat tanlash:

// Vue — uch ekvivalent yo'l:
select(cert)            // 1. select() metodi
selected.value = cert   // 2. ref'ga to'g'ridan-to'g'ri
// 3. template'da: <select v-model="selected">

// React / Angular — faqat select():
select(cert)

Qaysi metod selected talab qiladi:

| Metod | selected kerakmi? | Sabab | |---|:-:|---| | install() / loadCertificates() / select() | ❌ | Sertifikatsiz ishlaydi | | sign(data, opts?) | ✅ | selected'dan oladi | | signHash(file, opts?) | ✅ | selected'dan oladi | | authenticate(challenge) | ✅ | selected'dan oladi | | signWithSerial(serial, data) | ❌ | Serial bo'yicha topadi |

// To'g'ri tartib:
await install()                        // 1
const certs = await loadCertificates() // 2
select(certs[0])                       // 3 ⚠️ MAJBURIY — o'tkazib yuborilsa, authenticate xato beradi
const pkcs7 = await authenticate(challenge) // 4

💡 Sertifikatni state'da saqlamasdan ishlash uchun core API'ni (createEimzo()) ishlating.


Imzolash holatlari

Misollar core API uchun. Adapter'larda cert'ni argument sifatida bermaysiz — selected'dan olinadi.

sign() qabul qiladigan turlar:

type BinaryInput = string | ArrayBuffer | ArrayBufferView | Blob

1. Auth challenge (matn):

const challenge = await fetch('/api/auth/challenge').then(r => r.text())
const pkcs7 = await eimzo.authenticate(challenge, cert)

2. JSON hujjat:

const result = await eimzo.sign(cert, JSON.stringify({ orderId: 12345, amount: 1_000_000 }))

3. PDF/DOC fayl (Blob/File):

const file = inputElement.files[0]
const result = await eimzo.sign(cert, file)

4. Katta fayl — SHA-256 hash imzolash (10+ MB uchun tavsiya etiladi):

const { pkcs7, hash } = await eimzo.signHash(cert, file)  // avto SHA-256 + detached PKCS#7
await fetch('/api/sign', {
  method: 'POST',
  body: JSON.stringify({ pkcs7, hashHex: bytesToHex(hash) }),
})

5. Binary baytlar:

const result = await eimzo.sign(cert, new Uint8Array([0x01, 0x02, 0x03]))

6. Allaqachon base64 satr:

const result = await eimzo.sign(cert, alreadyBase64, { isBase64: true })

7. Detached imzo (asl hujjatsiz):

const result = await eimzo.sign(cert, file, { detached: true })  // PKCS#7 ichida fayl yo'q

Qurilma orqali kirish (ID-card / BAIK / CKC)

Bu uchta qurilma sertifikat ro'yxatiga kirmaydi (listKeys() ularni qaytarmaydi) — alohida tugma orqali ishlatiladi. PIN'ni E-IMZO daemon o'zi so'raydi (JS tomondan load_key/verify_pin chaqirilmaydi).

if (await eimzo.isBaikConnected()) {
  const challenge = await fetch('/api/challenge').then(r => r.text())
  const pkcs7 = await eimzo.authenticateWithBaik(challenge)
  await fetch('/api/login', { method: 'POST', body: pkcs7 })
}

| Metod | Tavsif | |---|---| | isIdCardConnected() / isBaikConnected() / isCkcConnected() | Qurilma ulanganmi? | | signWithIdCard(data, opts?) / signWithBaik(...) / signWithCkc(...) | Imzolash | | authenticateWithIdCard(challenge) / authenticateWithBaik(...) / authenticateWithCkc(...) | Challenge imzolash | | signWithDevice(device, data, opts?) | Umumiy variant (device: 'idcard'/'baikey'/'ckc') |

Versiya talabi: ID-card uchun E-IMZO 4.12+, BAIK/CKC uchun 4.86+. Eski versiyada EimzoVersionError tashlanadi.


Mobil ID-card (QR + deeplink)

E-IMZO desktop dasturi telefonda yo'q — uning o'rniga E-IMZO ID-CARD mobile ilovasi ishlatiladi. U butunlay boshqa, REST-API asosidagi oqim (qo0p/e-imzo-doc, 3-bo'lim):

  1. Backend POST /frontend/mobile/auth{ siteId, documentId, challange }
  2. Frontend challange'dan GOST hash + CRC32 hisoblab qc quradi:
    • web (desktop)qc QR rasm bo'lib chiziladi, foydalanuvchi telefon bilan skanlaydi
    • same-device (mobil brauzer)eimzo://... deeplink ochiladi
  3. POST /frontend/mobile/status (documentId=…) ni status:1 bo'lguncha poll qilamiz
  4. Backend GET /backend/mobile/authenticate/{documentId} orqali tasdiqlaydi

QR/deeplink quruvchi alohida, tree-shake'lanadigan subpath'da: eimzo-client/mobile-idcard (GOST jadvallari faqat shuni import qilgan bundle'ga kiradi).

⚠️ GOST hash'ni frontend hisoblaydi — bu rasmiy protokol talabi, backend tayyor qc qaytarmaydi. Bu modul rasmiy e-imzo-mobile.js ning toza TS ekvivalenti (7/7 GOST test-vektori + real skanlangan QR bilan tasdiqlangan), shuning uchun tashqi skript yuklash shart emas.

import { buildIdCardMobileQr } from 'eimzo-client/mobile-idcard'
import { pollMobileResult, isMobilePlatform } from 'eimzo-client'
import QRCode from 'qrcode'

// 1. Backend auth sessiyasini yaratadi
const auth = await fetch('/frontend/mobile/auth', { method: 'POST' }).then(r => r.json())
// { siteId, documentId, challange }

// 2. qc / deeplink / hash quramiz
const { qc, deeplink, hash } = buildIdCardMobileQr(auth)

if (isMobilePlatform()) {
  window.location.href = deeplink        // same-device: ilovani ochamiz
} else {
  const dataUrl = await QRCode.toDataURL(qc)  // desktop: QR chizamiz (boshqa telefon skanlaydi)
}
// `hash` — QR yonida ko'rsatiladigan "hesh-kod"; foydalanuvchi ilovadagi bilan solishtiradi

// 3. status:1 bo'lguncha poll qilamiz
await pollMobileResult(
  async () => {
    const r = await fetch('/frontend/mobile/status', {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: `documentId=${encodeURIComponent(auth.documentId)}`,
    }).then(r => r.json())
    return r.status === 1 ? { ready: true, data: r } : { ready: false }
  },
  { intervalMs: 2000, timeoutMs: 5 * 60 * 1000 },
)

// 4. Backend tasdiqlaydi:
//    GET /backend/mobile/authenticate/{documentId} → { status:1, subjectCertificateInfo }

eimzo-client/mobile-idcard eksportlari:

| Funksiya | Tavsif | |---|---| | buildIdCardMobileQr({ siteId, documentId, challange }) | { qc, deeplink, hash } quradi | | gostHash(text) | GOST R 34.11-94 hash (ASCII matn — login/auth uchun) | | gostHashHex(hex) | GOST hash (hex input — hujjat imzolash uchun) | | crc32Hex(hex) | CRC32, 8 belgi lowercase hex |

Platformani aniqlash: getPlatform()'ios' | 'android' | 'desktop' | 'unknown', isMobilePlatform()boolean. Default'da install() mobil brauzerda EimzoMobileUnsupportedError tashlaydi (onMobile: 'throw').


Timestamp (TST) qo'shish

Imzoga ishonchli vaqt belgisi ulash uchun timestamp callback bering:

const result = await eimzo.sign(cert, data, {
  async timestamp(signatureHex) {
    return fetch('/api/timestamp', { method: 'POST', body: signatureHex }).then(r => r.text())
  },
})

Transport rejimi

Default — inline: paket o'zining WebSocket transportini ishlatadi, tashqi skript yuklamaydi.

const eimzo = createEimzo({ transport: 'inline' })  // DEFAULT

Eski window.CAPIWS skriptiga tayanish (legacy):

const eimzo = createEimzo({
  transport: 'external',
  scriptUrl: 'https://e-imzo.uz/e-imzo-cm/e-imzo.js',
  scriptIntegrity: 'sha384-...',  // SRI tavsiya etiladi
})

| Xususiyat | inline (default) | external | |---|---|---| | Tashqi skript yuklash | ❌ Yo'q | ✅ e-imzo.uz dan ≈50KB | | Supply-chain xavfi | ✅ Yo'q | ⚠️ CDN xavfi (SRI bilan kamayadi) | | CSP script-src | Faqat 'self' | 'self' https://e-imzo.uz | | WebSocket bekor qilish (AbortSignal) | ✅ Bor | ❌ Yo'q | | Birinchi imzo tezligi | ⚡ Tezroq | Skript yuklash kutiladi | | Offline (intranet) | ✅ Ishlaydi | ❌ e-imzo.uz kerak |

Tavsiya: production'da inline'da qoldiring. external faqat eski integratsiyalar uchun.


API ma'lumotnomasi

createEimzo(options): EimzoClient

| Opsiya | Tip | Default | Tavsif | |---|---|---|---| | apiKeys | Record<string, string> | — | domen → key (faqat v5; v6 da e'tiborsiz) | | transport | 'inline' \| 'external' | 'inline' | Transport rejimi | | capiwsUrl | string | wss://127.0.0.1:64443/... | Inline mode WebSocket URL | | scriptUrl | string | e-imzo.uz CDN | External mode skript URL | | skipScriptLoad | boolean | false | Skript allaqachon mavjud bo'lsa | | scriptIntegrity | string | — | External mode SRI hash | | timeoutMs | number | 0 (timeout yo'q) | Har bir CAPIWS chaqiruv timeout'i | | maxDataBytes | number | 32 MB | Imzolanadigan ma'lumot maks hajmi | | onMobile | 'throw' \| 'warn' \| 'ignore' | 'throw' | Mobil brauzerda install() xatti-harakati |

timeoutMs default 0 — chunki load_key/create_pkcs7 foydalanuvchidan parol kutadi. Programmatik chaqiruvlar uchun > 0 bering.

EimzoClient metodlari

| Metod | Tavsif | |---|---| | install() | Ulanish: version aniqlash + apikey o'rnatish (external'da skript ham) | | listKeys() | PFX sertifikatlar ro'yxati (rol flag'lari bilan) | | loadKey(cert, { verify }) | Kalitni yuklash, ixtiyoriy parol/PIN tekshiruvi | | sign(cert, data, opts?) | PKCS#7 imzolash | | signWithSerial(serial, data, opts?) | Serial bo'yicha topib imzolash | | signHash(cert, file, opts?) | SHA-256 hash + detached PKCS#7 | | authenticate(challenge, cert) | Auth challenge'ni imzolash | | getCertificateChain(handle) | x509 sertifikat zanjiri | | isIdCardConnected() / isBaikConnected() / isCkcConnected() | Qurilma ulanganmi | | signWithDevice(device, data, opts?) | Qurilma orqali imzolash (umumiy) | | signWithIdCard(...) / signWithBaik(...) / signWithCkc(...) | Qurilma orqali imzolash (qisqartma) | | authenticateWithIdCard(...) / authenticateWithBaik(...) / authenticateWithCkc(...) | Challenge imzolash | | version | Versiya ma'lumoti (install() dan keyin) |

Sertifikat yordamchilari

Har bir Certificate listKeys() paytida avtomatik rol flag'lari bilan boyitiladi:

const cert = (await eimzo.listKeys())[0]
cert.isLegalEntity        // yuridik shaxsmi?
cert.isPhysicalPerson     // jismoniy shaxs (YATT ham kiradi)?
cert.isYATT               // yakka tartibdagi tadbirkor?

Free-funksiyalar (Pick'lar bilan ham ishlaydi):

import {
  isLegalEntity, isPhysicalPerson, isYATT,
  getCertificateRole, getCertificateRoleLabel, getCertificateStatus,
} from 'eimzo-client'

getCertificateRole(cert)              // 'legal' | 'yatt' | 'physical'
getCertificateRoleLabel(cert)         // "Yuridik shaxs" | "Yakka tartibdagi tadbirkor" | "Jismoniy shaxs"
getCertificateRoleLabel(cert, 'en')   // inglizcha variant
getCertificateStatus(cert)            // { status: 'active'|'expiring'|'expired'|'pending', daysLeft }

Encoding yordamchilari

import {
  encodeBase64, encodeBase64Async, decodeBase64, decodeBase64Text,
  bytesToHex, hexToBytes, sha256, sha256Hex, sha256Base64, byteLength,
} from 'eimzo-client'

encodeBase64('Salom dunyo')             // UTF-8 → base64
await encodeBase64Async(file)           // Blob/File → base64
decodeBase64Text('SGVsbG8=')            // base64 → string
await sha256Hex(file)                   // SHA-256 hex
bytesToHex(new Uint8Array([0xab, 0xcd])) // 'abcd'

Native fast path: Uint8Array.prototype.toBase64() mavjud bo'lgan brauzerlarda (Chrome 130+, Safari 18+) avtomatik undan foydalanadi; eski brauzerlarda chunked btoa (32 MB gacha stack overflow yo'q).

Xato turlari

Hammasi EimzoError'dan meros oladi va code xususiyatiga ega.

| Xato | Qachon | |---|---| | EimzoNotInstalledError | E-IMZO dasturi ishlamayapti | | EimzoTransportError | WebSocket / tarmoq xatosi | | EimzoVersionError | E-IMZO versiyasi mos kelmadi | | EimzoApiKeyError | API-key noto'g'ri yoki yo'q | | EimzoTimeoutError | Chaqiruv kutish vaqti tugadi | | EimzoWrongPasswordError | Noto'g'ri PFX parol / token PIN | | EimzoSignError | Imzolashda xatolik | | EimzoKeyNotFoundError | Sertifikat topilmadi | | EimzoDataTooLargeError | Ma'lumot maxDataBytes'dan oshdi | | EimzoResponseTooLargeError | Daemon javobi juda katta | | EimzoMobileUnsupportedError | Mobil brauzerda install() chaqirilgan |

import { EimzoError, EimzoNotInstalledError, EimzoWrongPasswordError } from 'eimzo-client'

try {
  await eimzo.signWithBaik(data)
} catch (e) {
  if (e instanceof EimzoNotInstalledError) alert('E-IMZO dasturini ishga tushiring')
  else if (e instanceof EimzoWrongPasswordError) alert("Noto'g'ri PIN")
  else if (e instanceof EimzoError) console.error(e.code, e.message)
}

Xavfsizlik

E-IMZO bilan ishlashda frontend imzo hosil qiladi, lekin tekshirmaydi. Backend tomonida quyidagilar majburiy.

Auth (login) checklist

  • Challenge tasodifiyligi — kamida 32 bayt CSPRNG (crypto.randomBytes(32))
  • TTL ≤ 5 daqiqa — challenge cache'da muddati cheklangan (masalan, Redis TTL)
  • Bir martalik — verify'dan keyin challenge'ni darhol o'chiring
  • Origin/audience binding — challenge ichida saytingiz host'i bo'lsin
  • Sertifikat zanjiri — Root CA gacha tekshiring (E-IMZO PKI'siga ishonch)
  • Sertifikat statusivalidFrom <= now <= validTo, mumkin bo'lsa CRL/OCSP
  • PKCS#7 imzosi GOST/RSA bilan tekshirilgan va challenge baytlariga mos

Token saqlash

localStorage JWT uchun zaif (XSS'da o'g'irlanadi):

  • 🟢 HttpOnly + Secure + SameSite=Strict cookie
  • 🟡 Qisqa TTL (15–30 min) + refresh token rotation
  • 🔴 localStorage — faqat development yoki token bo'lmagan narsa uchun

ID-card mobil oqim xavfsizligi

  • documentId/challange ni backend yaratadi — frontend faqat GOST hash/CRC32 quradi. siteId ro'yxatdan o'tgan UPLOAD URL'ga bog'langan, shuning uchun PKCS#7 faqat sizning /frontend/mobile/upload ga keladi.
  • challange bir martalik + qisqa TTL — har auth da yangi challange, backend Redis'da cheklangan muddat saqlaydi.
  • Yakuniy tekshiruv backendda — frontend'dagi status:1 o'zi yetarli emas; foydalanuvchi ma'lumoti /backend/mobile/authenticate/{documentId} javobidan olinadi.
  • hash ("hesh-kod") ni foydalanuvchiga ko'rsating — ilovadagi bilan ko'z bilan solishtirish phishing'ni kamaytiradi.

Localhost daemon TLS

E-IMZO daemon wss://127.0.0.1:64443 da self-signed sertifikat ishlatadi (pinning yo'q). Lokal mashinadagi zararli proses portga "o'tirib" imzolarni tutib qolishi mumkin — bu paket buni oldini olmaydi (tahdid model — OS-level malware). Mitigatsiya: ishonchli mashina, antivirus, host-based IDS.

CSP tavsiyalari

script-src 'self';                               # inline mode
connect-src 'self' wss://127.0.0.1:* ws://127.0.0.1:*;

External mode'da script-src ga https://e-imzo.uz qo'shing va scriptIntegrity (SRI) bering.


E-IMZO v6 yangiliklari

Paket avtomatik aniqlaydi va moslashadi:

  • ✅ API-KEY avtomatik o'rnatiladi (apikey chaqiruv kerak emas)
  • ✅ 32 MB gacha hujjat imzolash
  • ✅ ID-card emulyatori (test rejimi)
  • ✅ UZGUARD token qo'llab-quvvatlash
  • ✅ JRE 17 → JRE 1.8 PFX moslik

Bog'lanish

Muallif: Qobiljon Jumaboyev

Savol, taklif yoki xavfsizlik muammolari uchun yuqoridagi kanallar orqali bog'laning.


Litsenziya

MIT © Qobiljon Jumaboyev