Cipherion Client SDK

A robust JavaScript/TypeScript SDK for the Cipherion Encryption API

Secure • Scalable • Enterprise-Ready

Features

Complete Encryption Suite

Basic and deep object encryption/decryption with enterprise-grade security

Enterprise Ready

Built-in logging, error handling, and retry mechanisms for production use

Migration Tools

Batch processing with queue and background worker support for large datasets

Type Safe

Full TypeScript support with comprehensive type definitions

Compliance Logging

Structured logging for audit and compliance requirements

High Performance

Optimized for large-scale data processing with memory management

Quick Start

Installation

npm i @cipherion/client
or  
yarn add @cipherion/client

Credentials Setup

  1. Log in to your Cipherion Dashboard
  2. Navigate to Project Settings
  3. Generate or retrieve your Project ID and API Key
  4. Create a passphrase (minimum 12 characters) and store it securely
  5. CRITICAL: Use the same passphrase when generating encryption keys in the dashboard and in your application

Environment Setup

Create a .env file in your project root:

CIPHERION_BASE_URL = https://api.cipherion.cloud/api/v1/crypto
CIPHERION_PROJECT_ID = proj_your_project_id
CIPHERION_API_KEY = your_api_key_here
CIPHERION_PASSPHRASE = your_secure_passphrase_here

Configuration Interface

interface CipherionConfig {
  baseUrl: string;          // API base URL
  projectId: string;        // Your project ID from dashboard
  apiKey: string;           // Your API key from dashboard
  passphrase: string;       // Your encryption passphrase (min 12 chars)
  timeout?: number;       // Request timeout (default: 30000ms)
  retries?: number;       // Retry attempts (default: 3)
  logLevel?: 'error' | 'warn' | 'info' | 'debug';
  enableLogging?: boolean;   // Enable logging (default: true)
}

Basic Usage

const { CipherionClient } = require('cipherion-client');

// Initialize client
const client = new CipherionClient();

async function example() {
  try {
    // Basic string encryption
    const encrypted = await client.encrypt("Hello, World!");
    console.log('Encrypted:', encrypted);

    // Basic string decryption
    const decrypted = await client.decrypt(encrypted);
    console.log('Decrypted:', decrypted);

    // Deep object encryption
    const userData = {
      name: "John Doe",
      email: "john@example.com",
      ssn: "123-45-6789"
    };

    const deepEncrypted = await client.deepEncrypt(userData);
    const deepDecrypted = await client.deepDecrypt(deepEncrypted.encrypted);

    console.log('Original:', userData);
    console.log('Decrypted:', deepDecrypted.data);

  } catch (error) {
    console.error('Error:', error.message);
  }
}
example();

TypeScript Usage

import { CipherionClient, CipherionConfig } from 'cipherion-client';

interface UserData {
  id: number;
  name: string;
  email: string;
}

const config: CipherionConfig = {
  baseUrl: process.env.CIPHERION_BASE_URL!,
  projectId: process.env.CIPHERION_PROJECT_ID!,
  apiKey: process.env.CIPHERION_API_KEY!,
  logLevel: 'info'
};

const client = new CipherionClient(config);

const userData: UserData = {
  id: 1,
  name: "Jane Smith",
  email: "jane@example.com"
};

const result = await client.deepEncrypt(userData);

Quick Start

import { CipherionClient } from '@cipherion/client';

// Initialize client (reads from environment variables)
const cipherion = new CipherionClient();

// Or with custom configuration
const cipherionCustom = new CipherionClient({
  baseUrl: process.env.CIPHERION_BASE_URL,
  projectId: process.env.CIPHERION_PROJECT_ID,
  apiKey: process.env.CIPHERION_API_KEY,
  passphrase: process.env.CIPHERION_PASSPHRASE,
  timeout: 30000,
  logLevel: 'info'
});

// Basic encryption
const encrypted = await cipherion.encrypt('sensitive data');

// Basic decryption
const decrypted = await cipherion.decrypt(encrypted);

API Reference

Basic Encryption & Decryption

#### encrypt(data: string): Promise<string>
// Encrypts a string using basic encryption
const encrypted = await cipherion.encrypt('Hello, World!');
// Returns: encrypted string

#### decrypt(encryptedData: string): Promise<string>
// Decrypts a string that was encrypted using encrypt()
const decrypted = await cipherion.decrypt(encryptedData);
// Returns: 'Hello, World!'

Deep Encryption & Decryption

