Deoxys-II Security-Focused API Documentation

Algorithm: Deoxys-II-256-128
Type: Authenticated Encryption with Associated Data (AEAD)
Security Level: 128-bit
Nonce Size: 120 bits (15 bytes)
Key Size: 256 bits (32 bytes)
Tag Size: 128 bits (16 bytes)
Standard: CAESAR Competition Finalist

Table of Contents

  1. Security Contract
  2. Attack Resistance Matrix
  3. Secure Usage Examples
  4. Common Mistakes
  5. Performance vs Security
  6. Platform-Specific Notes
  7. Compliance Information

Security Contract

encrypt(key: Uint8Array, nonce: Uint8Array, plaintext: Uint8Array, associatedData?: Uint8Array): { ciphertext: Uint8Array, tag: Uint8Array }

Preconditions:

Postconditions:

Side Effects:

decrypt(key: Uint8Array, nonce: Uint8Array, ciphertext: Uint8Array, tag: Uint8Array, associatedData?: Uint8Array): Uint8Array | null

Preconditions:

Postconditions:

Side Effects:

Attack Resistance Matrix

✅ Attacks Prevented

Attack Type Protection Mechanism Security Level
Forgery 128-bit authentication tag 2^-128 probability
Chosen Ciphertext AEAD construction with tag verification Complete protection
Nonce Misuse Deterministic encryption for same nonce Reveals plaintext equality only
Side-Channel (Timing) Constant-time operations No key-dependent branches
Related-Key Attacks Strong key schedule 256-bit security
Differential Cryptanalysis AES-based with strong mixing > 2^128 complexity
Linear Cryptanalysis Multiple AES rounds > 2^128 complexity
Padding Oracle No padding required Not applicable

❌ Attacks NOT Prevented

Attack Type Reason Mitigation Required
Nonce Reuse Same nonce reveals XOR of plaintexts Implement nonce management
Key Reuse Across Domains No domain separation Use different keys per context
Fault Injection No built-in fault detection Hardware countermeasures
Power Analysis (DPA) Implementation-dependent Use masked implementations
Replay Attacks No built-in replay protection Add sequence numbers
Traffic Analysis Ciphertext length reveals plaintext length Add padding scheme

⚠️ Security Limitations

  1. Nonce Size: 120-bit nonce allows ~2^60 encryptions before birthday collision
  2. Single Key: No built-in key rotation mechanism
  3. No Forward Secrecy: Compromised key reveals all past messages
  4. Deterministic: Same key/nonce/plaintext produces same ciphertext

Secure Usage Examples

Basic Encryption/Decryption

import { DeoxysII } from '@metamui/deoxys-ii';
import { randomBytes } from '@metamui/random';

// Generate a random key (store securely!)
const key = randomBytes(32);

// CRITICAL: Generate unique nonce for EVERY encryption
const nonce = randomBytes(15); // 120 bits

// Your sensitive data
const plaintext = new TextEncoder().encode('Secret message');
const associatedData = new TextEncoder().encode('metadata');

// Encrypt
const { ciphertext, tag } = DeoxysII.encrypt(
  key,
  nonce,
  plaintext,
  associatedData
);

// Store/transmit: nonce || ciphertext || tag
const message = new Uint8Array(nonce.length + ciphertext.length + tag.length);
message.set(nonce, 0);
message.set(ciphertext, nonce.length);
message.set(tag, nonce.length + ciphertext.length);

// Decrypt
const receivedNonce = message.slice(0, 15);
const receivedCiphertext = message.slice(15, -16);
const receivedTag = message.slice(-16);

const decrypted = DeoxysII.decrypt(
  key,
  receivedNonce,
  receivedCiphertext,
  receivedTag,
  associatedData
);

if (decrypted === null) {
  throw new Error('Authentication failed - data tampered!');
}

Secure Nonce Management

class SecureDeoxysII {
  private counter: bigint = 0n;
  private readonly maxCounter = (1n << 96n) - 1n; // Reserve 24 bits for randomness
  
  constructor(private readonly key: Uint8Array) {
    if (key.length !== 32) {
      throw new Error('Key must be 32 bytes');
    }
  }
  
  encrypt(plaintext: Uint8Array, associatedData?: Uint8Array): {
    nonce: Uint8Array;
    ciphertext: Uint8Array;
    tag: Uint8Array;
  } {
    // Generate nonce: 96-bit counter || 24-bit random
    if (this.counter > this.maxCounter) {
      throw new Error('Nonce counter exhausted - generate new key');
    }
    
    const nonce = new Uint8Array(15);
    const counterBytes = new Uint8Array(12);
    const randomBytes = crypto.getRandomValues(new Uint8Array(3));
    
    // Write counter as big-endian
    let c = this.counter++;
    for (let i = 11; i >= 0; i--) {
      counterBytes[i] = Number(c & 0xFFn);
      c >>= 8n;
    }
    
    nonce.set(counterBytes, 0);
    nonce.set(randomBytes, 12);
    
    const { ciphertext, tag } = DeoxysII.encrypt(
      this.key,
      nonce,
      plaintext,
      associatedData
    );
    
    return { nonce, ciphertext, tag };
  }
}

Streaming Large Files

