@gibme/eapol
v22.0.0
Published
A comprehensive, low-level EAPOL (Extensible Authentication Protocol over LAN) Key Frame parser for Wi-Fi security protocols. Parses and validates EAPOL-Key frames used in WPA/WPA2/WPA3 4-way handshakes, group key handshakes, and Fast Transition (802.11r)
Downloads
23
Maintainers
Readme
@gibme/eapol
A comprehensive, low-level EAPOL (Extensible Authentication Protocol over LAN) Key Frame parser for Wi-Fi security protocols.
Parses and validates EAPOL-Key frames used in WPA/WPA2/WPA3 4-way handshakes, group key handshakes, and Fast Transition (802.11r) operations. Supports RSN/WPA IE parsing, all KDE types (GTK, IGTK, PMKID, etc.), and all standard cipher suites and AKM methods.
Parser-only implementation - does not perform cryptographic operations.
Requirements
- Node.js >= 22
Installation
npm install @gibme/eapolor
yarn add @gibme/eapolQuick Start
import { Frame, EAPOL } from '@gibme/eapol';
// Parse from hex string
const frame = Frame.from('0203005f02...', 'hex');
// Parse from buffer
const frame = Frame.from(buffer);
// Identify the handshake message
console.log(`Message ${frame.messageNumber} of ${frame.handshakeType} handshake`);
// Validate the frame
const result = frame.validate();
if (!result.valid) {
console.error('Validation errors:', result.errors);
}Features
Frame Parsing
- Parse complete EAPOL-Key frames from buffers or hex strings
- Automatic frame detection — scans up to 512 bytes past 802.11/LLC headers to locate the EAPOL header
- Supports EAPOL versions 1, 2, and 3 (802.1X-2001/2004/2010)
- Extracts all key descriptor fields (nonces, MIC, replay counter, IVs, RSC, etc.)
- Parses Key Information flags with full bit-field decoding
Security Protocol Support
| Protocol | Standard | Description | |---|---|---| | WPA/TKIP | IEEE 802.11i | Legacy WPA with Microsoft OUI (00:50:F2:01) | | WPA2/WPA3 | IEEE 802.11i/ac/ax | RSN Information Element (IE 0x30) parsing | | Fast Transition | IEEE 802.11r | Full FT-IE and Mobility Domain parsing | | PMF | IEEE 802.11w | Management Frame Protection with IGTK support | | FILS | IEEE 802.11ai | Fast Initial Link Setup support |
Key Data Encapsulation (KDE) Parsing
All standard KDE types are recognized and parsed:
- GTK - Group Temporal Key (key ID, Tx flag, key material)
- IGTK - Integrity Group Temporal Key with IPN (802.11w PMF)
- PMKID - Pairwise Master Key Identifier (16 bytes)
- MAC Address - TDLS peer identification
- SMK - Station-to-Station Master Key (TDLS)
- Nonce - Additional 32-byte nonce
- Lifetime - Key lifetime in seconds
- Error - Handshake error codes
- Key ID - Generic key identifier
- Multiband GTK / Key ID - Multi-band operation support
Cipher Suites
Complete constants for all IEEE 802.11 cipher suites:
| Constant | Value | Usage |
|---|---|---|
| CCMP_128 | 0x04 | WPA2/WPA3 standard |
| GCMP_128 | 0x08 | WPA3 |
| GCMP_256 | 0x09 | WPA3 192-bit |
| CCMP_256 | 0x0a | WPA3 192-bit |
| TKIP | 0x02 | Legacy WPA |
| WEP40 / WEP_104 | 0x01 / 0x05 | Legacy (deprecated) |
| BIP_CMAC_128 | 0x06 | PMF |
| BIP_GMAC_128 / BIP_GMAC_256 | 0x0b / 0x0c | PMF |
| BIP_CMAC_256 | 0x0d | PMF |
Available via EAPOL.PairwiseCipherSuite, EAPOL.GroupCipherSuite, and EAPOL.ManagementFrameProtectionSuite.
AKM Suites
All standard Authentication and Key Management methods:
| Constant | Value | Usage |
|---|---|---|
| PSK | 0x02 | WPA2-Personal |
| EAP | 0x01 | WPA2-Enterprise |
| SAE | 0x08 | WPA3-Personal |
| OWE | 0x12 | Opportunistic Wireless Encryption |
| FT_PSK / FT_SAE | 0x04 / 0x09 | Fast Transition variants |
| EAP_SUITE_B_192 | 0x0c | WPA3-Enterprise 192-bit |
| FILS_SHA256 / FILS_SHA384 | 0x0e / 0x0f | Fast Initial Link Setup |
| SAE_EXT_KEY / FT_SAE_EXT_KEY | 0x18 / 0x19 | SAE with Extended Key |
| PASN | 0x13 | Pre-Association Security Negotiation |
Available via EAPOL.AkmSuite.
Frame Validation
Comprehensive validation including:
- EAPOL version and descriptor type compatibility
- Key Information flag consistency per IEEE 802.11 spec
- Message-specific requirements (Messages 1-4 of the 4-way handshake)
- Replay counter validation
- RSN/WPA IE structure integrity (version, cipher counts, AKM counts)
- KDE structure validation (IGTK IPN length, MAC address length, PMKID length, nonce length)
- Nonce and MIC presence requirements
- Pairwise key length checks
- Encrypted key data flag consistency
Handshake Message Detection
Automatic identification of 4-way handshake messages based on flag combinations:
| Message | Direction | Key Flags |
|---|---|---|
| Message 1 | AP -> STA | hasAck, no hasMic, no hasInstall |
| Message 2 | STA -> AP | hasMic, no hasAck, no isSecure |
| Message 3 | AP -> STA | hasAck, hasInstall, hasMic |
| Message 4 | STA -> AP | hasMic, isSecure, no hasAck |
Also detects group key handshake messages.
Usage Examples
Identify Handshake Messages
import { Frame } from '@gibme/eapol';
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('Version:', frame.rsn.version);
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);
console.log('PMKIDs:', frame.rsn.pmkIds.length);
}
// 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'));
}Compare Cipher Suites
import { Frame, EAPOL } from '@gibme/eapol';
const frame = Frame.from(buffer);
if (frame.rsn) {
const supportsCCMP = frame.rsn.pairwiseCipherSuites.some(
suite => suite.equals(EAPOL.PairwiseCipherSuite.CCMP_128)
);
const supportsSAE = frame.rsn.akmSuites.some(
suite => suite.equals(EAPOL.AkmSuite.SAE)
);
console.log('Supports CCMP-128:', supportsCCMP);
console.log('Supports WPA3-SAE:', supportsSAE);
}Validate a 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');
console.log('Key Descriptor Version valid:', frame.isValidKeyDescriptorVersion());
}MIC Verification Support
const frame = Frame.from(buffer);
// Get the frame with MIC field zeroed for external MIC calculation
const zeroedFrame = frame.zeroedFrame;
// The MIC algorithm depends on the Key Descriptor Version
switch (frame.keyVersion) {
case EAPOL.KeyVersion.HMAC_MD5_RC4:
// HMAC-MD5 (WPA/TKIP)
break;
case EAPOL.KeyVersion.HMAC_SHA1_AES:
// HMAC-SHA1-128 (WPA2/CCMP)
break;
case EAPOL.KeyVersion.AES_128_CMAC:
// AES-128-CMAC (WPA3, PMF, FT)
break;
}API Reference
Frame.from(blob, encoding?)
Parses an EAPOL Key Frame from a buffer or string.
blob-Bufferorstringcontaining the EAPOL frameencoding- OptionalBufferEncoding(default:'hex')- Returns:
Frame - Throws:
Errorif the blob does not contain a valid EAPOL Key Frame
Frame Properties
| Property | Type | Description |
|---|---|---|
| version | EAPOL.Version | EAPOL protocol version (0x01-0x03) |
| type | EAPOL.Type | Packet type (0x03 for EAPOL-Key) |
| descriptor | EAPOL.Descriptor | Key descriptor type (RC4, RSN, FT, PMF, FILS, EHT) |
| keyVersion | EAPOL.KeyVersion | Crypto algorithm for MIC and key wrapping |
| replayCounter | bigint | 8-byte replay counter |
| keyLength | number | Pairwise key length in bytes |
| keyNonce | Buffer | 32-byte ANonce or SNonce |
| keyIv | Buffer | 16-byte initialization vector |
| keyRsc | Buffer | 8-byte receive sequence counter |
| keyId | Buffer | 8-byte key identifier (reserved) |
| mic | Buffer | Message Integrity Code |
| zeroedFrame | Buffer | Frame copy with MIC zeroed for verification |
Key Information Flags
| Property | Type | Description |
|---|---|---|
| keyInfo | EAPOL.KeyInfo | Complete key info structure |
| isPairwise | boolean | Pairwise key (PTK) vs group key (GTK) |
| hasInstall | boolean | Key should be installed |
| hasAck | boolean | From authenticator (AP) |
| hasMic | boolean | MIC field is valid |
| isSecure | boolean | Secure association established |
| hasError | boolean | Error flag |
| isRequest | boolean | Supplicant requests new key |
| isEncrypted | boolean | Key data is encrypted |
| isSmk | boolean | TDLS SMK message |
Handshake Detection
| Property | Type | Description |
|---|---|---|
| isMessage1 | boolean | Message 1 of 4-way handshake |
| isMessage2 | boolean | Message 2 of 4-way handshake |
| isMessage3 | boolean | Message 3 of 4-way handshake |
| isMessage4 | boolean | Message 4 of 4-way handshake |
| messageNumber | 1 \| 2 \| 3 \| 4 \| undefined | Detected message number |
| handshakeType | string | 'four-way', 'group-key', or 'unknown' |
Parsed Information Elements
| Property | Type | Description |
|---|---|---|
| rsn | EAPOL.Rsn \| undefined | RSN IE (WPA2/WPA3) |
| wpa | EAPOL.Wpa \| undefined | Legacy WPA IE |
| ft | Partial<EAPOL.Ft> \| undefined | Fast Transition IE (802.11r) |
| mobilityDomain | EAPOL.MobilityDomain \| undefined | Mobility Domain IE |
| ies | EAPOL.Ie[] | All parsed information elements |
Parsed KDEs
| Property | Type | Description |
|---|---|---|
| gtk | EAPOL.GtkKde \| undefined | Group Temporal Key |
| igtk | EAPOL.IgtkKde \| undefined | Integrity Group Temporal Key (PMF) |
| pmkid | EAPOL.PmkidKde \| undefined | Pairwise Master Key Identifier |
| macAddr | EAPOL.MacAddrKde \| undefined | MAC Address (TDLS) |
| smk | EAPOL.SmkKde \| undefined | Station-to-Station Master Key |
| nonce | EAPOL.NonceKde \| undefined | Additional nonce |
| lifetime | EAPOL.LifetimeKde \| undefined | Key lifetime |
| error | EAPOL.ErrorKde \| undefined | Error information |
| keyIdKde | EAPOL.KeyIdKde \| undefined | Generic key identifier |
| multibandGtk | EAPOL.MultibandGtkKde \| undefined | Multiband GTK |
| multibandKeyId | EAPOL.MultibandKeyIdKde \| undefined | Multiband key identifier |
| kdes | EAPOL.Kde[] | All parsed KDEs |
| encryptedKeyData | Buffer | Raw encrypted key data (if encrypted) |
Frame Methods
validate()
Validates the frame structure and content against IEEE 802.11 requirements.
Returns: { valid: boolean; errors: string[] }
isValidKeyDescriptorVersion()
Checks if the Key Descriptor Version is valid for the Descriptor Type.
Returns: boolean
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
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
License
MIT
Contributing
Issues and pull requests welcome at github.com/gibme-npm/eapol
Author
Brandon Lehmann [email protected]