#### deepEncrypt(data: any): Promise<DeepEncryptResponse['data']>
// Encrypts complex data structures while preserving their structure
const userData = {
  name: 'John Doe',
  email: 'john@example.com',
  address: { street: '123 Main St', city: 'New York' },
  creditCards: ['4111111111111111', '5500000000000004']
};

const encrypted = await cipherion.deepEncrypt(userData);
// Returns: encrypted structure with meta data

#### deepDecrypt(encryptedData: any): Promise<DeepDecryptResponse['data']>
const decrypted = await cipherion.deepDecrypt(encrypted.encrypted);
// Returns: original data structure with meta data

API Reference

Core Methods

MethodDescriptionReturns
encrypt(data)Encrypts a stringPromise<string>
decrypt(encryptedData)Decrypts a stringPromise<string>
deepEncrypt(data)Encrypts complex objectsPromise<DeepEncryptResponse>
deepDecrypt(encryptedData)Decrypts complex objectsPromise<DeepDecryptResponse>

Migration Methods

MethodDescriptionUse Case
migrateEncrypt(dataArray, options?)Batch encrypt array of objectsLarge dataset encryption
migrateDecrypt(encryptedArray, options?)Batch decrypt array of objectsLarge dataset decryption

Configuration Options

getConfig(): Omit<CipherionConfig, 'apiKey' | 'passphrase'>

Returns current configuration without sensitive data.

typescript
const config = cipherion.getConfig();
console.log(config.projectId); // Safe to log

updateConfig(newConfig: Partial<CipherionConfig>): void

Updates client configuration.

typescript
cipherion.updateConfig({
  timeout: 60000,
  logLevel: 'debug'
});

Migration & Batch Processing

Perfect for enterprise scenarios requiring large-scale data processing:

migrateEncrypt(dataArray: any[], options?: MigrationOptions): Promise<MigrationResult>

Batch encrypts an array of data items with progress tracking. Useful for migrating existing databases.

typescript
const users = [ 
  { name: 'User 1', email: 'user1@example.com' },
  { name: 'User 2', email: 'user2@example.com' },
  // ... more users
];

const result = await cipherion.migrateEncrypt(users, {
  batchSize: 10,
  delayBetweenBatches: 1000,
  maxRetries: 3,
  onProgress: (progress) => {
    console.log(`Progress: ${progress.percentage}%`);
  },
  onError: (error, item) => {
    console.error('Failed to encrypt:', item, error);
  }
});

// Returns:
{
  successful: [ /* encrypted items */ ],
  failed: [ /* failed items with errors */ ],
  summary: {
    total: 100,
    processed: 100,
    successful: 98,
    failed: 2,
    percentage: 100
  }
}

migrateDecrypt(encryptedArray: any[], options?: MigrationOptions): Promise<MigrationResult>

Batch decrypts an array of encrypted data items.

typescript
const result = await cipherion.migrateDecrypt(encryptedUsers, {
  batchSize: 10,
  onProgress: (progress) => {
    console.log(`Decrypted: ${progress.successful} of ${progress.total}`);
  }
});

Integration Examples

Express.js Integration
// src/config/cipherion.ts
import { CipherionClient } from '@cipherion/client';
import dotenv from 'dotenv';

dotenv.config();

export const cipherion = new CipherionClient({
  baseUrl: process.env.CIPHERION_BASE_URL!,
  projectId: process.env.CIPHERION_PROJECT_ID!,
  apiKey: process.env.CIPHERION_API_KEY!,
  passphrase: process.env.CIPHERION_PASSPHRASE!,
});
// src/app.ts
import express from 'express';
import { cipherion } from './config/cipherion';

const app = express();
app.use(express.json());

