Skip to content

v20.0.0

Choose a tag to compare

@brandonlehmann brandonlehmann released this 01 Feb 02:01
· 1 commit to master since this release
dd9a0cc

@gibme/eapol is a comprehensive, low-level EAPOL (Extensible Authentication Protocol over LAN) Key Frame parser for Wi-Fi security protocols.

It parses and validates EAPOL-Key frames used in WPA/WPA2/WPA3 4-way handshakes, group key handshakes, and Fast Transition (802.11r) operations.


Features

Frame Parsing

  • Parse complete EAPOL-Key frames from buffers or hex strings
  • Automatic frame detection (scans up to 512 bytes for EAPOL header)
  • Supports EAPOL versions 1, 2, and 3 (802.1X-2001/2004/2010)
  • Extracts all key descriptor fields (nonces, MIC, replay counter, etc.)
  • Parses Key Information flags with full bit-field decoding

Security Protocol Support

  • WPA/TKIP: Legacy WPA with Microsoft OUI (00:50:F2:01)
  • WPA2/WPA3: RSN Information Element (IE 0x30) parsing
  • 802.11r (Fast Transition): Full FT-IE and Mobility Domain parsing
  • 802.11w (PMF): Management Frame Protection with IGTK support
  • 802.11ai (FILS): Fast Initial Link Setup support

Key Data Encapsulation (KDE) Parsing

  • GTK: Group Temporal Key for multicast/broadcast traffic
  • IGTK: Integrity Group Temporal Key for management frame protection
  • PMKID: Pairwise Master Key Identifier for fast roaming
  • MAC Address: TDLS peer identification
  • SMK: Station-to-Station Master Key (TDLS)
  • Nonce, Lifetime, Error: Additional key metadata
  • Multiband: Multi-band operation support

Cipher Suite & AKM Support

Complete constants for all standard cipher suites and AKM (Authentication and Key Management) methods:

Cipher Suites:

  • WEP-40/104 (legacy)
  • TKIP (WPA)
  • CCMP-128/256 (WPA2/WPA3)
  • GCMP-128/256 (WPA3, 802.11ac/ax)
  • BIP-CMAC/GMAC-128/256 (PMF)

AKM Suites:

  • PSK, EAP (WPA2-Personal/Enterprise)
  • SAE (WPA3-Personal)
  • FT (802.11r Fast Transition variants)
  • FILS (802.11ai Fast Initial Link Setup)
  • OWE (Opportunistic Wireless Encryption)
  • Suite-B-192 (WPA3-Enterprise 192-bit)

Frame Validation

Comprehensive validation including:

  • EAPOL version and descriptor compatibility
  • Key Information flag consistency (per 802.11 spec)
  • Message-specific requirements (Messages 1-4 of 4-way handshake)
  • Replay counter validation
  • IE/KDE structure validation
  • Nonce and MIC presence requirements

Frame Type Detection

  • Automatic 4-way handshake message detection (Messages 1-4)
  • Group key handshake identification
  • Handshake type classification (four-way, group-key, unknown)

Installation

npm install @gibme/eapol

Usage

Parse an EAPOL Frame

import { Frame } from '@gibme/eapol';

// From hex string
const frame = Frame.from('0203005f02...', 'hex');

// From buffer
const frame = Frame.from(buffer);

// Access parsed data
console.log(`Message ${frame.messageNumber} of 4-way handshake`);
console.log(`Replay Counter: ${frame.replayCounter}`);
console.log(`ANonce: ${frame.keyNonce.toString('hex')}`);
console.log(`Has MIC: ${frame.hasMic}`);
console.log(`MIC: ${frame.mic.toString('hex')}`);

Identify Handshake Messages

const frame = Frame.from(buffer);

if (frame.isMessage1) {
  console.log('Message 1: AP → STA (ANonce)');
  console.log('ANonce:', frame.keyNonce.toString('hex'));
}

if (frame.isMessage2) {
  console.log('Message 2: STA → AP (SNonce, RSN IE)');
  console.log('SNonce:', frame.keyNonce.toString('hex'));
  console.log('RSN:', frame.rsn);
}

