ARIA-256 Security-Focused API Documentation
Algorithm: ARIA-256
Type: Symmetric Block Cipher
Security Level: 256-bit
Block Size: 128 bits (16 bytes)
Key Size: 256 bits (32 bytes)
Origin: Korean Standard (KS X 1213:2004)
Standard: RFC 5794, ISO/IEC 18033-3
Table of Contents
- Security Contract
- Attack Resistance Matrix
- Secure Usage Examples
- Common Mistakes
- Performance vs Security
- Platform-Specific Notes
- Compliance Information
Security Contract
encrypt(key: Uint8Array, plaintext: Uint8Array, mode: string, iv?: Uint8Array): Uint8Array
Preconditions:
keyMUST be exactly 32 bytes (256 bits)plaintextlength requirements depend on modemodeMUST be one of: ‘ECB’, ‘CBC’, ‘CTR’, ‘GCM’, ‘CCM’ivrequired for all modes except ECB (16 bytes)ivMUST be unique for each encryption with same key- For CCM mode, nonce length can be 7-13 bytes
Postconditions:
- Returns ciphertext (length depends on mode and padding)
- For authenticated modes (GCM/CCM), includes authentication tag
- Ciphertext indistinguishable from random without key
- No information leakage through timing
Side Effects:
- May allocate memory for padding/expansion
- No key-dependent timing variations
decrypt(key: Uint8Array, ciphertext: Uint8Array, mode: string, iv?: Uint8Array, tag?: Uint8Array): Uint8Array | null
Preconditions:
keyMUST match encryption keyciphertextMUST be valid encrypted datamodeMUST match encryption modeivMUST match encryption IV/noncetagrequired for GCM/CCM modes
Postconditions:
- Returns original plaintext on success
- Returns null if authentication fails (GCM/CCM)
- Removes padding automatically (CBC mode)
- Constant-time authentication check
Side Effects:
- No timing variations based on decryption result
- Memory cleared after use
Attack Resistance Matrix
✅ Attacks Prevented
| Attack Type | Protection Mechanism | Security Level |
|---|---|---|
| Brute Force | 256-bit key space | 2^256 operations |
| Differential Cryptanalysis | Involutional SPN structure | > 2^256 complexity |
| Linear Cryptanalysis | Strong S-boxes from inverse function | > 2^256 complexity |
| Impossible Differential | 16 rounds with strong diffusion | No practical attacks |
| Boomerang Attacks | Full rounds prevent | > 2^256 complexity |
| Related-Key Attacks | Strong key schedule | Best: 2^245 (theoretical) |
| Algebraic Attacks | High algebraic degree | Not vulnerable |
| Slide Attacks | Round constants in key schedule | Not vulnerable |
❌ Attacks NOT Prevented (Mode-Dependent)
| Attack Type | Vulnerable Modes | Mitigation Required |
|---|---|---|
| Padding Oracle | CBC with padding | Use authenticated modes |
| Bit-Flipping | CTR, CBC | Use GCM/CCM |
| IV/Nonce Reuse | CTR, GCM, CCM | Unique IV management |
| Pattern Analysis | ECB | Never use ECB |
| Chosen Ciphertext | Non-authenticated modes | Use GCM/CCM |
| Replay Attacks | All modes | Add sequence numbers |
⚠️ Security Limitations
- Korean Origin: May face scrutiny in some jurisdictions
- Less Analysis: Not as extensively studied as AES
- Patent Status: Was patented (now expired)
- Implementation Maturity: Fewer optimized implementations
Secure Usage Examples
Authenticated Encryption with GCM
import { ARIA256 } from '@metamui/aria256';
import { randomBytes } from '@metamui/random';
class SecureARIA {
private static readonly TAG_LENGTH = 16; // 128-bit tag
static encrypt(
key: Uint8Array,
plaintext: Uint8Array,
associatedData?: Uint8Array
): {
ciphertext: Uint8Array;
nonce: Uint8Array;
tag: Uint8Array;
} {
if (key.length !== 32) {
throw new Error('Key must be 256 bits');
}
// Generate random nonce for GCM
const nonce = randomBytes(12); // 96-bit nonce recommended
// Encrypt with authentication
const result = ARIA256.encryptGCM(
key,
nonce,
plaintext,
associatedData
);
return {
ciphertext: result.ciphertext,
nonce: nonce,
tag: result.tag
};
}
static decrypt(
key: Uint8Array,
ciphertext: Uint8Array,
nonce: Uint8Array,
tag: Uint8Array,
associatedData?: Uint8Array
): Uint8Array | null {
try {
return ARIA256.decryptGCM(
key,
nonce,
ciphertext,
tag,
associatedData
);
} catch (e) {
// Authentication failed
return null;
}
}
}
Counter Mode with HMAC
import { HMAC } from '@metamui/hmac';
import { SHA256 } from '@metamui/sha256';
class ARIACTRWithHMAC {
private static deriveKeys(
masterKey: Uint8Array
): { encKey: Uint8Array; macKey: Uint8Array } {
// Derive separate keys for encryption and MAC
const encKey = HMAC.compute(
masterKey,
new TextEncoder().encode('ARIA-ENCRYPTION-KEY'),
SHA256
).slice(0, 32);
const macKey = HMAC.compute(
masterKey,
new TextEncoder().encode('ARIA-MAC-KEY'),
SHA256
);
return { encKey, macKey };
}
static encryptAuthenticated(
masterKey: Uint8Array,
plaintext: Uint8Array
): {
ciphertext: Uint8Array;
iv: Uint8Array;
mac: Uint8Array;
} {
const { encKey, macKey } = this.deriveKeys(masterKey);
// Generate random IV
const iv = randomBytes(16);
// Encrypt using CTR mode
const ciphertext = ARIA256.encryptCTR(encKey, iv, plaintext);
// Compute MAC over IV || ciphertext
const macData = new Uint8Array(iv.length + ciphertext.length);
macData.set(iv, 0);
macData.set(ciphertext, iv.length);
const mac = HMAC.compute(macKey, macData, SHA256);
// Clear derived keys
encKey.fill(0);
macKey.fill(0);
return { ciphertext, iv, mac };
}
}
CCM Mode for Constrained Devices
class ARIACCMMode {
static encryptCCM(
key: Uint8Array,
plaintext: Uint8Array,
associatedData: Uint8Array,
nonceLength: number = 13 // 13 bytes recommended
): {
ciphertext: Uint8Array;
nonce: Uint8Array;
tag: Uint8Array;
} {
if (nonceLength < 7 || nonceLength > 13) {
throw new Error('Nonce length must be 7-13 bytes');
}
// Generate nonce
const nonce = randomBytes(nonceLength);
// CCM requires knowing all lengths upfront
const result = ARIA256.encryptCCM(
key,
nonce,
plaintext,
associatedData,
16 // tag length
);
return {
ciphertext: result.ciphertext,
nonce: nonce,
tag: result.tag
};
}
}
Secure Key Rotation
class ARIAKeyRotation {
private static readonly KEY_LIFETIME = 30 * 24 * 60 * 60 * 1000; // 30 days
private keys: Map<number, { key: Uint8Array; created: number }> = new Map();
private currentKeyId: number = 0;
constructor(private readonly masterSecret: Uint8Array) {
this.rotateKey();
}
private deriveKey(keyId: number): Uint8Array {
const info = new Uint8Array(4);
new DataView(info.buffer).setUint32(0, keyId);
return HKDF.expand(
this.masterSecret,
info,
32,
'ARIA-256-KEY'
);
}
private rotateKey(): void {
this.currentKeyId++;
const newKey = this.deriveKey(this.currentKeyId);
this.keys.set(this.currentKeyId, {
key: newKey,
created: Date.now()
});
// Clean old keys
const cutoff = Date.now() - this.KEY_LIFETIME * 2;
for (const [id, data] of this.keys.entries()) {
if (data.created < cutoff) {
data.key.fill(0);
this.keys.delete(id);
}
}
}
encrypt(plaintext: Uint8Array): {
keyId: number;
ciphertext: Uint8Array;
nonce: Uint8Array;
tag: Uint8Array;
} {
// Check if rotation needed
const currentKey = this.keys.get(this.currentKeyId)!;
if (Date.now() - currentKey.created > this.KEY_LIFETIME) {
this.rotateKey();
}
const result = SecureARIA.encrypt(
this.keys.get(this.currentKeyId)!.key,
plaintext
);
return {
keyId: this.currentKeyId,
...result
};
}
}
Common Mistakes
❌ Using ECB Mode
// NEVER DO THIS - ECB reveals patterns
function insecureEncrypt(key: Uint8Array, data: Uint8Array): Uint8Array {
return ARIA256.encryptECB(key, data);
}
// Identical blocks produce identical ciphertext!
❌ Static or Predictable IVs
// WRONG - Predictable IV
class BadARIA {
private counter = 0;
encrypt(key: Uint8Array, data: Uint8Array): Uint8Array {
const iv = new Uint8Array(16);
new DataView(iv.buffer).setUint32(0, this.counter++);
// Counter in first 4 bytes, rest zeros - PREDICTABLE!
return ARIA256.encryptCBC(key, iv, data);
}
}
// CORRECT - Random IV
function goodEncrypt(key: Uint8Array, data: Uint8Array): {
iv: Uint8Array;
ciphertext: Uint8Array;
} {
const iv = randomBytes(16);
return {
iv,
ciphertext: ARIA256.encryptCBC(key, iv, data)
};
}
❌ Reusing Nonces in GCM
// CATASTROPHIC - Nonce reuse in GCM breaks security
class BrokenGCM {
private nonce = randomBytes(12); // REUSED!
encrypt(key: Uint8Array, data: Uint8Array): Uint8Array {
// This completely breaks GCM security
return ARIA256.encryptGCM(key, this.nonce, data).ciphertext;
}
}
❌ Ignoring Authentication Tags
// WRONG - Not verifying authentication
function insecureDecrypt(
key: Uint8Array,
data: EncryptedData
): Uint8Array {
// Just decrypt without checking tag!
const plaintext = ARIA256.decryptCTR(key, data.iv, data.ciphertext);
// Attacker can modify ciphertext!
return plaintext;
}
// CORRECT - Always verify authentication
function secureDecrypt(
key: Uint8Array,
data: EncryptedData
): Uint8Array | null {
return ARIA256.decryptGCM(
key,
data.nonce,
data.ciphertext,
data.tag
);
}
Performance vs Security
Mode Performance Comparison
| Mode | Speed | Security | Use Case |
|---|---|---|---|
| ECB | Fastest | ❌ Insecure | Never |
| CBC | Fast | ⚠️ Padding oracle | Legacy only |
| CTR | Fast, parallel | ✅ With HMAC | Streaming |
| GCM | Moderate | ✅ Authenticated | Recommended |
| CCM | Slower | ✅ Authenticated | IoT devices |
Optimization Guidelines
// Parallel CTR mode encryption
class ParallelARIA {
static async encryptLarge(
key: Uint8Array,
plaintext: Uint8Array,
workers: number = 4
): Promise<Uint8Array> {
const iv = randomBytes(16);
const chunkSize = Math.ceil(plaintext.length / workers);
const promises = [];
for (let i = 0; i < workers; i++) {
const start = i * chunkSize;
const end = Math.min(start + chunkSize, plaintext.length);
const chunk = plaintext.slice(start, end);
// Adjust counter for each worker
const workerIV = new Uint8Array(iv);
const counter = new DataView(workerIV.buffer);
counter.setBigUint64(8, BigInt(start / 16));
promises.push(
ARIA256.encryptCTR(key, workerIV, chunk)
);
}
const chunks = await Promise.all(promises);
return concatenate(chunks);
}
}
Platform-Specific Notes
JavaScript/TypeScript
- No native ARIA support in WebCrypto
- Pure JS implementations slower than native
- Consider WASM for performance
- Use
crypto.getRandomValues()for IVs
Python
cryptographylibrary has ARIA support- PyCryptodome includes ARIA
- Hardware acceleration unlikely
Java/Kotlin
- Bouncy Castle provides ARIA
- Android 9+ includes ARIA support
- Use
SecureRandomfor IVs
C/C++
- Reference implementation available
- Optimize S-box lookups
- Use AES-NI style optimizations where possible
Compliance Information
Standards Compliance
- KS X 1213:2004: Korean national standard
- RFC 5794: IETF specification
- ISO/IEC 18033-3: International standard
- NESSIE: Not selected (competed against AES)
Regulatory Status
- Korea: Government approved and recommended
- International: Recognized but not widely mandated
- Patents: Original patents expired (free to use)
Security Evaluation
- Designed with AES competition criteria
- Extensive Korean government evaluation
- Academic cryptanalysis published
- No practical attacks known
Use Cases
✅ Recommended for:
- Korean market requirements
- Diversity from AES
- Patent-free requirements
- Academic/research purposes
⚠️ Consider carefully for:
- International standards compliance
- Maximum performance requirements
- Extensive third-party support needs
❌ Not recommended for:
- FIPS compliance requirements
- Maximum ecosystem support
Security Notice: ARIA is a secure cipher with government backing. However, AES has broader support and more analysis. Choose based on your requirements. Report issues to security@metamui.id
Last Updated: 2025-07-06
**Version: 3.0.0
License: BSL-1.1
Security Analysis
Threat Model: ARIA-256 Threat Model
The comprehensive threat analysis covers:
- Algorithm-specific attack vectors
- Implementation vulnerabilities
- Side-channel considerations
- Quantum resistance analysis (where applicable)
- Deployment recommendations
For complete security analysis and risk assessment, see the dedicated threat model documentation.