# How AionUi Plugin Credential Encryption Works Using Base64 in credentialCrypto.ts

> Discover how AionUi encrypts plugin credentials using Base64 in credentialCrypto.ts for secure storage in SQLite. Learn about obfuscation and backward compatibility.

- Repository: [OfficeAI/AionUi](https://github.com/iofficeai/aionui)
- Tags: internals
- Published: 2026-02-16

---

**AionUi uses Base64 encoding with format prefixes in [`credentialCrypto.ts`](https://github.com/iOfficeAI/AionUi/blob/main/credentialCrypto.ts) to obfuscate plugin credentials like OAuth tokens and API keys before persisting them to SQLite, while maintaining backward compatibility with legacy storage formats.**

The AionUi desktop application manages sensitive plugin configurations—such as Telegram bot tokens or OAuth credentials—through a lightweight encryption layer implemented in [`src/channels/utils/credentialCrypto.ts`](https://github.com/iOfficeAI/AionUi/blob/main/src/channels/utils/credentialCrypto.ts). Rather than storing secrets in plain text within the local SQLite database, the module applies Base64 transformation with identifiable prefixes to deter casual inspection and support migration from older encryption schemes.

## Core Encryption Functions in credentialCrypto.ts

The [`credentialCrypto.ts`](https://github.com/iOfficeAI/AionUi/blob/main/credentialCrypto.ts) module exposes two primary string-level functions that handle the encoding and decoding of individual credential values.

### String-Level Encoding with encryptString

The `encryptString(plaintext)` function converts sensitive strings into obfuscated form using the following algorithm as implemented in lines 26-33:

1. Validates that the input is a non-empty string
2. Converts the string to UTF-8 bytes
3. Applies Base64 encoding
4. Prefixes the result with `b64:` to identify the transformation format

If the conversion throws an exception (for example, due to unexpected binary input), the function falls back to prefixing the original value with `plain:` to ensure the credential is never lost during the encryption attempt.

### String-Level Decoding with decryptString

The `decryptString(encoded)` function reverses the obfuscation process and handles multiple legacy formats as defined in lines 44-77:

- **`plain:` prefix** → Returns the substring unchanged (lines 48-50)
- **`b64:` prefix** → Strips the prefix and decodes the Base64 payload back to UTF-8 (lines 52-60)
- **`enc:` prefix** → Legacy format from an older safe-storage mechanism; accepted for backward compatibility (lines 62-70)
- **No recognized prefix** → Returns the value as-is, preserving data that pre-dated the encoding feature (lines 74-77)

## Object-Level Credential Handling

For practical use with plugin configurations, the module provides object-level wrappers that target specific sensitive fields.

### Encrypting Plugin Credential Objects

The `encryptCredentials(credentials)` function creates a shallow copy of the supplied object and applies `encryptString` **only to the `token` field** (lines 84-90). This selective approach ensures that only the sensitive authentication secret is obfuscated while leaving other configuration parameters (such as API endpoints or usernames) in readable form for debugging purposes.

### Decrypting Stored Credentials

Conversely, `decryptCredentials(credentials)` mirrors the encryption step by applying `decryptString` to the `token` field of the stored object (lines 96-101). This restores the original plain-text credential for runtime use by plugin implementations such as [`TelegramPlugin.ts`](https://github.com/iOfficeAI/AionUi/blob/main/TelegramPlugin.ts).

## Database Integration and Storage Flow

The encryption layer integrates with the persistence tier in [`src/process/database/index.ts`](https://github.com/iOfficeAI/AionUi/blob/main/src/process/database/index.ts) (lines 871-884). When a plugin configuration is saved, the system first passes the credentials object through `encryptCredentials` before serializing it to JSON and writing to the SQLite `plugin_config` table. On retrieval, the database layer invokes `decryptCredentials` to restore the sensitive values before passing the configuration to the plugin constructor.

This architecture ensures that the SQLite database file contains only obfuscated tokens (prefixed with `b64:`) rather than plain-text secrets, mitigating the risk of credential exposure through casual file inspection or accidental version control commits.

## Code Examples

### String-Level Encryption and Decryption

```typescript
import {
  encryptString,
  decryptString,
} from '@/channels/utils/credentialCrypto';

const rawToken = 'my-secret-token-123';

// Encode: produces "b64:bXktc2VjcmV0LXRva2VuLTEyMw=="
const encoded = encryptString(rawToken);
console.log(encoded);

// Decode: restores "my-secret-token-123"
const decoded = decryptString(encoded);
console.log(decoded);

```

### Object-Level Credential Handling

```typescript
import {
  encryptCredentials,
  decryptCredentials,
} from '@/channels/utils/credentialCrypto';

const credObj = { token: 'my-secret-token-123', apiUrl: 'https://api.example.com' };

// Encrypt only the token field
const stored = encryptCredentials(credObj);
// stored.token === "b64:bXktc2VjcmV0LXRva2VuLTEyMw=="
// stored.apiUrl remains "https://api.example.com"

// Decrypt for runtime use
const restored = decryptCredentials(stored);
// restored.token === "my-secret-token-123"

```

### Database Persistence Flow

```typescript
import { encryptCredentials, decryptCredentials } from '@/channels/utils/credentialCrypto';
import db from '@/process/database';

// Saving plugin configuration
async function savePluginConfig(pluginType: string, token: string) {
  const encrypted = encryptCredentials({ token });
  await db.run(
    `INSERT INTO plugin_config (type, credentials) VALUES (?, ?)`,
    [pluginType, JSON.stringify(encrypted)]
  );
}

// Loading plugin configuration
async function loadPluginConfig(pluginType: string) {
  const row = await db.get(
    `SELECT credentials FROM plugin_config WHERE type = ?`,
    [pluginType]
  );
  const stored = JSON.parse(row.credentials);
  return decryptCredentials(stored);
}

```

## Summary

- **AionUi** stores plugin credentials in SQLite using lightweight **Base64 obfuscation** rather than plain text.
- The **[`credentialCrypto.ts`](https://github.com/iOfficeAI/AionUi/blob/main/credentialCrypto.ts)** module provides `encryptString` and `decryptString` functions that prefix encoded values with `b64:` for identification.
- **Object-level helpers** `encryptCredentials` and `decryptCredentials` target only the `token` field, leaving other configuration parameters readable.
- The system maintains **backward compatibility** with legacy formats (`enc:`, `plain:`, and unprefixed values) to prevent data loss during upgrades.
- Integration occurs in **[`src/process/database/index.ts`](https://github.com/iOfficeAI/AionUi/blob/main/src/process/database/index.ts)**, ensuring credentials are obfuscated before persistence and restored before runtime use.

## Frequently Asked Questions

### Is AionUi's Base64 credential encryption secure?

No, the Base64 encoding used in [`credentialCrypto.ts`](https://github.com/iOfficeAI/AionUi/blob/main/credentialCrypto.ts) is **obfuscation, not encryption**. It is designed to deter casual inspection of the SQLite database file rather than protect against determined attackers. The implementation explicitly avoids cryptographic algorithms in favor of simple Base64 transformation with format prefixes, making it unsuitable for high-security environments requiring true encryption.

### What happens if decryptString encounters an unknown format?

The `decryptString` function handles unrecognized prefixes gracefully by returning the value unchanged. According to lines 74-77 of [`credentialCrypto.ts`](https://github.com/iOfficeAI/AionUi/blob/main/credentialCrypto.ts), if the encoded string lacks a recognized prefix (`b64:`, `plain:`, or `enc:`), the function returns the raw string as-is. This ensures that legacy credentials or manually inserted values never cause runtime failures during the decryption process.

### Which fields are encrypted in plugin credentials?

The `encryptCredentials` function encrypts **only the `token` field** of the credentials object. As implemented in lines 84-90 of [`credentialCrypto.ts`](https://github.com/iOfficeAI/AionUi/blob/main/credentialCrypto.ts), the function creates a shallow copy of the input object and applies `encryptString` exclusively to the `token` property. Other fields such as `apiUrl`, `username`, or custom configuration parameters remain in plain text to facilitate debugging and manual database inspection.

### Where does AionUi store encrypted credentials?

AionUi persists encrypted credentials in a **local SQLite database** managed by the database layer in [`src/process/database/index.ts`](https://github.com/iOfficeAI/AionUi/blob/main/src/process/database/index.ts). When saving plugin configurations, the system serializes the encrypted credentials object to JSON and stores it in the `plugin_config` table. The encryption occurs immediately before the database write operation (lines 871-884), ensuring that the SQLite file contains only obfuscated `b64:` prefixed tokens rather than sensitive plain-text secrets.