Ascon Security-Focused API Documentation

Algorithm: Ascon-128 / Ascon-128a
Type: Authenticated Encryption with Associated Data (AEAD) & Hashing
Security Level: 128-bit
Key Size: 128 bits (16 bytes)
Nonce Size: 128 bits (16 bytes)
Tag Size: 128 bits (16 bytes)
Standard: NIST Lightweight Cryptography Winner (2023)

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:

hash(message: Uint8Array, outputLength?: number): Uint8Array

Preconditions:

Postconditions:

Side Effects:

Attack Resistance Matrix

✅ Attacks Prevented

Attack Type Protection Mechanism Security Level
Forgery 128-bit authentication tag 2^-128 probability
Key Recovery Sponge construction security 2^128 operations
State Recovery Large internal state (320 bits) Not feasible
Differential Cryptanalysis 12 rounds (Ascon-128) > 2^128 complexity
Linear Cryptanalysis Strong S-box design > 2^128 complexity
Cube Attacks Sufficient rounds No practical attacks
Side-Channel (Timing) Bitsliced implementation Constant-time
Power Analysis Low power design Reduced leakage
Fault Attacks Redundancy in state Detection possible

❌ Attacks NOT Prevented

Attack Type Reason Mitigation Required
Nonce Reuse Deterministic encryption Strict nonce management
Multi-Target Birthday bound on tags Limit encryptions per key
Quantum Attacks Symmetric primitive Use 256-bit variant
Replay Attacks No built-in replay protection Add timestamps
Key Commitment Not built-in Add key commitment if needed

⚠️ Security Limitations

  1. 128-bit Security: May be insufficient for long-term security
  2. Nonce Size: Large nonce (128 bits) requires careful management
  3. Lightweight Focus: Optimized for efficiency over maximum security
  4. Single Key: No built-in key separation

Secure Usage Examples

Basic AEAD Encryption

import { Ascon } from '@metamui/ascon';
import { randomBytes } from '@metamui/random';

class SecureAscon {
  static encrypt(
    key: Uint8Array,
    plaintext: Uint8Array,
    associatedData?: Uint8Array
  ): {
    nonce: Uint8Array;
    ciphertext: Uint8Array;
    tag: Uint8Array;
  } {
    if (key.length !== 16) {
      throw new Error('Key must be 128 bits');
    }
    
    // Generate unique nonce
    const nonce = randomBytes(16);
    
    // Encrypt with Ascon-128
    const { ciphertext, tag } = Ascon.encrypt(
      key,
      nonce,
      plaintext,
      associatedData
    );
    
    return { nonce, ciphertext, tag };
  }
  
  static decrypt(
    key: Uint8Array,
    nonce: Uint8Array,
    ciphertext: Uint8Array,
    tag: Uint8Array,
    associatedData?: Uint8Array
  ): Uint8Array | null {
    return Ascon.decrypt(
      key,
      nonce,
      ciphertext,
      tag,
      associatedData
    );
  }
}

IoT Device Communication

class IoTSecureChannel {
  private readonly deviceId: Uint8Array;
  private messageCounter: bigint = 0n;
  
  constructor(
    private readonly sharedKey: Uint8Array,
    deviceId: string
  ) {
    this.deviceId = new TextEncoder().encode(deviceId);
  }
  
  sendMessage(
    command: string,
    payload: Uint8Array
  ): {
    packet: Uint8Array;
  } {
    // Create nonce from device ID and counter
    const nonce = new Uint8Array(16);
    nonce.set(this.deviceId.slice(0, 8), 0);
    
    const counterBytes = new Uint8Array(8);
    for (let i = 7; i >= 0; i--) {
      counterBytes[i] = Number(this.messageCounter & 0xFFn);
      this.messageCounter >>= 8n;
    }
    nonce.set(counterBytes, 8);
    this.messageCounter++;
    
    // Create associated data
    const associatedData = new TextEncoder().encode(
      `${command}:${Date.now()}`
    );
    
    // Encrypt payload
    const { ciphertext, tag } = Ascon.encrypt(
      this.sharedKey,
      nonce,
      payload,
      associatedData
    );
    
    // Build packet: command(1) || nonce(16) || tag(16) || ciphertext
    const packet = new Uint8Array(
      1 + 16 + 16 + ciphertext.length
    );
    packet[0] = command.charCodeAt(0);
    packet.set(nonce, 1);
    packet.set(tag, 17);
    packet.set(ciphertext, 33);
    
    return { packet };
  }
  