if (frame.isMessage3) {
  console.log('Message 3: AP → STA (ANonce, GTK, Install)');
  console.log('GTK Key ID:', frame.gtk?.keyId);
  console.log('GTK:', frame.gtk?.gtk.toString('hex'));
}

if (frame.isMessage4) {
  console.log('Message 4: STA → AP (Confirmation)');
}

Extract Security Information

const frame = Frame.from(buffer);

// RSN Information Element (WPA2/WPA3)
if (frame.rsn) {
  console.log('Group Cipher:', frame.rsn.groupCipher.toString('hex'));
  console.log('Pairwise Ciphers:', frame.rsn.pairwiseCipherSuites.length);
  console.log('AKM Suites:', frame.rsn.akmSuites.length);
  console.log('MFP Required:', frame.rsn.capabilities.mfpRequired);
  console.log('MFP Capable:', frame.rsn.capabilities.mfpCapable);
}

// Legacy WPA Information Element
if (frame.wpa) {
  console.log('WPA Version:', frame.wpa.version);
  console.log('Group Cipher:', frame.wpa.groupCipher.toString('hex'));
}

// Fast Transition (802.11r)
if (frame.ft) {
  console.log('Mobility Domain ID:', frame.mdid.toString('hex'));
  console.log('R0KH-ID:', frame.ft.r0KHId?.toString('hex'));
  console.log('R1KH-ID:', frame.ft.r1KHId?.toString('hex'));
}

Extract Keys

const frame = Frame.from(buffer);

// Group Temporal Key
if (frame.gtk) {
  console.log('GTK Key ID:', frame.gtk.keyId);
  console.log('GTK Tx Flag:', frame.gtk.txFlag);
  console.log('GTK:', frame.gtk.gtk.toString('hex'));
}

// Integrity Group Temporal Key (PMF)
if (frame.igtk) {
  console.log('IGTK Key ID:', frame.igtk.keyId);
  console.log('IGTK IPN:', frame.igtk.ipn.toString('hex'));
  console.log('IGTK:', frame.igtk.igtk.toString('hex'));
}

// PMKID (for fast roaming)
if (frame.pmkid) {
  console.log('PMKID:', frame.pmkid.pmkid.toString('hex'));
}

Validate Frame

const frame = Frame.from(buffer);
const validation = frame.validate();

if (!validation.valid) {
  console.error('Frame validation failed:');
  validation.errors.forEach(err => console.error(`  - ${err}`));
} else {
  console.log('Frame is valid!');
}

Compare Cipher Suites

import { EAPOL } from '@gibme/eapol';

const frame = Frame.from(buffer);

if (frame.rsn) {
  // Check if CCMP-128 is supported
  const supportsCCMP = frame.rsn.pairwiseCipherSuites.some(
    suite => suite.equals(EAPOL.PairwiseCipherSuite.CCMP_128)
  );

  // Check if SAE (WPA3) is supported
  const supportsSAE = frame.rsn.akmSuites.some(
    suite => suite.equals(EAPOL.AkmSuite.SAE)
  );

  console.log('Supports CCMP-128:', supportsCCMP);
  console.log('Supports WPA3-SAE:', supportsSAE);
}

API Reference

Frame.from(blob, encoding?)

Parses an EAPOL Key Frame from a buffer or string.

Parameters:

  • blob - Buffer or hex string containing the EAPOL frame
  • encoding - Optional encoding (default: 'hex')

Returns: Frame object

Throws: Error if blob does not contain a valid EAPOL Key Frame

Frame Properties

Header Fields

  • version - EAPOL protocol version (0x01, 0x02, 0x03)
  • type - EAPOL packet type (typically 0x03 for EAPOL-Key)
  • descriptor - Key Descriptor Type (RC4, RSN, FT, PMF, FILS, EHT)
  • keyVersion - Key Descriptor Version (indicates MIC/encryption algorithm)
  • replayCounter - 8-byte replay counter (bigint)

Key Fields

  • keyLength - Key length in bytes
  • keyNonce - 32-byte nonce (ANonce or SNonce)
  • keyRsc - 8-byte Receive Sequence Counter
  • keyIv - 16-byte Initialization Vector
  • keyId - 8-byte key identifier (reserved)
  • mic - 16-byte Message Integrity Code
  • zeroedFrame - Frame copy with MIC zeroed (for verification)