// Encrypt user data endpoint
app.post('/api/users', async (req, res) => {
  try {
    const { name, email, ssn, creditCard } = req.body;

    const encrypted = await cipherion.deepEncrypt({
      name,
      email,
      ssn,
      creditCard
    });

    res.json({
      success: true,
      data: encrypted.encrypted,
      meta: encrypted.meta
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

// Decrypt user data endpoint
app.get('/api/users/:id', async (req, res) => {
  try {
    const encryptedData = await getUserFromDB(req.params.id);
    const decrypted = await cipherion.deepDecrypt(encryptedData);

    res.json({
      success: true,
      data: decrypted.data
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: error.message
    });
  }
});

// Middleware for encrypting response data
const encryptMiddleware = async (req, res, next) => {
  const originalJson = res.json.bind(res);

  res.json = async function(data) {
    if (data.sensitive) {
      const encrypted = await cipherion.deepEncrypt(data.sensitive);
      data.sensitive = encrypted.encrypted;
    }
    originalJson(data);
  };

  next();
};

app.use(encryptMiddleware);

app.listen(3000, () => {
  console.log('Server running on port 3000');
});
Nest Js Integration
// src/cipherion/cipherion.module.ts
import { Module, Global } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { CipherionService } from './cipherion.service';

@Global()
@Module({
  imports: [ConfigModule],
  providers: [CipherionService],
  exports: [CipherionService],
})
export class CipherionModule {}
// src/cipherion/cipherion.service.ts
import { Injectable, OnModuleInit } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { CipherionClient } from '@cipherion/client';

@Injectable()
export class CipherionService implements OnModuleInit {
  private client: CipherionClient;

  constructor(private configService: ConfigService) {}

  onModuleInit() {
    this.client = new CipherionClient({
      baseUrl: this.configService.get('CIPHERION_BASE_URL'),
      projectId: this.configService.get('CIPHERION_PROJECT_ID'),
      apiKey: this.configService.get('CIPHERION_API_KEY'),
      passphrase: this.configService.get('CIPHERION_PASSPHRASE'),
    });
  }

  async encrypt(data: string): Promise<string> {
    return this.client.encrypt(data);
  }

  async decrypt(encryptedData: string): Promise<string> {
    return this.client.decrypt(encryptedData);
  }

  async deepEncrypt(data: any) {
    return this.client.deepEncrypt(data);
  }

  async deepDecrypt(encryptedData: any) {
    return this.client.deepDecrypt(encryptedData);
  }

  async migrateEncrypt(dataArray: any[], options?: any) {
    return this.client.migrateEncrypt(dataArray, options);
  }

  async migrateDecrypt(encryptedArray: any[], options?: any) {
    return this.client.migrateDecrypt(encryptedArray, options);
  }
}
// src/users/users.controller.ts
import { Controller, Post, Get, Body, Param } from '@nestjs/common';
import { CipherionService } from '../cipherion/cipherion.service';

@Controller('users')
export class UsersController {
  constructor(private readonly cipherionService: CipherionService) {}

  @Post()
  async createUser( @Body() userData: any) {
    try {
      const encrypted = await this.cipherionService.deepEncrypt({
        name: userData.name,
        email: userData.email,
        ssn: userData.ssn,
        creditCard: userData.creditCard,
      });

      // Save to database
      // await this.usersService.create(encrypted.encrypted);

      return {
        success: true,
        data: encrypted.encrypted,
        meta: encrypted.meta,
      };
    } catch (error) {
      return {
        success: false,
        error: error.message,
      };
    }
  }

  @Get(':id')
  async getUser( @Param('id') id: string) {
    try {
      // Retrieve from database
      // const encryptedData = await this.usersService.findOne(id);

      const decrypted = await this.cipherionService.deepDecrypt( encryptedData);

      return {
        success: true,
        data: decrypted.data,
      };
    } catch (error) {
      return {
        success: false,
        error: error.message,
      };
    }
  }
}
// src/app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { CipherionModule } from './cipherion/cipherion.module';
import { UsersModule } from './users/users.module';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
    }),
    CipherionModule,
    UsersModule,
  ],
})
export class AppModule {}

Database Migration Example

// migrate-to-encryption.ts
import { CipherionClient } from '@cipherion/client';
import { connectToDatabase, User } from './database';

