AnkaSecure Crypto CLI Architecture
CLI Version: 3.4.0 Language: Java 25 Total Commands: 35 Build Tool: Maven 3.9+
This document provides an architecture overview of the AnkaSecure Crypto CLI, including how it parses command-line arguments, authenticates with the server, logs information, and delegates cryptographic logic to the remote AnkaSecure Core API through the AnkaSecureSdk and the AnkaSecureOpenApiClient.
Table of Contents
- Introduction
- High-Level Workflow
- Key Components
- Authentication Flow
- Configuration
- Error Handling
- Streaming vs Non-Streaming Operations
- Security Features
- Build & Distribution
- CLI Execution Lifecycle
- Related Documentation
1. Introduction
The AnkaSecure Crypto CLI is a command-line application that provides 26 subcommands for end-user cryptographic operations on data — encryption, decryption, signing, verification, combined operations, streaming, PKCS#7 conversion — plus read-only key browsing. Administrative key write/lifecycle operations are not part of this CLI; they live in the Key Management CLI (ankasecure-km) and the Admin Console. Despite offering a wide set of functionality, the CLI itself does not implement cryptographic logic directly. Instead, it:
CLI Responsibilities:
- Parses user commands and arguments (e.g.,
list-keys,encrypt-file-stream, etc.) - Authenticates against the AnkaSecure Core API with
clientIdandclientSecret - Delegates all actual cryptographic operations to the AnkaSecure Core API via a Java SDK (
AnkaSecureSdk) - Manages configuration, logging, and error handling
- Provides both command-line and interactive modes
Architectural Benefits:
By separating the CLI from the core cryptographic implementation, the solution achieves:
- Crypto-agility: Algorithm changes don't require CLI updates
- Centralized security: HSM-protected keys on server side
- Easy maintenance: CLI, SDK, and API evolve independently
- Client flexibility: Same API supports CLI, SDK, and custom clients
Users invoke commands locally, while the AnkaSecure Core API performs the secure operations server-side with HSM protection.
2. High-Level Workflow
Below is a simplified depiction of how the CLI processes a command:
Example command:
AnkaSecureCLI encrypt-file --kid my-ml-kem-key --input-file plaintext.txt --output-file ciphertext.bin
Processing flow:
Step 1: Command Parsing
The CLI main class (AnkaSecureCLI) parses the command-line arguments:
- Identifies command:
encrypt-file - Extracts parameters:
--kid my-ml-kem-key,--input-file plaintext.txt,--output-file ciphertext.bin - Validates required parameters are present
Step 2: Configuration Loading
Loads cli.properties or ~/.ankasecure-crypto/config.properties:
- Server connection:
openapi.scheme,openapi.host,openapi.port - Encrypted credentials:
clientIdEnc,clientSecretEnc - Timeouts, proxy settings, PQC transport options
Step 3: SDK Initialization
Constructs the AnkaSecureSdk instance with loaded configuration
Step 4: Authentication
Authenticates with the server:
- Decrypts credentials using PBKDF2 + AES-GCM
- Calls the token endpoint:
POST /api/v3/auth/token(grant_type=client_credentials) - Receives JWT Bearer token
- Token cached for subsequent requests
If authentication fails, prints error and exits with code 1.
Step 5: Command Dispatch
Routes the command to its handler method:
- Command
encrypt-file→ calls SDK methodencryptFile(kid, input, output) - Command
encrypt-file-stream→ calls SDK methodencryptFileStream(kid, input, output)
Step 6: SDK Delegation
The SDK method calls the corresponding OpenAPI client method:
AuthenticatedSdk.encrypt()→AnkaSecureOpenApiClientdata-plane call- Prepares request body and headers (including Bearer token)
Step 7: REST API Call
The OpenAPI client sends HTTP request to AnkaSecure Core API:
- Example:
POST /api/v3/crypto/encrypt - Headers:
Authorization: Bearer <jwt>,Content-Type: application/json - Body: the operation request (for encrypt:
kidand the Base64data)
Step 8: Response Handling
Success path:
- Server returns 200/201 with operation result
- CLI prints localized success message
- Displays operation metadata (key ID, algorithm, status)
- Exits with code 0
Error path:
- Server returns 4xx/5xx error
- SDK throws
AnkaSecureSdkException - CLI catches exception, logs to
devLogger - Prints user-friendly error message (localized)
- Exits with appropriate error code (1-3)
Step 9: Exit
CLI terminates with exit code indicating success or failure type.
3. Key Components
3.1 AnkaSecureCLI (Main Entry Point)
Location: co.ankatech.ankasecure.core.cli.AnkaSecureCLI
Entry Point: main(String[] args)
Responsibilities:
Configuration Management:
- Reads configuration from
cli.propertiesor~/.ankasecure-crypto/config.properties - Loads server connection details: scheme, host, port, timeouts
- Decrypts stored credentials using PBKDF2 + AES-GCM
Command Routing:
- Parses command-line arguments to identify command and parameters
- Routes to appropriate command handler (35 commands total)
- Validates required parameters before execution
Authentication:
- Authenticates with server using decrypted
clientIdandclientSecret - Manages JWT Bearer token lifecycle
- Handles token refresh when expired
Error Handling:
- Catches SDK exceptions and maps to user-friendly messages
- Logs detailed errors to
devLoggerfor troubleshooting - Manages exit codes:
- 0: Success
- 1: Invalid arguments
- 2: Not found (key doesn't exist)
- 3: Execution error (HTTP errors, I/O exceptions)
Mode Support:
- Command-line mode: Direct command execution
- Interactive mode: Menu-driven interface (launch with
-ior--interactive)
Key Principle: No cryptographic logic resides here; all operations delegated to AnkaSecureSdk.
3.2 AnkaSecureSdk (Client Bridge)
Location: co.ankatech.ankasecure.sdk.AnkaSecureSdk
Purpose: Main client-facing bridge to the remote AnkaSecure Core API
High-Level Operations:
- Key Management: Generate, import, export, list, remove, revoke, patch, rotate keys
- Encryption/Decryption: File encryption with symmetric or asymmetric keys (non-streaming and streaming)
- Digital Signatures: Sign and verify files with classical or post-quantum algorithms
- Key Rotation: Re-encrypt and re-sign operations for algorithm transitions
- Migration: Import PKCS#12 bundles, analyze and convert PKCS#7/CMS files
- Interoperability: Encrypt/verify with external public keys (not stored in keystore)
- License Management: Retrieve usage and entitlement information
Implementation Pattern:
The SDK provides high-level methods that abstract the REST API complexity:
- Method
encrypt(kid, plaintext)→ calls OpenAPI client →POST /api/v3/crypto/encrypt. Key provisioning is NOT on this path: the SDK is data-plane only, and creating a key is an Admin API operation reached throughankasecure-kmor the Admin Console. - Method
encryptFileStream(kid, input, output)→ calls OpenAPI client →POST /api/v3/crypto/stream/encrypt
Exception Handling:
Catches low-level exceptions (ApiException, IOException) and rethrows as unified AnkaSecureSdkException with clean error messages and correlation IDs.
3.3 AnkaSecureOpenApiClient (HTTP Client)
Location: co.ankatech.ankasecure.openapi.client.AnkaSecureOpenApiClient
Purpose: HTTP client layer that orchestrates REST API calls
Responsibilities:
HTTP Configuration:
- Configures OkHttp client with timeouts, proxy, SSL trust settings
- Applies properties from configuration file
- Manages connection pooling and keep-alive
Authentication:
- Adds
Authorization: Bearer <jwt>header to all requests - Manages token lifecycle and expiration
- Supports token refresh when expired
Request/Response Handling:
- Prepares request bodies (JSON serialization)
- Adds required headers (Content-Type, Accept, X-Correlation-ID)
- Handles multipart form-data for streaming operations
- Parses response bodies (JSON deserialization)
Streaming Support:
- Sets up streaming endpoints for large files
- Uses multipart form-data: metadata (JSON) + file stream (binary)
- Optional progress bar display for uploads (
openapi.enableProgressBar=true) - Memory-efficient: reads files in chunks (64 KB default)
PQC Transport Layer:
- Optional quantum-resistant transport encryption
- Encrypts request/response payloads with ML-KEM + AES-GCM
- Manages PQC sessions with Redis-backed state
- See PQC Transport Layer for details
3.4 OpenAPI-Generated Classes
Location: co.ankatech.secure.client.* (generated code)
Packages:
co.ankatech.secure.client.api- API interfaces (KeyManagementApi, SecureApi, StreamingApi, etc.)co.ankatech.secure.client.model- Model classes (EncryptRequest, EncryptResponse, KeyMetadata, etc.)co.ankatech.secure.client.invoker- ApiClient, configuration, exceptions
Generation Process:
Uses Maven plugin openapi-generator-maven-plugin with AnkaSecureAPI.json specification:
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<configuration>
<inputSpec>${project.basedir}/AnkaSecureAPI.json</inputSpec>
<generatorName>java</generatorName>
<library>okhttp-gson</library>
</configuration>
</plugin>
Responsibilities:
- Type-safe API: Java interfaces for all REST endpoints
- Model classes: Request/response DTOs with validation
- Serialization: JSON ↔ Java object mapping (Gson)
- Exception handling: Typed
ApiExceptionwith HTTP status codes
Note: These classes are auto-generated and should not be manually edited. See Maven OpenAPI Generator for regeneration instructions.
4. Authentication Flow
The CLI authenticates once at startup and reuses the JWT token for all subsequent operations.
Authentication Process:
Step 1: Load Credentials
The CLI reads encrypted credentials from configuration:
client.uuid- Installation-specific identifierclient.salt- Random salt for key derivationclientIdEnc- Encrypted client ID (Base64)clientSecretEnc- Encrypted client secret (Base64)
Step 2: Decrypt Credentials
Derives decryption key using PBKDF2-HMAC-SHA256 (150,000 iterations):
- Input:
client.uuid(password) +client.salt - Output: 256-bit AES key
Decrypts credentials using AES-GCM:
- Ciphertext format:
<IV:12 bytes><Ciphertext><AuthTag:16 bytes> - Result: Plaintext
clientIdandclientSecret
Step 3: Call Authentication Endpoint
SDK calls authentication API:
- Endpoint:
POST /api/v3/auth/token - Body (
application/x-www-form-urlencoded):grant_type=client_credentials,client_id,client_secret - Response:
{ access_token, token_type, expires_in }(norefresh_tokenis issued forclient_credentials)
Step 4: Store Token
JWT Bearer token cached in SDK for subsequent requests:
- Added to all API calls:
Authorization: Bearer <jwt> - Token lifetime: ~1 hour (configurable)
- Refresh token: ~7 days (for long-running processes)
Step 5: Execute Operations
All subsequent cryptographic operations reuse the authenticated SDK instance. No re-authentication required unless token expires.
Security Note: Credentials never sent in plaintext over network. Encryption at rest (config file) and in transit (TLS + optional PQC transport).
Credential Storage
The CLI uses AES-256-GCM encryption for secure credential storage:
flowchart LR
subgraph Init["init Command"]
UUID["Generate UUID"]
Salt["Generate Salt"]
PBKDF2["PBKDF2-HMAC-SHA256<br/>150,000 iterations"]
AES["AES-256-GCM"]
end
subgraph Storage["cli.properties"]
Props["client.uuid<br/>client.salt<br/>clientIdEnc<br/>clientSecretEnc"]
end
UUID --> PBKDF2
Salt --> PBKDF2
PBKDF2 -->|256-bit key| AES
AES --> Props Runtime Authentication
sequenceDiagram
participant CLI
participant SDK as AnkaSecureSdk
participant Auth as Auth API
CLI->>CLI: Load cli.properties
CLI->>CLI: Derive AES key (PBKDF2)
CLI->>CLI: Decrypt credentials
CLI->>SDK: authenticateApplication(clientId, secret)
SDK->>Auth: POST /api/v3/auth/token
Auth-->>SDK: {accessToken, refreshToken}
SDK->>SDK: Store tokens in memory
Note over SDK: Subsequent calls use Bearer token 5. Configuration
Server Connection
# API Server
openapi.scheme=https
openapi.host=dev.ankatech.co
openapi.port=443
openapi.insecureSkipTlsVerify=false # Set true for self-signed certs
# Timeouts
openapi.connectTimeoutMs=10000
openapi.readTimeoutMs=30000
openapi.writeTimeoutMs=30000
Proxy Support
# Optional proxy configuration
openapi.proxyHost=proxy.company.com
openapi.proxyPort=8080
openapi.proxyUser=username
openapi.proxyPassword=password
Logging Configuration
# Logging configuration
user.log.level=INFO
user.log.filename=AnkaSecureCLI.log
user.log.maxFileSize=5MB
openapi.debugging=false # Enable HTTP debug logs
Dual-Logger System
The CLI uses two separate loggers for different audiences:
User Logger (co.ankatech.cli.user):
- Purpose: User-facing messages
- Level: INFO, WARN, ERROR
- Output: Console + rolling file (
user.log) - Examples:
- "✓ Key generated successfully"
- "⚠ Warning: Key will expire in 30 days"
- "✗ Error: Key not found"
Dev Logger (co.ankatech.cli.dev):
- Purpose: Technical troubleshooting and debugging
- Level: DEBUG, TRACE
- Output: Rolling file only (
dev.log) - Examples:
- "SDK initialized with config: {...}"
- "HTTP POST /api/v3/crypto/encrypt → 200 OK"
- "Stack trace: AnkaSecureSdkException at line 145..."
Configuration: Managed via logback.xml in the CLI JAR.
Internationalization (i18n)
Resource Bundles:
The CLI uses Java ResourceBundle for all user-visible text:
messages.properties(English) - Defaultmessages_es.properties(Spanish)
Message Loading:
All user-facing text loaded from bundles:
- Success messages:
MSG.getString("encryptFileSuccess") - Error messages:
MSG.getString("keyNotFound") - HTTP status:
MSG.getString("http.401.unauthorized")
Locale Detection:
- Automatically detects system locale (
Locale.getDefault()) - Falls back to English if bundle not available
- Manual override:
-Duser.language=es
Supported Languages:
- English (en) - Default
- Spanish (es) - Complete translation
See Internationalization Guide for complete details.
6. Error Handling
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Invalid arguments |
| 2 | Command not found |
| 3 | Execution error |
HTTP Status Mapping
| HTTP Status | CLI Behavior |
|---|---|
| 400 | Bad Request error with context |
| 401 | Authentication failed |
| 403 | Insufficient permissions |
| 404 | Resource not found |
| 409 | Conflict (key exists) |
| 422 | Validation error |
| 5xx | Server error |
Internationalization
All user-facing messages support i18n:
messages.properties(English - default)messages_es.properties(Spanish)
7. Streaming vs Non-Streaming Operations
The CLI provides two modes for file operations to handle different file sizes efficiently.
Non-Streaming Mode
Commands: encrypt-file, decrypt-file, sign-file, verify-signature, reencrypt-file, resign-file
Characteristics:
- File size limit: < 100 MB recommended
- Memory usage: Loads entire file into memory
- Encoding: Base64-encoded JSON payloads
- HTTP method: Single POST request
- Speed: Faster for small files (less overhead)
Process:
- Read entire file into byte array
- Base64-encode file content
- Send as JSON body, for example encrypt:
{ "kid": "...", "data": "BASE64..." } - Receive JSON response, for example encrypt:
{ "jweToken": { ...JWE General JSON... }, "keyRequested": "...", ... } - Write the result to the output file (decrypt returns
decryptedData, which is Base64-decoded first)
Streaming Mode
Commands: encrypt-file-stream, decrypt-file-stream, sign-file-stream, verify-signature-stream, reencrypt-file-stream, resign-file-stream
Characteristics:
- File size limit: none in the API (tested up to 500 GB); a proxy in front of the deployment may cap uploads; see Behind a buffering proxy
- Memory usage: O(1) constant ~500 MB regardless of file size
- Encoding: Binary chunks with JSON metadata
- HTTP method: Multipart POST (header + file stream)
- Progress: Optional progress bar display
Process:
- Prepare JSON header with operation metadata
- Open file input stream
- Create multipart request:
- Part 1:
header(application/json) - Operation metadata - Part 2:
file(application/octet-stream) - File stream
- Part 1:
- Upload in chunks (default 64 KB)
- Server processes stream and returns detached result
- Write output stream to file
Performance:
- Small files (< 10 MB): Non-streaming faster (less overhead)
- Large files (> 100 MB): Streaming required (memory efficient)
- Huge files (> 1 GB): Streaming only option
8. Security Features
Credential Protection
| Feature | Implementation |
|---|---|
| Encryption | AES-256-GCM with 128-bit auth tag |
| Key Derivation | PBKDF2-HMAC-SHA256, 150,000 iterations |
| Salt | 128-bit random per credential |
| IV | 96-bit random per encryption |
Code Protection
| Feature | Implementation |
|---|---|
| JAR Signing | Timestamped code signature, on BOTH the thin jar and the runnable fat jar |
| Obfuscation | ProGuard runs on the thin jar only. The fat jar that ships is shaded before ProGuard runs, so the CLI classes inside it are NOT obfuscated |
| SDK | Readable in full. The data-plane SDK is not obfuscated: every class keeps its source name, so a CLI stack trace names real types |
Best Practices
- Protect
cli.propertieswith OS file permissions (chmod 600) - Use separate credentials per environment
- Enable TLS verification in production (
insecureSkipTlsVerify=false) - Rotate application credentials regularly
9. Build & Distribution
Build Pipeline
flowchart LR
Compile["Java 25<br/>Compile"] --> JAR["Thin JAR"]
JAR --> Shade["Maven Shade<br/>Fat JAR (runnable)"]
JAR --> Obfuscate["ProGuard<br/>thin JAR only"]
Shade --> SignFat["JAR Signing<br/>fat"]
Obfuscate --> SignThin["JAR Signing<br/>thin"]
SignFat --> Package["Install4J<br/>Installers"] Artifacts
| Artifact | Description |
|---|---|
AnkaSecureCLI-3.0.0.jar | Regular JAR |
AnkaSecureCLI-3.0.0-fat.jar | Fat JAR with every dependency but Bouncy Castle |
lib/bcprov-jdk18on.jar, lib/bcutil-jdk18on.jar, lib/bcpkix-jdk18on.jar | Bouncy Castle, unmodified and signed, loaded by the fat JAR's Class-Path |
| Windows Installer | .exe with bundled JRE 25 |
| macOS Installer | .dmg with bundled JRE 25 |
| Linux Installer | .sh with bundled JRE 25 |
Dependencies
| Dependency | Version | Purpose |
|---|---|---|
| AnkaSecure SDK | 3.0.0 | Core SDK library |
| Picocli | 4.7.7 | CLI framework |
| OkHttp | (transitive) | HTTP client |
| Bouncy Castle | (transitive) | PQC cryptography |
Jackson 2 (com.fasterxml.jackson) | (transitive) | JSON processing. The CLI resolves Jackson 2 only — the platform runs two Jackson majors side by side, and the Jackson 3 (tools.jackson) half is confined to three server-side mappers the CLI never links. See The Jackson Major Split* |
| Logback | 1.5.25 | Logging |
10. CLI Execution Lifecycle
Detailed execution flow from launch to exit:
Phase 1: Startup (0-100ms)
- JVM launches with
main(String[] args) - Parse global flags (
--help,--version,--interactive) - Initialize logging framework (Logback)
- Load configuration from file or prompt if missing
Phase 2: Configuration (100-200ms)
- Read
cli.propertiesor~/.ankasecure-crypto/config.properties - Decrypt credentials using PBKDF2 + AES-GCM (150,000 iterations)
- Validate required properties present
- Initialize SDK with configuration
Phase 3: Authentication (200-500ms)
- Call the token endpoint:
POST /api/v3/auth/token(grant_type=client_credentials) - Receive JWT Bearer token
- Cache token in SDK for reuse
- Set up HTTP headers for subsequent requests
Phase 4: Command Execution (variable)
- Parse command-specific arguments
- Validate required parameters
- Call SDK method (e.g.,
encrypt(),encryptFileStream()) - SDK calls OpenAPI client
- OpenAPI client sends HTTP request
- Server processes and returns response
Phase 5: Response Processing (50-100ms)
- Parse JSON response or stream output
- Validate response structure
- Extract operation metadata
- Print localized success message
- Log details to dev logger
Phase 6: Cleanup and Exit (0-50ms)
- Close open file streams
- Flush log buffers
- Exit with appropriate code (0-3)
Total execution time:
- Simple operations (list-keys): ~500ms
- Key generation: ~1-2 seconds
- Small file encryption: ~1-3 seconds
- Large file streaming (100 GB): Minutes to hours (depends on file size and network)
11. Related Documentation
CLI Documentation
User Guides:
- CLI Overview - High-level introduction to features and the 26 subcommands
- CLI Commands - Complete command reference with all parameters
- Interactive Mode - Menu-driven interface guide
- Installation Guide - Install CLI on your platform
Technical Documentation:
- Internationalization - Multi-language support (English/Spanish)
- OpenAPI Client - HTTP client, streaming, token management
- Maven OpenAPI Generator - Code generation from OpenAPI spec
SDK Documentation
The CLI is built on the AnkaSecure SDK:
- SDK Overview - SDK architecture and features
- SDK Usage Guide - Programmatic integration
- Integration Flows - 21 complete code examples
- PQC Transport Layer - Quantum-resistant transport encryption
Core API Documentation
The CLI calls the AnkaSecure Core API:
- Core API Overview* - REST API architecture
- Core API Endpoints* - HTTP endpoint reference
- Streaming Operations* - Large-file handling
Security & Algorithms
- Algorithm Catalog - 89 simple algorithm profiles and 41 composite pairings
- FIPS 140-3, Random Bit Generation and Approved Algorithms - FIPS 140-3 roles and approved algorithms
Last Updated: December 2025
CLI Version: 3.0.0 Java Version: 25
© 2025 ANKATech Solutions Inc. All rights reserved.