  receiveMessage(packet: Uint8Array): {
    command: string;
    payload: Uint8Array;
  } | null {
    if (packet.length < 33) {
      return null; // Too short
    }
    
    const command = String.fromCharCode(packet[0]);
    const nonce = packet.slice(1, 17);
    const tag = packet.slice(17, 33);
    const ciphertext = packet.slice(33);
    
    // Verify counter is newer
    const receivedCounter = new DataView(
      nonce.buffer,
      nonce.byteOffset + 8
    ).getBigUint64(0);
    
    if (receivedCounter <= this.messageCounter) {
      return null; // Replay attack
    }
    
    // Decrypt and verify
    const associatedData = new TextEncoder().encode(
      `${command}:${Date.now()}`
    );
    
    const payload = Ascon.decrypt(
      this.sharedKey,
      nonce,
      ciphertext,
      tag,
      associatedData
    );
    
    if (payload === null) {
      return null; // Authentication failed
    }
    
    // Update counter
    this.messageCounter = receivedCounter;
    
    return { command, payload };
  }
}

Lightweight File Encryption

class AsconFileEncryption {
  static async encryptFile(
    key: Uint8Array,
    inputFile: File,
    chunkSize: number = 4096 // 4KB chunks for low memory
  ): Promise<Uint8Array> {
    const chunks: Uint8Array[] = [];
    const fileNonce = randomBytes(16);
    
    // File metadata as associated data
    const metadata = new TextEncoder().encode(JSON.stringify({
      name: inputFile.name,
      size: inputFile.size,
      type: inputFile.type,
      modified: inputFile.lastModified
    }));
    
    const reader = inputFile.stream().getReader();
    let chunkIndex = 0;
    
    try {
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        
        // Derive per-chunk nonce
        const chunkNonce = new Uint8Array(fileNonce);
        new DataView(chunkNonce.buffer).setUint32(12, chunkIndex++);
        
        // Encrypt chunk
        const { ciphertext, tag } = Ascon.encrypt(
          key,
          chunkNonce,
          value,
          metadata
        );
        
        // Store tag + ciphertext
        const chunk = new Uint8Array(16 + ciphertext.length);
        chunk.set(tag, 0);
        chunk.set(ciphertext, 16);
        chunks.push(chunk);
      }
      
      // Build final file: fileNonce || metadataLen || metadata || chunks
      const metadataLenBytes = new Uint8Array(4);
      new DataView(metadataLenBytes.buffer).setUint32(0, metadata.length);
      
      const totalSize = 16 + 4 + metadata.length + 
        chunks.reduce((sum, chunk) => sum + chunk.length, 0);
      
      const encrypted = new Uint8Array(totalSize);
      let offset = 0;
      
      encrypted.set(fileNonce, offset);
      offset += 16;
      
      encrypted.set(metadataLenBytes, offset);
      offset += 4;
      
      encrypted.set(metadata, offset);
      offset += metadata.length;
      
      for (const chunk of chunks) {
        encrypted.set(chunk, offset);
        offset += chunk.length;
      }
      
      return encrypted;
    } finally {
      reader.releaseLock();
    }
  }
}

Ascon-Hash for Key Derivation

class AsconKDF {
  static deriveKey(
    password: string,
    salt: Uint8Array,
    outputLength: number = 32
  ): Uint8Array {
    // Use Ascon-Hash for key derivation
    const passwordBytes = new TextEncoder().encode(password);
    
    // Combine password and salt
    const input = new Uint8Array(passwordBytes.length + salt.length);
    input.set(passwordBytes, 0);
    input.set(salt, passwordBytes.length);
    
    // Hash with Ascon
    const hash = Ascon.hash(input, outputLength);
    
    // Clear sensitive data
    input.fill(0);
    
    return hash;
  }
  
