@@ -4958,20 +4958,16 @@ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](
49584958---
49594959## Functions
49604960
4961- | |
4962- | --- |
4963- | [AES](#function-aes) |
4964- | [AESGCM](#function-aesgcm) |
4965- | [AESGCMDecrypt](#function-aesgcmdecrypt) |
4966- | [assertValidHex](#function-assertvalidhex) |
4967- | [base64ToArray](#function-base64toarray) |
4968- | [ghash](#function-ghash) |
4969- | [normalizeHex](#function-normalizehex) |
4970- | [pbkdf2](#function-pbkdf2) |
4971- | [red](#function-red) |
4972- | [toArray](#function-toarray) |
4973- | [toBase64](#function-tobase64) |
4974- | [verifyNotNull](#function-verifynotnull) |
4961+ | | |
4962+ | --- | --- |
4963+ | [AES](#function-aes) | [pbkdf2](#function-pbkdf2) |
4964+ | [AESGCM](#function-aesgcm) | [realHtonl](#function-realhtonl) |
4965+ | [AESGCMDecrypt](#function-aesgcmdecrypt) | [red](#function-red) |
4966+ | [assertValidHex](#function-assertvalidhex) | [swapBytes32](#function-swapbytes32) |
4967+ | [base64ToArray](#function-base64toarray) | [toArray](#function-toarray) |
4968+ | [ghash](#function-ghash) | [toBase64](#function-tobase64) |
4969+ | [htonl](#function-htonl) | [verifyNotNull](#function-verifynotnull) |
4970+ | [normalizeHex](#function-normalizehex) | |
49754971
49764972Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
49774973
@@ -4988,6 +4984,47 @@ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](
49884984---
49894985### Function: AESGCM
49904986
4987+ SECURITY NOTE – NON-STANDARD AES-GCM PADDING
4988+
4989+ This implementation intentionally deviates from NIST SP 800-38D’s AES-GCM
4990+ specification in how the GHASH input is formed when the additional
4991+ authenticated data (AAD ) or ciphertext length is zero.
4992+
4993+ In the standard, AAD and ciphertext are each padded with the minimum number
4994+ of zero bytes required to reach a multiple of 16 bytes; when the length is
4995+ already a multiple of 16 (including the case length = 0 ), no padding block
4996+ is added . In this implementation , when AAD .length === 0 or ciphertext .length
4997+ === 0 , an extra 16 - byte block of zeros is appended before the length fields
4998+ are processed . The same formatting logic is used symmetrically in both
4999+ AESGCM (encryption ) and AESGCMDecrypt (decryption ).
5000+
5001+ As a result :
5002+ - Authentication tags produced here are NOT compatible with tags produced
5003+ by standards - compliant AES - GCM implementations in the cases where AAD
5004+ or ciphertext are empty .
5005+ - Ciphertexts generated by this code must be decrypted by this exact
5006+ implementation (or one that reproduces the same GHASH formatting ), and
5007+ must not be mixed with ciphertexts produced by a strictly standard
5008+ AES - GCM library .
5009+
5010+ Cryptographic impact : this change alters only the encoding of the message
5011+ that is input to GHASH ; it does not change the block cipher , key derivation ,
5012+ IV handling , or the basic “encrypt - then - MAC over (AAD , ciphertext , lengths )”
5013+ structure of AES - GCM . Under the usual assumptions that AES is a secure block
5014+ cipher and GHASH with a secret subkey is a secure polynomial MAC , this
5015+ variant continues to provide confidentiality and integrity for data encrypted
5016+ and decrypted consistently with this implementation . We are not aware of any
5017+ attack that exploits the presence of this extra zero block when AAD or
5018+ ciphertext are empty .
5019+
5020+ However , this padding behavior is non - compliant with NIST SP 800 - 38D and has
5021+ not been analyzed as extensively as standard AES - GCM . Code that requires
5022+ strict standards compliance or interoperability with external AES - GCM
5023+ implementations SHOULD NOT use this module as - is . Any future migration to a
5024+ fully compliant AES - GCM encoding will require a compatibility strategy , as
5025+ existing ciphertexts produced by this implementation will otherwise become
5026+ undecryptable .
5027+
49915028` ` ` ts
49925029export function AESGCM(plainText: number[], additionalAuthenticatedData: number[], initializationVector: number[], key: number[]): {
49935030 result: number[];
@@ -5033,6 +5070,15 @@ export function ghash(input: number[], hashSubKey: number[]): number[]
50335070
50345071Links : [API ](#api ), [Interfaces ](#interfaces ), [Classes ](#classes ), [Functions ](#functions ), [Types ](#types ), [Enums ](#enums ), [Variables ](#variables )
50355072
5073+ -- -
5074+ ### Function : htonl
5075+
5076+ ` ` ` ts
5077+ export function htonl(w: number): number
5078+ ` ` `
5079+
5080+ Links : [API ](#api ), [Interfaces ](#interfaces ), [Classes ](#classes ), [Functions ](#functions ), [Types ](#types ), [Enums ](#enums ), [Variables ](#variables )
5081+
50365082-- -
50375083### Function : normalizeHex
50385084
@@ -5070,6 +5116,42 @@ Argument Details
50705116
50715117Links: [API](#api ), [Interfaces](#interfaces ), [Classes](#classes ), [Functions](#functions ), [Types](#types ), [Enums](#enums ), [Variables](#variables )
50725118
5119+ ---
5120+ ### Function: realHtonl
5121+
5122+ Converts a 32-bit unsigned integer from host byte order to network byte order.
5123+
5124+ Unlike the legacy `htonl()` implementation (which always swapped bytes ),
5125+ this function behaves like the traditional C `htonl()`:
5126+
5127+ - On ** little-endian** machines → performs a byte swap.
5128+ - On ** big-endian** machines → returns the value unchanged.
5129+
5130+ This function is provided to resolve TOB-20, which identified that the
5131+ previous `htonl()` implementation had a misleading name and did not match
5132+ platform-dependent semantics.
5133+
5134+ Example
5135+
5136+ ```ts
5137+ realHtonl(0x11223344) // → 0x44332211 on little-endian systems
5138+ ```
5139+
5140+ ```ts
5141+ export function realHtonl(w : number ): number
5142+ ```
5143+
5144+ Returns
5145+
5146+ The value converted to network byte order.
5147+
5148+ Argument Details
5149+
5150+ + ** w**
5151+ + A 32-bit unsigned integer.
5152+
5153+ Links: [API](#api ), [Interfaces](#interfaces ), [Classes](#classes ), [Functions](#functions ), [Types](#types ), [Enums](#enums ), [Variables](#variables )
5154+
50735155---
50745156### Function: red
50755157
@@ -5079,6 +5161,41 @@ export function red(x: bigint): bigint
50795161
50805162Links: [API](#api ), [Interfaces](#interfaces ), [Classes](#classes ), [Functions](#functions ), [Types](#types ), [Enums](#enums ), [Variables](#variables )
50815163
5164+ ---
5165+ ### Function: swapBytes32
5166+
5167+ Unconditionally swaps the byte order of a 32-bit unsigned integer.
5168+
5169+ This function performs a strict 32-bit byte swap regardless of host
5170+ endianness. It is equivalent to the behavior commonly referred to as
5171+ `bswap32` in low-level libraries.
5172+
5173+ This function is introduced as part of TOB-20 to provide a clearly-named
5174+ alternative to `htonl()`, which was previously implemented as an
5175+ unconditional byte swap and did not match the semantics of the traditional
5176+ C `htonl()` function.
5177+
5178+ Example
5179+
5180+ ```ts
5181+ swapBytes32(0x11223344) // → 0x44332211
5182+ ```
5183+
5184+ ```ts
5185+ export function swapBytes32(w : number ): number
5186+ ```
5187+
5188+ Returns
5189+
5190+ The value with its byte order reversed.
5191+
5192+ Argument Details
5193+
5194+ + ** w**
5195+ + A 32-bit unsigned integer.
5196+
5197+ Links: [API](#api ), [Interfaces](#interfaces ), [Classes](#classes ), [Functions](#functions ), [Types](#types ), [Enums](#enums ), [Variables](#variables )
5198+
50825199---
50835200### Function: toArray
50845201
0 commit comments