Skip to content

Commit 4824154

Browse files
bwp91claude
andcommitted
fix: O(n²) buffer concat in encrypt/decrypt hot path
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 3bea72f commit 4824154

2 files changed

Lines changed: 7 additions & 6 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ All notable changes to `@homebridge/hap-nodejs` will be documented in this file.
2222
- fix: missing error argument in pairing debug logs
2323
- fix: use constant-time comparison for pincode checks
2424
- fix: `"undefined"` string in characteristic error warnings
25+
- fix: O(n²) buffer concat in encrypt/decrypt hot path
2526

2627
## v2.1.2 (2026-03-29)
2728

src/lib/util/hapCrypto.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export function chacha20_poly1305_encryptAndSeal(key: Buffer, nonce: Buffer, aad
118118
* @group Cryptography
119119
*/
120120
export function layerEncrypt(data: Buffer, encryption: HAPEncryption): Buffer {
121-
let result = Buffer.alloc(0);
121+
const chunks: Buffer[] = [];
122122
const total = data.length;
123123
for (let offset = 0; offset < total; ) {
124124
const length = Math.min(total - offset, 0x400);
@@ -131,9 +131,9 @@ export function layerEncrypt(data: Buffer, encryption: HAPEncryption): Buffer {
131131
const encrypted = chacha20_poly1305_encryptAndSeal(encryption.accessoryToControllerKey, nonce, leLength, data.subarray(offset, offset + length));
132132
offset += length;
133133

134-
result = Buffer.concat([result,leLength,encrypted.ciphertext,encrypted.authTag]);
134+
chunks.push(leLength, encrypted.ciphertext, encrypted.authTag);
135135
}
136-
return result;
136+
return Buffer.concat(chunks);
137137
}
138138

139139
/**
@@ -145,7 +145,7 @@ export function layerDecrypt(packet: Buffer, encryption: HAPEncryption): Buffer
145145
encryption.incompleteFrame = undefined;
146146
}
147147

148-
let result = Buffer.alloc(0);
148+
const chunks: Buffer[] = [];
149149
const total = packet.length;
150150

151151
for (let offset = 0; offset < total;) {
@@ -167,9 +167,9 @@ export function layerDecrypt(packet: Buffer, encryption: HAPEncryption): Buffer
167167
packet.subarray(offset + 2, offset + 2 + realDataLength),
168168
packet.subarray(offset + 2 + realDataLength, offset + 2 + realDataLength + 16),
169169
);
170-
result = Buffer.concat([result, plaintext]);
170+
chunks.push(plaintext);
171171
offset += (18 + realDataLength);
172172
}
173173

174-
return result;
174+
return Buffer.concat(chunks);
175175
}

0 commit comments

Comments
 (0)