  static async deriveMultipleKeys(
    masterKey: Uint8Array,
    context: string,
    keyCount: number
  ): Promise<Uint8Array[]> {
    const keys: Uint8Array[] = [];
    
    for (let i = 0; i < keyCount; i++) {
      const info = new TextEncoder().encode(`${context}-${i}`);
      const input = new Uint8Array(masterKey.length + info.length);
      input.set(masterKey, 0);
      input.set(info, masterKey.length);
      
      keys.push(Ascon.hash(input, 16)); // 128-bit keys
      
      input.fill(0);
    }
    
    return keys;
  }
}

Common Mistakes

❌ Nonce Reuse

// NEVER DO THIS - Catastrophic failure
class BrokenAscon {
  private static FIXED_NONCE = new Uint8Array(16); // All zeros!
  
  static encrypt(key: Uint8Array, data: Uint8Array): Uint8Array {
    // Reusing nonce breaks security completely
    const { ciphertext, tag } = Ascon.encrypt(
      key,
      this.FIXED_NONCE, // NEVER DO THIS!
      data
    );
    return new Uint8Array([...ciphertext, ...tag]);
  }
}

❌ Insufficient Nonce Randomness

// BAD - Predictable nonce
function weakNonce(): Uint8Array {
  const nonce = new Uint8Array(16);
  const time = Date.now();
  new DataView(nonce.buffer).setBigUint64(0, BigInt(time));
  // Only 8 bytes of entropy!
  return nonce;
}

// GOOD - Full randomness
function strongNonce(): Uint8Array {
  return randomBytes(16);
}

❌ Tag Truncation

// WRONG - Reducing security
function insecureEncrypt(key: Uint8Array, data: Uint8Array): {
  ciphertext: Uint8Array;
  shortTag: Uint8Array;
} {
  const { ciphertext, tag } = Ascon.encrypt(key, randomBytes(16), data);
  
  // NEVER truncate the tag!
  return {
    ciphertext,
    shortTag: tag.slice(0, 8) // Only 64 bits - INSECURE!
  };
}

❌ Using for Password Hashing

// WRONG - Ascon-Hash not designed for passwords
function badPasswordHash(password: string): Uint8Array {
  return Ascon.hash(new TextEncoder().encode(password));
}

// CORRECT - Use proper password hashing
import { Argon2 } from '@metamui/argon2';

async function goodPasswordHash(password: string): Promise<Uint8Array> {
  const salt = randomBytes(16);
  return Argon2.hash(password, salt);
}

Performance vs Security

Variant Comparison

Variant Rate Security Use Case
Ascon-128 64 bits/round Standard General purpose
Ascon-128a 128 bits/round Standard Higher throughput
Ascon-Hash - Collision resistant Hashing
Ascon-Xof - Variable output Key derivation

Performance Characteristics

// Benchmark results (approximate)
// Platform: ARM Cortex-M4 @ 48MHz
// 
// Ascon-128 AEAD:
// - Setup: ~500 cycles
// - Per byte: ~15 cycles
// - Tag generation: ~800 cycles
// 
// Compared to AES-GCM:
// - 3x less ROM
// - 5x less RAM  
// - Similar speed on small messages
// - Better on constrained devices

Optimization for Microcontrollers

class AsconMCU {
  // Bit-sliced implementation for 32-bit MCUs
  static optimizedEncrypt(
    key: Uint8Array,
    nonce: Uint8Array,
    plaintext: Uint8Array
  ): { ciphertext: Uint8Array; tag: Uint8Array } {
    // Use 32-bit word operations
    const state = new Uint32Array(10); // 320-bit state
    
    // Initialize with key and nonce
    // ... (bit-sliced operations)
    
    // Process data in 64-bit blocks (Ascon-128)
    // ... (optimized for 32-bit MCU)
    
    return Ascon.encrypt(key, nonce, plaintext);
  }
}

Platform-Specific Notes

Embedded Systems

JavaScript/TypeScript

Hardware

Mobile

Compliance Information

Standards and Recognition

Security Analysis

Ideal for:

Not recommended for:

Implementation Requirements


Security Notice: Ascon is the NIST Lightweight Cryptography standard. It provides excellent security for constrained environments. Always ensure proper nonce management. Report issues to security@metamui.id

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

Security Analysis

Threat Model: Ascon-128 Threat Model

The comprehensive threat analysis covers:

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