Understanding the E-IMZO Agnostic Library architecture and design principles.
E-IMZO Agnostic Library follows a modular, plugin-based architecture designed for flexibility, maintainability, and ease of use.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Application Layer β
β βββββββββββββββ βββββββββββββββ βββββββββββββββββββββββββββ β
β β Browser β β Node.js β β Electron App β β
β β App β β Server β β β β
β βββββββββββββββ βββββββββββββββ βββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β E-IMZO Agnostic Library β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Public API β β
β β eimzoApi, pfxPlugin, pkcs7Plugin, ftjcPlugin... β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Plugin System β β
β β βββββββββββββββ βββββββββββββββ βββββββββββββββββββββββ β β
β β β PFX Plugin β βPKCS7 Plugin β β FTJC Plugin β β β
β β βββββββββββββββ βββββββββββββββ βββββββββββββββββββββββ β β
β β βββββββββββββββ βββββββββββββββ βββββββββββββββββββββββ β β
β β β CRL Plugin β β X509 Plugin β β Custom Plugins β β β
β β βββββββββββββββ βββββββββββββββ βββββββββββββββββββββββ β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Core System β β
β β βββββββββββββββ βββββββββββββββ βββββββββββββββββββββββ β β
β β βPlugin Base β β Types β β Utilities β β β
β β βββββββββββββββ βββββββββββββββ βββββββββββββββββββββββ β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Communication Layer β β
β β WebSocket Client (CAPIWS) β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β E-IMZO System β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β E-IMZO Service β β
β β (Windows Service / Daemon) β β
β β Port: 127.0.0.1:64443 β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Certificate Storage β β
β β Windows Certificate Store / File System β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
The foundation of the library that handles WebSocket communication with E-IMZO.
// capiws.ts
class CAPIWS {
private ws: WebSocket | null = null;
private callbacks: Map<string, Function> = new Map();
async connect(): Promise<boolean> {
return new Promise((resolve, reject) => {
this.ws = new WebSocket('wss://127.0.0.1:64443/');
this.ws.onopen = () => resolve(true);
this.ws.onerror = error => reject(error);
this.ws.onmessage = event => this.handleMessage(event);
});
}
async call(method: string, params: any[]): Promise<any> {
const id = this.generateId();
const message = {
id,
method,
params
};
return new Promise((resolve, reject) => {
this.callbacks.set(id, { resolve, reject });
this.ws?.send(JSON.stringify(message));
});
}
}
Responsibilities:
Provides the foundation for all plugins with common functionality.
// plugin-base.ts
export abstract class EIMZOPlugin {
protected name: string;
protected capiws: CAPIWS;
constructor(name: string) {
this.name = name;
this.capiws = new CAPIWS();
}
protected async callEimzoMethod(
method: string,
params: unknown[] = []
): Promise<unknown> {
await this.ensureConnected();
return this.capiws.call(method, params);
}
protected async ensureConnected(): Promise<void> {
if (!this.capiws.isConnected()) {
await this.capiws.connect();
}
}
// Plugin lifecycle methods
abstract isAvailable(): Promise<boolean>;
}
Features:
Each plugin encapsulates specific E-IMZO functionality.
// Plugin structure example
export class PFXPlugin extends EIMZOPlugin {
constructor() {
super('pfx');
}
async listCertificates(): Promise<Certificate[]> {
const result = await this.callEimzoMethod('PFX_LIST_CERTIFICATES');
return this.parseCertificates(result);
}
async loadKeyFromId(certId: string, password: string): Promise<boolean> {
return this.callEimzoMethod('PFX_LOAD_KEY', [certId, password]);
}
async isAvailable(): Promise<boolean> {
try {
await this.callEimzoMethod('PFX_CHECK_AVAILABILITY');
return true;
} catch {
return false;
}
}
}
Each plugin is self-contained and independent:
// Only import what you need
import { pfxPlugin } from 'imzo-agnost'; // Only PFX functionality
import { pfxPlugin, pkcs7Plugin } from 'imzo-agnost'; // PFX + PKCS7
import * as eimzo from 'imzo-agnost'; // Everything
Comprehensive TypeScript support:
// Strong typing throughout
interface Certificate {
serialNumber: string;
subjectName: string;
issuerName: string;
validFrom: string;
validTo: string;
keyUsage: string;
publicKey: string;
}
// Type-safe plugin methods
async listCertificates(): Promise<Certificate[]> {
// Implementation
}
Consistent error handling across all plugins:
class EIMZOError extends Error {
public readonly code: string;
public readonly details?: unknown;
constructor(message: string, code: string, details?: unknown) {
super(message);
this.code = code;
this.details = details;
this.name = 'EIMZOError';
}
}
// Usage in plugins
try {
return await this.callEimzoMethod('SOME_METHOD', params);
} catch (error) {
throw new EIMZOError('Operation failed', 'OPERATION_ERROR', error);
}
All operations are asynchronous:
// Everything returns promises
const certificates = await pfxPlugin.listCertificates();
const signature = await pkcs7Plugin.createPKCS7(data, certId);
const isValid = await pkcs7Plugin.verifyPKCS7(signature, data);
Application
β
βΌ
Plugin Method (e.g., pfxPlugin.listCertificates())
β
βΌ
Plugin Base (callEimzoMethod)
β
βΌ
CAPIWS (WebSocket call)
β
βΌ
E-IMZO Service
β
βΌ
Certificate Store / Cryptographic Operations
β
βΌ
Response (JSON)
β
βΌ
CAPIWS (Parse response)
β
βΌ
Plugin Base (Handle result/error)
β
βΌ
Plugin Method (Transform data)
β
βΌ
Application (Typed result)
E-IMZO Error
β
βΌ
CAPIWS (Catch WebSocket/JSON errors)
β
βΌ
Plugin Base (Wrap in EIMZOError)
β
βΌ
Plugin Method (Add context)
β
βΌ
Application (Handle typed error)
// core/plugin-manager.ts
class PluginManager {
private static plugins = new Map<string, EIMZOPlugin>();
static registerPlugin(plugin: EIMZOPlugin): void {
this.plugins.set(plugin.name, plugin);
}
static getPlugin(name: string): EIMZOPlugin | undefined {
return this.plugins.get(name);
}
static getAvailablePlugins(): string[] {
return Array.from(this.plugins.keys());
}
}
// Automatic registration
export const pfxPlugin = new PFXPlugin();
PluginManager.registerPlugin(pfxPlugin);
abstract class EIMZOPlugin {
// Initialization (lazy)
protected async initialize(): Promise<void> {
if (!this.initialized) {
await this.setup();
this.initialized = true;
}
}
// Cleanup
async cleanup(): Promise<void> {
if (this.capiws) {
await this.capiws.disconnect();
}
}
// Health check
abstract isAvailable(): Promise<boolean>;
}
// config.ts
interface EIMZOConfig {
host: string;
port: number;
secure: boolean;
timeout: number;
retryAttempts: number;
}
const defaultConfig: EIMZOConfig = {
host: '127.0.0.1',
port: 64443,
secure: true,
timeout: 30000,
retryAttempts: 3
};
// Environment overrides
const config: EIMZOConfig = {
...defaultConfig,
host: process.env.EIMZO_HOST || defaultConfig.host,
port: parseInt(process.env.EIMZO_PORT || defaultConfig.port.toString()),
timeout: parseInt(
process.env.EIMZO_TIMEOUT || defaultConfig.timeout.toString()
)
};
// Individual plugin configuration
interface PluginConfig {
enabled: boolean;
timeout?: number;
retryAttempts?: number;
customOptions?: Record<string, unknown>;
}
const pluginConfigs: Record<string, PluginConfig> = {
pfx: { enabled: true, timeout: 10000 },
pkcs7: { enabled: true, timeout: 15000 },
ftjc: { enabled: true, customOptions: { validateSchema: true } }
};
The library supports multiple output formats for maximum compatibility:
// tsup.config.ts
export default defineConfig([
{
entry: ['src/index.ts'],
format: ['esm', 'cjs', 'iife'],
dts: true,
sourcemap: true,
clean: true,
globalName: 'EIMZOAgnost', // For IIFE
noExternal: ['ws'] // Bundle dependencies for browser
}
]);
Output Files:
dist/index.mjs - ES Modules (56.64KB)dist/index.cjs - CommonJS (56.81KB)dist/index.js - IIFE/Browser Global (60.36KB)dist/index.d.ts - TypeScript declarations (35.82KB){
"dependencies": {
"ws": "^8.x.x"
},
"peerDependencies": {
"typescript": ">=4.5.0"
},
"devDependencies": {
"tsup": "^8.5.0",
"typescript": "^5.9.2"
}
}
// Secure WebSocket connection
class SecureConnection {
private validateCertificate(cert: any): boolean {
// Validate E-IMZO certificate
return cert.issuer.includes('E-IMZO');
}
private createSecureWebSocket(): WebSocket {
return new WebSocket('wss://127.0.0.1:64443/', {
rejectUnauthorized: false, // E-IMZO uses self-signed cert
checkServerIdentity: this.validateCertificate
});
}
}
// Sensitive data handling
class DataProtection {
static sanitizeError(error: Error): Error {
const sensitivePatterns = [/password/i, /key/i, /certificate.*data/i];
let message = error.message;
sensitivePatterns.forEach(pattern => {
message = message.replace(pattern, '[REDACTED]');
});
return new Error(message);
}
}
class ConnectionPool {
private connections: Map<string, CAPIWS> = new Map();
private maxConnections = 5;
async getConnection(key: string): Promise<CAPIWS> {
if (!this.connections.has(key)) {
if (this.connections.size >= this.maxConnections) {
// Implement LRU eviction
this.evictOldest();
}
const connection = new CAPIWS();
await connection.connect();
this.connections.set(key, connection);
}
return this.connections.get(key)!;
}
}
class MethodCache {
private cache = new Map<string, { result: any; expiry: number }>();
private defaultTTL = 60000; // 1 minute
get(key: string): any | null {
const cached = this.cache.get(key);
if (cached && cached.expiry > Date.now()) {
return cached.result;
}
this.cache.delete(key);
return null;
}
set(key: string, result: any, ttl = this.defaultTTL): void {
this.cache.set(key, {
result,
expiry: Date.now() + ttl
});
}
}
// Template for custom plugins
abstract class CustomEIMZOPlugin extends EIMZOPlugin {
// Required methods
abstract getPluginInfo(): PluginInfo;
abstract validateRequirements(): Promise<boolean>;
// Optional overrides
protected async onInitialize(): Promise<void> {
// Custom initialization logic
}
protected async onCleanup(): Promise<void> {
// Custom cleanup logic
}
}
// Plugin registration
export function registerCustomPlugin(plugin: CustomEIMZOPlugin): void {
if (plugin.validateRequirements()) {
PluginManager.registerPlugin(plugin);
} else {
console.warn(`Plugin ${plugin.name} requirements not met`);
}
}
interface Middleware {
name: string;
before?(method: string, params: any[]): Promise<any[]>;
after?(method: string, result: any): Promise<any>;
onError?(method: string, error: Error): Promise<Error>;
}
class MiddlewareManager {
private middlewares: Middleware[] = [];
use(middleware: Middleware): void {
this.middlewares.push(middleware);
}
async executeMiddlewares(
phase: 'before' | 'after' | 'onError',
context: any
): Promise<any> {
for (const middleware of this.middlewares) {
if (middleware[phase]) {
context = await middleware[phase]!(context);
}
}
return context;
}
}
class DebugManager {
private static enabled = process.env.EIMZO_DEBUG === 'true';
static log(category: string, message: string, data?: any): void {
if (this.enabled) {
console.log(`[EIMZO:${category}] ${message}`, data || '');
}
}
static time(label: string): void {
if (this.enabled) {
console.time(`[EIMZO] ${label}`);
}
}
static timeEnd(label: string): void {
if (this.enabled) {
console.timeEnd(`[EIMZO] ${label}`);
}
}
}
class PerformanceMetrics {
private metrics = new Map<string, number[]>();
recordTime(operation: string, duration: number): void {
if (!this.metrics.has(operation)) {
this.metrics.set(operation, []);
}
this.metrics.get(operation)!.push(duration);
}
getAverageTime(operation: string): number {
const times = this.metrics.get(operation) || [];
return times.reduce((a, b) => a + b, 0) / times.length;
}
getReport(): Record<string, any> {
const report: Record<string, any> = {};
for (const [operation, times] of this.metrics) {
report[operation] = {
count: times.length,
average: this.getAverageTime(operation),
min: Math.min(...times),
max: Math.max(...times)
};
}
return report;
}
}