Key Information Flags

  • keyInfo - Complete KeyInfo object
  • isPairwise - Pairwise key (PTK) vs group key (GTK)
  • hasInstall - Install flag set
  • hasAck - ACK flag set (from authenticator)
  • hasMic - MIC flag set
  • isSecure - Secure flag set
  • hasError - Error flag set
  • isRequest - Request flag set
  • isEncrypted - Key Data encrypted
  • isSmk - TDLS SMK message

Handshake Detection

  • isMessage1 - Message 1 of 4-way handshake
  • isMessage2 - Message 2 of 4-way handshake
  • isMessage3 - Message 3 of 4-way handshake
  • isMessage4 - Message 4 of 4-way handshake
  • messageNumber - Returns 1, 2, 3, 4, or undefined
  • handshakeType - 'four-way', 'group-key', or 'unknown'

Parsed Information Elements

  • rsn - RSN Information Element (WPA2/WPA3)
  • wpa - WPA Information Element (legacy)
  • ft - Fast Transition Information Element
  • mobilityDomain - Mobility Domain IE
  • ies - Array of all Information Elements

Parsed KDEs

  • gtk - Group Temporal Key
  • igtk - Integrity Group Temporal Key (PMF)
  • pmkid - Pairwise Master Key Identifier
  • macAddr - MAC Address (TDLS)
  • smk - Station-to-Station Master Key
  • nonce - Additional nonce
  • lifetime - Key lifetime
  • error - Error information
  • keyIdKde - Generic key identifier
  • multibandGtk - Multiband GTK
  • multibandKeyId - Multiband key identifier
  • kdes - Array of all KDEs

Other

  • encryptedKeyData - Encrypted key data (if encrypted)

Frame Methods

validate()

Validates the frame structure and content.

Returns: { valid: boolean, errors: string[] }

isValidKeyDescriptorVersion()

Checks if the Key Descriptor Version is valid for the Descriptor Type.

Returns: boolean


Supported Standards

  • IEEE 802.11i - RSN (WPA2)
  • IEEE 802.11r - Fast Transition (FT)
  • IEEE 802.11w - Protected Management Frames (PMF)
  • IEEE 802.11ai - Fast Initial Link Setup (FILS)
  • IEEE 802.11ac/ax - WPA3, GCMP ciphers
  • Wi-Fi Alliance - WPA, WPA2, WPA3

Non-Goals

This library does not:

  • Capture packets from network interfaces
  • Implement cryptographic operations (PMK/PTK derivation, MIC calculation)
  • Perform active attacks or password cracking
  • Implement EAP authentication protocols
  • Act as a RADIUS server or supplicant

It is purely a parser and validator for already-captured EAPOL frames.


Use Cases

  • Wireless security analysis - Parse captured handshakes
  • DPSK implementations - Validate handshake frames
  • Network monitoring - Extract handshake parameters
  • Research & education - Understand WPA/WPA2/WPA3 protocols
  • Testing & validation - Verify frame structure and compliance
  • Forensics - Analyze captured Wi-Fi traffic

TypeScript Support

Full TypeScript definitions included. All types, enums, and constants are exported.

import { Frame, EAPOL } from '@gibme/eapol';

// Full type safety
const frame: Frame = Frame.from(buffer);
const version: EAPOL.Version = frame.version;
const rsn: EAPOL.Rsn | undefined = frame.rsn;

Performance

  • Optimized for correctness and clarity
  • Pure TypeScript with minimal dependencies
  • Suitable for real-time packet analysis
  • Can parse thousands of frames per second on modern hardware

Security Considerations

  • Input data is parsed defensively with bounds checking
  • Validates frame structure before parsing
  • Detects truncated or malformed frames
  • Does not execute any cryptographic operations
  • Designed for analysis of captured traffic, not active network operations

License

MIT


Contributing

Issues and pull requests welcome at github.com/gibme-npm/eapol


Author

Brandon Lehmann brandonlehmann@gmail.com