async function encryptFile(
  key: Uint8Array,
  inputFile: File,
  chunkSize: number = 64 * 1024 // 64KB chunks
): AsyncGenerator<Uint8Array> {
  const fileId = randomBytes(8);
  let chunkIndex = 0;
  
  const reader = inputFile.stream().getReader();
  
  try {
    while (true) {
      const { done, value } = await reader.read();
      if (done) break;
      
      // Create unique nonce for each chunk
      const nonce = new Uint8Array(15);
      nonce.set(fileId, 0); // 8 bytes file ID
      const indexBytes = new Uint8Array(7);
      let idx = chunkIndex++;
      for (let i = 6; i >= 0; i--) {
        indexBytes[i] = idx & 0xFF;
        idx >>= 8;
      }
      nonce.set(indexBytes, 8);
      
      // Include chunk metadata in associated data
      const metadata = new Uint8Array(16);
      new DataView(metadata.buffer).setBigUint64(0, BigInt(chunkIndex - 1));
      new DataView(metadata.buffer).setBigUint64(8, BigInt(value.length));
      
      const { ciphertext, tag } = DeoxysII.encrypt(
        key,
        nonce,
        value,
        metadata
      );
      
      // Yield: nonce || ciphertext || tag
      const chunk = new Uint8Array(15 + ciphertext.length + 16);
      chunk.set(nonce, 0);
      chunk.set(ciphertext, 15);
      chunk.set(tag, 15 + ciphertext.length);
      
      yield chunk;
    }
  } finally {
    reader.releaseLock();
  }
}

Common Mistakes

❌ CRITICAL: Nonce Reuse

// NEVER DO THIS - Catastrophic security failure!
const fixedNonce = new Uint8Array(15); // All zeros

function insecureEncrypt(key: Uint8Array, data: Uint8Array): Uint8Array {
  // Using same nonce breaks security completely!
  const { ciphertext, tag } = DeoxysII.encrypt(key, fixedNonce, data);
  return new Uint8Array([...ciphertext, ...tag]);
}

// If attacker gets two ciphertexts with same nonce:
// ciphertext1 XOR ciphertext2 = plaintext1 XOR plaintext2

❌ Insufficient Nonce Randomness

// BAD: Predictable nonce generation
function badNonceGeneration(): Uint8Array {
  const nonce = new Uint8Array(15);
  const timestamp = Date.now();
  new DataView(nonce.buffer).setBigUint64(0, BigInt(timestamp));
  // Only 8 bytes of entropy - collisions likely!
  return nonce;
}

// GOOD: Cryptographically random nonce
function goodNonceGeneration(): Uint8Array {
  return crypto.getRandomValues(new Uint8Array(15));
}

❌ Ignoring Authentication Failures

// NEVER DO THIS - Opens door to attacks
function insecureDecrypt(key: Uint8Array, data: Uint8Array): Uint8Array {
  const nonce = data.slice(0, 15);
  const ciphertext = data.slice(15, -16);
  const tag = data.slice(-16);
  
  const result = DeoxysII.decrypt(key, nonce, ciphertext, tag);
  
  // WRONG: Returning partial data on failure
  if (result === null) {
    console.warn('Authentication failed, returning ciphertext');
    return ciphertext; // NEVER DO THIS!
  }
  
  return result;
}

// CORRECT: Always fail completely
function secureDecrypt(key: Uint8Array, data: Uint8Array): Uint8Array {
  const result = DeoxysII.decrypt(key, nonce, ciphertext, tag);
  
  if (result === null) {
    throw new Error('Authentication failed - data integrity compromised');
  }
  
  return result;
}

❌ Key Derivation Mistakes

// BAD: Weak key derivation
const weakKey = new TextEncoder().encode('my-password-123').slice(0, 32);

// GOOD: Proper key derivation
import { Argon2 } from '@metamui/argon2';

async function deriveKey(password: string, salt: Uint8Array): Promise<Uint8Array> {
  return await Argon2.hash(password, salt, {
    outputLength: 32,
    timeCost: 3,
    memoryCost: 65536,
    parallelism: 4
  });
}

Performance vs Security

Optimization Guidelines

Optimization Security Impact Recommendation
Parallel Processing None - inherently parallel ✅ Use for large data
Nonce Precomputation None if unique ✅ Acceptable
Key Caching Increases key exposure time ⚠️ Limit cache duration
Tag Truncation Reduces security exponentially ❌ Never truncate
Skip Authentication Complete security failure ❌ Never skip

Performance Characteristics

// Benchmark results (approximate)
// Platform: Intel i7-10700K @ 3.8GHz
// 
// Small messages (< 1KB): ~2-3 μs
// Medium messages (1MB): ~1-2 ms  
// Large messages (100MB): ~100-150 ms
// 
// Throughput: ~800-1000 MB/s

Platform-Specific Notes

TypeScript/JavaScript

Python

Rust

Swift

Kotlin/JVM

WASM

Compliance Information

Standards Compliance

Security Certifications

Regulatory Considerations

Ideal for:

Not recommended for:


Security Notice: This implementation has been professionally audited. However, always perform your own security assessment before production use. Report security issues to security@metamui.id

Last Updated: 2025-07-06
**Version
: 3.0.0
License: BSL-1.1

Security Analysis

Threat Model: Deoxys-II Threat Model

The comprehensive threat analysis covers:

For complete security analysis and risk assessment, see the dedicated threat model documentation.