async function migrateUsers() {
  const cipherion = new CipherionClient();
  const db = await connectToDatabase();

  // Fetch all users from database
  const users = await db.collection('users').find().toArray();

  console.log(`Starting migration for ${users.length} users...`);

  const result = await cipherion.migrateEncrypt(users, {
    batchSize: 50,
    delayBetweenBatches: 2000,
    maxRetries: 3,
    onProgress: (progress) => {
      console.log(`Progress: ${progress.percentage}% (${progress.successful} successful, ${progress.failed} failed)`);
    },
    onError: (error, item) => {
      console.error(`Failed to encrypt user ${item._id}:`, error.message);
    },
  });

  // Update database with encrypted data
  for (const encryptedUser of result.successful) {
    await db.collection('users').updateOne({_id: encryptedUser.encrypted._id }}, {{"$set": {{data: encryptedUser.encrypted }});
  }

  console.log('\\nMigration Summary:');
  console.log(`Total: ${result.summary.total}`);
  console.log(`Successful: ${result.summary.successful}`);
  console.log(`Failed: ${result.summary.failed}`);

  // Handle failed items
  if (result.failed.length > 0) {
    console.log('\\nFailed items:', result.failed);
  }
}

migrateUsers().catch(console.error);

Error Handling

CipherionError Class

// src/errors/CipherionError.ts
class CipherionError extends Error {
  statusCode: number;
  details?: string;
  originalError?: Error;
}

Error handling Examples

// Error Handling Examples
import { CipherionError } from '@cipherion/client';

try {
  const encrypted = await cipherion.encrypt(data);
} catch (error) {
  if (error instanceof CipherionError) {
    console.error('Cipherion Error:', {
      message: error.message,
      statusCode: error.statusCode,
      details: error.details
    });

    // Handle specific errors
    switch (error.statusCode) {
      case 400:
        // Invalid request (e.g., missing passphrase)
        break;
      case 401:
        // Unauthorized (invalid API key)
        break;
      case 429:
        // Rate limit exceeded
        break;
      case 500:
        // Server error
        break;
    }
  }
}

Express Error Handling Middleware

// Express Error Handling Middleware
app.use((error, req, res, next) => {
  if (error instanceof CipherionError) {
    return res.status(error.statusCode).json({
      success: false,
      error: error.message,
      details: error.details
    });
  }

  res.status(500).json({
    success: false,
    error: 'Internal server error'
  });
});

NestJS Exception Filter

// NestJS Exception Filter
import { ExceptionFilter, Catch, ArgumentsHost, HttpStatus } from '@nestjs/common';
import { CipherionError } from '@cipherion/client';

@Catch(CipherionError)
export class CipherionExceptionFilter implements ExceptionFilter {
  catch(exception: CipherionError, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();

    response.status(exception.statusCode || HttpStatus.INTERNAL_SERVER_ERROR).json({
      success: false,
      statusCode: exception.statusCode,
      message: exception.message,
      details: exception.details,
    });
  }
}

// Apply globally
app.useGlobalFilters(new CipherionExceptionFilter());

Migration Guide

Best Practices for Large-Scale Migrations

  1. Start with a small batch to test your migration setup
  2. Use appropriate batch sizes (10-50 items recommended)
  3. Add delays between batches to avoid rate limiting
  4. Implement progress tracking for monitoring
  5. Log all errors for troubleshooting
  6. Keep backups of original data before migration

Example: Background Job Migration (Bull Queue)

import Queue from 'bull';
import CipherionClient from '@cipherion/client';

const encryptionQueue = new Queue('encryption', {
  redis: { host: 'localhost', port: 6379 }
});

// Add jobs to queue
async function queueEncryptionJobs(users) {
  for (const user of users) {
    await encryptionQueue.add('encrypt-user', { user });
  }
}

// Process jobs
encryptionQueue.process('encrypt-user', async (job) => {
  const cipherion = new CipherionClient();
  const { user } = job.data;
  
  try {
    const encrypted = await cipherion.deepEncrypt(user);
    await updateDatabase(user.id, encrypted.encrypted);
    return { success: true };
  } catch (error) {
    throw error; // Will be retried by Bull
  }
});

// Monitor progress
encryptionQueue.on('completed', (job) => {
  console.log(`User ${job.data.user.id} encrypted successfully`);
});

encryptionQueue.on('failed', (job, err) => {
  console.error(`Failed to encrypt user ${job.data.user.id}:`, err);
});

Security Best Practices

  1. Never hardcode credentials - Always use environment variables
  2. Use the same passphrase that was used to generate keys in the Cipherion dashboard
  3. Rotate passphrases regularly and re-encrypt data when doing so
  4. Restrict API key permissions in the dashboard to minimum required access
  5. Enable logging in production for audit trails
  6. Implement rate limiting on your endpoints to prevent abuse
  7. Use HTTPS for all API communications
  8. Store encrypted data separately from encryption keys
  9. Implement access controls for decryption operations
  10. Monitor usage and costs through the Cipherion dashboard

Logging

The SDK automatically logs operations to cipherion-logs/ directory:

  • error.log - Error-level logs only
  • combined.log - All logs
const cipherion = new CipherionClient({
  logLevel: 'debug', // 'error' | 'warn' | 'info' | 'debug'
  enableLogging: true
});

Support