werift 0.22.8 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/common/src/crc.d.ts +4 -0
- package/lib/common/src/crc.js +124 -0
- package/lib/common/src/crc.js.map +1 -0
- package/lib/common/src/index.d.ts +1 -0
- package/lib/common/src/index.js +1 -0
- package/lib/common/src/index.js.map +1 -1
- package/lib/dtls/src/flight/server/flight6.js +12 -2
- package/lib/dtls/src/flight/server/flight6.js.map +1 -1
- package/lib/dtls/src/server.js +6 -1
- package/lib/dtls/src/server.js.map +1 -1
- package/lib/dtls/src/socket.d.ts +1 -0
- package/lib/dtls/src/socket.js +3 -0
- package/lib/dtls/src/socket.js.map +1 -1
- package/lib/ice/src/stun/message.js +2 -10
- package/lib/ice/src/stun/message.js.map +1 -1
- package/lib/index.mjs +705 -113
- package/lib/nonstandard/index.mjs +308 -44
- package/lib/rtp/src/index.d.ts +1 -0
- package/lib/rtp/src/index.js +1 -0
- package/lib/rtp/src/index.js.map +1 -1
- package/lib/rtp/src/srtp/cipher/ctr.d.ts +3 -3
- package/lib/rtp/src/srtp/cipher/ctr.js +25 -14
- package/lib/rtp/src/srtp/cipher/ctr.js.map +1 -1
- package/lib/rtp/src/srtp/cipher/gcm.d.ts +3 -3
- package/lib/rtp/src/srtp/cipher/gcm.js +57 -20
- package/lib/rtp/src/srtp/cipher/gcm.js.map +1 -1
- package/lib/rtp/src/srtp/cipher/index.d.ts +1 -1
- package/lib/rtp/src/srtp/cipher/index.js +1 -1
- package/lib/rtp/src/srtp/cipher/index.js.map +1 -1
- package/lib/rtp/src/srtp/context/srtp.d.ts +2 -1
- package/lib/rtp/src/srtp/context/srtp.js +22 -5
- package/lib/rtp/src/srtp/context/srtp.js.map +1 -1
- package/lib/rtp/src/srtp/error.d.ts +3 -0
- package/lib/rtp/src/srtp/error.js +11 -0
- package/lib/rtp/src/srtp/error.js.map +1 -0
- package/lib/rtp/src/srtp/packet.d.ts +5 -0
- package/lib/rtp/src/srtp/packet.js +48 -0
- package/lib/rtp/src/srtp/packet.js.map +1 -0
- package/lib/sctp/src/chunk.js +3 -6
- package/lib/sctp/src/chunk.js.map +1 -1
- package/lib/sctp/src/sctp.d.ts +19 -0
- package/lib/sctp/src/sctp.js +259 -23
- package/lib/sctp/src/sctp.js.map +1 -1
- package/lib/webrtc/src/dataChannel.d.ts +1 -0
- package/lib/webrtc/src/dataChannel.js +5 -2
- package/lib/webrtc/src/dataChannel.js.map +1 -1
- package/lib/webrtc/src/peerConnection.d.ts +4 -1
- package/lib/webrtc/src/peerConnection.js +26 -5
- package/lib/webrtc/src/peerConnection.js.map +1 -1
- package/lib/webrtc/src/sctpManager.d.ts +1 -1
- package/lib/webrtc/src/sctpManager.js +3 -2
- package/lib/webrtc/src/sctpManager.js.map +1 -1
- package/lib/webrtc/src/sdpManager.d.ts +1 -1
- package/lib/webrtc/src/sdpManager.js +3 -4
- package/lib/webrtc/src/sdpManager.js.map +1 -1
- package/lib/webrtc/src/secureTransportManager.js +1 -1
- package/lib/webrtc/src/secureTransportManager.js.map +1 -1
- package/lib/webrtc/src/transceiverManager.js +3 -2
- package/lib/webrtc/src/transceiverManager.js.map +1 -1
- package/lib/webrtc/src/transport/dtls.d.ts +1 -0
- package/lib/webrtc/src/transport/dtls.js +117 -12
- package/lib/webrtc/src/transport/dtls.js.map +1 -1
- package/lib/webrtc/src/transport/sctp.d.ts +9 -3
- package/lib/webrtc/src/transport/sctp.js +35 -9
- package/lib/webrtc/src/transport/sctp.js.map +1 -1
- package/lib/webrtc/src/utils.d.ts +2 -0
- package/lib/webrtc/src/utils.js +20 -0
- package/lib/webrtc/src/utils.js.map +1 -1
- package/package.json +1 -3
|
@@ -229,6 +229,105 @@ var BitStream = class {
|
|
|
229
229
|
}
|
|
230
230
|
};
|
|
231
231
|
|
|
232
|
+
// ../common/src/crc.ts
|
|
233
|
+
var POLY_CRC32 = 3988292384;
|
|
234
|
+
var POLY_CRC32C = 2197175160;
|
|
235
|
+
function isBufferLike(input) {
|
|
236
|
+
return typeof input !== "string";
|
|
237
|
+
}
|
|
238
|
+
function generateCRCTable(polynomial) {
|
|
239
|
+
const table = new Array(256);
|
|
240
|
+
let c = 0;
|
|
241
|
+
for (let n = 0; n < 256; ++n) {
|
|
242
|
+
c = n;
|
|
243
|
+
c = c & 1 ? polynomial ^ c >>> 1 : c >>> 1;
|
|
244
|
+
c = c & 1 ? polynomial ^ c >>> 1 : c >>> 1;
|
|
245
|
+
c = c & 1 ? polynomial ^ c >>> 1 : c >>> 1;
|
|
246
|
+
c = c & 1 ? polynomial ^ c >>> 1 : c >>> 1;
|
|
247
|
+
c = c & 1 ? polynomial ^ c >>> 1 : c >>> 1;
|
|
248
|
+
c = c & 1 ? polynomial ^ c >>> 1 : c >>> 1;
|
|
249
|
+
c = c & 1 ? polynomial ^ c >>> 1 : c >>> 1;
|
|
250
|
+
c = c & 1 ? polynomial ^ c >>> 1 : c >>> 1;
|
|
251
|
+
table[n] = c;
|
|
252
|
+
}
|
|
253
|
+
return new Int32Array(table);
|
|
254
|
+
}
|
|
255
|
+
function generateSliceBy16Tables(table0) {
|
|
256
|
+
const table = new Int32Array(4096);
|
|
257
|
+
let c = 0;
|
|
258
|
+
let v = 0;
|
|
259
|
+
let n = 0;
|
|
260
|
+
for (n = 0; n < 256; ++n) table[n] = table0[n];
|
|
261
|
+
for (n = 0; n < 256; ++n) {
|
|
262
|
+
v = table0[n];
|
|
263
|
+
for (c = 256 + n; c < 4096; c += 256) {
|
|
264
|
+
v = table[c] = v >>> 8 ^ table0[v & 255];
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
const out = [];
|
|
268
|
+
for (n = 1; n < 16; ++n) {
|
|
269
|
+
out[n - 1] = table.subarray(n * 256, n * 256 + 256);
|
|
270
|
+
}
|
|
271
|
+
return out;
|
|
272
|
+
}
|
|
273
|
+
function crcGenericString(value, seed, table0) {
|
|
274
|
+
let crc = seed ^ -1;
|
|
275
|
+
let i = 0;
|
|
276
|
+
const len = value.length;
|
|
277
|
+
let c = 0;
|
|
278
|
+
let d = 0;
|
|
279
|
+
while (i < len) {
|
|
280
|
+
c = value.charCodeAt(i++);
|
|
281
|
+
if (c < 128) {
|
|
282
|
+
crc = crc >>> 8 ^ table0[(crc ^ c) & 255];
|
|
283
|
+
} else if (c < 2048) {
|
|
284
|
+
crc = crc >>> 8 ^ table0[(crc ^ (192 | c >> 6 & 31)) & 255];
|
|
285
|
+
crc = crc >>> 8 ^ table0[(crc ^ (128 | c & 63)) & 255];
|
|
286
|
+
} else if (c >= 55296 && c < 57344) {
|
|
287
|
+
c = (c & 1023) + 64;
|
|
288
|
+
d = value.charCodeAt(i++) & 1023;
|
|
289
|
+
crc = crc >>> 8 ^ table0[(crc ^ (240 | c >> 8 & 7)) & 255];
|
|
290
|
+
crc = crc >>> 8 ^ table0[(crc ^ (128 | c >> 2 & 63)) & 255];
|
|
291
|
+
crc = crc >>> 8 ^ table0[(crc ^ (128 | d >> 6 & 15 | (c & 3) << 4)) & 255];
|
|
292
|
+
crc = crc >>> 8 ^ table0[(crc ^ (128 | d & 63)) & 255];
|
|
293
|
+
} else {
|
|
294
|
+
crc = crc >>> 8 ^ table0[(crc ^ (224 | c >> 12 & 15)) & 255];
|
|
295
|
+
crc = crc >>> 8 ^ table0[(crc ^ (128 | c >> 6 & 63)) & 255];
|
|
296
|
+
crc = crc >>> 8 ^ table0[(crc ^ (128 | c & 63)) & 255];
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return ~crc >>> 0;
|
|
300
|
+
}
|
|
301
|
+
function crcBuffer(value, seed, table0, tables16) {
|
|
302
|
+
const [t1, t2, t3, t4, t5, t6, t7, t8, t9, ta, tb, tc, td, te, tf] = tables16;
|
|
303
|
+
let crc = seed ^ -1;
|
|
304
|
+
let i = 0;
|
|
305
|
+
let len = value.length - 15;
|
|
306
|
+
while (i < len) {
|
|
307
|
+
crc = tf[value[i++] ^ crc & 255] ^ te[value[i++] ^ crc >>> 8 & 255] ^ td[value[i++] ^ crc >>> 16 & 255] ^ tc[value[i++] ^ crc >>> 24] ^ tb[value[i++]] ^ ta[value[i++]] ^ t9[value[i++]] ^ t8[value[i++]] ^ t7[value[i++]] ^ t6[value[i++]] ^ t5[value[i++]] ^ t4[value[i++]] ^ t3[value[i++]] ^ t2[value[i++]] ^ t1[value[i++]] ^ table0[value[i++]];
|
|
308
|
+
}
|
|
309
|
+
for (len += 15; i < len; ) {
|
|
310
|
+
crc = crc >>> 8 ^ table0[(crc ^ value[i++]) & 255];
|
|
311
|
+
}
|
|
312
|
+
return ~crc >>> 0;
|
|
313
|
+
}
|
|
314
|
+
var table32 = generateCRCTable(POLY_CRC32);
|
|
315
|
+
var tables32By16 = generateSliceBy16Tables(table32);
|
|
316
|
+
var table32c = generateCRCTable(POLY_CRC32C);
|
|
317
|
+
var tables32cBy16 = generateSliceBy16Tables(table32c);
|
|
318
|
+
function crc32(input, seed = 0) {
|
|
319
|
+
if (isBufferLike(input)) {
|
|
320
|
+
return crcBuffer(input, seed, table32, tables32By16);
|
|
321
|
+
}
|
|
322
|
+
return crcGenericString(input, seed, table32);
|
|
323
|
+
}
|
|
324
|
+
function crc32c(input, seed = 0) {
|
|
325
|
+
if (isBufferLike(input)) {
|
|
326
|
+
return crcBuffer(input, seed, table32c, tables32cBy16);
|
|
327
|
+
}
|
|
328
|
+
return crcGenericString(input, seed, table32c);
|
|
329
|
+
}
|
|
330
|
+
|
|
232
331
|
// ../common/src/number.ts
|
|
233
332
|
function uint8Add(a, b) {
|
|
234
333
|
return a + b & 255;
|
|
@@ -4378,7 +4477,12 @@ import { createHmac as createHmac2 } from "crypto";
|
|
|
4378
4477
|
import AES from "aes-js";
|
|
4379
4478
|
|
|
4380
4479
|
// ../rtp/src/srtp/cipher/ctr.ts
|
|
4381
|
-
import {
|
|
4480
|
+
import {
|
|
4481
|
+
createCipheriv as createCipheriv2,
|
|
4482
|
+
createDecipheriv,
|
|
4483
|
+
createHmac,
|
|
4484
|
+
timingSafeEqual
|
|
4485
|
+
} from "crypto";
|
|
4382
4486
|
|
|
4383
4487
|
// ../rtp/src/srtp/cipher/index.ts
|
|
4384
4488
|
var CipherAesBase = class {
|
|
@@ -4391,7 +4495,7 @@ var CipherAesBase = class {
|
|
|
4391
4495
|
encryptRtp(header, payload, rolloverCounter) {
|
|
4392
4496
|
return Buffer.from([]);
|
|
4393
4497
|
}
|
|
4394
|
-
decryptRtp(cipherText, rolloverCounter) {
|
|
4498
|
+
decryptRtp(cipherText, rolloverCounter, header) {
|
|
4395
4499
|
return [];
|
|
4396
4500
|
}
|
|
4397
4501
|
encryptRTCP(rawRtcp, srtcpIndex) {
|
|
@@ -4402,6 +4506,74 @@ var CipherAesBase = class {
|
|
|
4402
4506
|
}
|
|
4403
4507
|
};
|
|
4404
4508
|
|
|
4509
|
+
// ../rtp/src/srtp/error.ts
|
|
4510
|
+
var SrtpAuthenticationError = class extends Error {
|
|
4511
|
+
constructor(message) {
|
|
4512
|
+
super(message);
|
|
4513
|
+
this.name = "SrtpAuthenticationError";
|
|
4514
|
+
}
|
|
4515
|
+
};
|
|
4516
|
+
|
|
4517
|
+
// ../rtp/src/srtp/packet.ts
|
|
4518
|
+
var minRtpHeaderSize = 12;
|
|
4519
|
+
var minRtcpPacketSize = 8;
|
|
4520
|
+
function parseSrtpRtpHeader(packet, authTagLength, message = "Failed to authenticate SRTP packet") {
|
|
4521
|
+
const authTagOffset = packet.length - authTagLength;
|
|
4522
|
+
assertAuthenticatedPacketLength(
|
|
4523
|
+
packet.length >= minRtpHeaderSize + authTagLength,
|
|
4524
|
+
message
|
|
4525
|
+
);
|
|
4526
|
+
const header = wrapAuthenticationError(
|
|
4527
|
+
() => RtpHeader.deSerialize(packet.subarray(0, authTagOffset)),
|
|
4528
|
+
message
|
|
4529
|
+
);
|
|
4530
|
+
header.paddingSize = 0;
|
|
4531
|
+
assertAuthenticatedPacketLength(
|
|
4532
|
+
header.payloadOffset >= minRtpHeaderSize && header.payloadOffset <= authTagOffset,
|
|
4533
|
+
message
|
|
4534
|
+
);
|
|
4535
|
+
return header;
|
|
4536
|
+
}
|
|
4537
|
+
function parseSrtcpHeader(packet, authTagLength, srtcpIndexSize3, message = "Failed to authenticate SRTCP packet") {
|
|
4538
|
+
assertAuthenticatedPacketLength(
|
|
4539
|
+
packet.length >= minRtcpPacketSize + authTagLength + srtcpIndexSize3,
|
|
4540
|
+
message
|
|
4541
|
+
);
|
|
4542
|
+
return wrapAuthenticationError(
|
|
4543
|
+
() => RtcpHeader.deSerialize(packet.subarray(0, RTCP_HEADER_SIZE)),
|
|
4544
|
+
message
|
|
4545
|
+
);
|
|
4546
|
+
}
|
|
4547
|
+
function assertAuthenticatedPacketLength(condition, message) {
|
|
4548
|
+
if (!condition) {
|
|
4549
|
+
throw new SrtpAuthenticationError(message);
|
|
4550
|
+
}
|
|
4551
|
+
}
|
|
4552
|
+
function wrapAuthenticationError(parse, message) {
|
|
4553
|
+
try {
|
|
4554
|
+
return parse();
|
|
4555
|
+
} catch {
|
|
4556
|
+
throw new SrtpAuthenticationError(message);
|
|
4557
|
+
}
|
|
4558
|
+
}
|
|
4559
|
+
function finalizeSrtpRtpHeader(header, packet, message = "Failed to authenticate SRTP packet") {
|
|
4560
|
+
if (!header.padding) {
|
|
4561
|
+
header.paddingSize = 0;
|
|
4562
|
+
return header;
|
|
4563
|
+
}
|
|
4564
|
+
assertAuthenticatedPacketLength(
|
|
4565
|
+
packet.length > header.payloadOffset,
|
|
4566
|
+
message
|
|
4567
|
+
);
|
|
4568
|
+
const paddingSize = packet[packet.length - 1];
|
|
4569
|
+
assertAuthenticatedPacketLength(
|
|
4570
|
+
paddingSize > 0 && paddingSize <= packet.length - header.payloadOffset,
|
|
4571
|
+
message
|
|
4572
|
+
);
|
|
4573
|
+
header.paddingSize = paddingSize;
|
|
4574
|
+
return header;
|
|
4575
|
+
}
|
|
4576
|
+
|
|
4405
4577
|
// ../rtp/src/srtp/cipher/ctr.ts
|
|
4406
4578
|
var CipherAesCtr = class extends CipherAesBase {
|
|
4407
4579
|
constructor(srtpSessionKey, srtpSessionSalt, srtcpSessionKey, srtcpSessionSalt, srtpSessionAuthTag, srtcpSessionAuthTag) {
|
|
@@ -4427,10 +4599,20 @@ var CipherAesCtr = class extends CipherAesBase {
|
|
|
4427
4599
|
);
|
|
4428
4600
|
return Buffer.concat([headerBuffer, enc, authTag]);
|
|
4429
4601
|
}
|
|
4430
|
-
decryptRtp(cipherText, rolloverCounter) {
|
|
4431
|
-
const
|
|
4432
|
-
const
|
|
4433
|
-
|
|
4602
|
+
decryptRtp(cipherText, rolloverCounter, header = parseSrtpRtpHeader(cipherText, this.authTagLength)) {
|
|
4603
|
+
const authTagOffset = cipherText.length - this.authTagLength;
|
|
4604
|
+
const encryptedPacket = cipherText.subarray(0, authTagOffset);
|
|
4605
|
+
const actualAuthTag = cipherText.subarray(authTagOffset);
|
|
4606
|
+
const expectedAuthTag = this.generateSrtpAuthTag(
|
|
4607
|
+
rolloverCounter,
|
|
4608
|
+
encryptedPacket.subarray(0, header.payloadOffset),
|
|
4609
|
+
encryptedPacket.subarray(header.payloadOffset)
|
|
4610
|
+
);
|
|
4611
|
+
assertAuthTag(
|
|
4612
|
+
actualAuthTag,
|
|
4613
|
+
expectedAuthTag,
|
|
4614
|
+
"Failed to authenticate SRTP packet"
|
|
4615
|
+
);
|
|
4434
4616
|
const counter = this.generateCounter(
|
|
4435
4617
|
header.sequenceNumber,
|
|
4436
4618
|
rolloverCounter,
|
|
@@ -4442,14 +4624,16 @@ var CipherAesCtr = class extends CipherAesBase {
|
|
|
4442
4624
|
this.srtpSessionKey,
|
|
4443
4625
|
counter
|
|
4444
4626
|
);
|
|
4445
|
-
const payload =
|
|
4627
|
+
const payload = encryptedPacket.subarray(header.payloadOffset);
|
|
4446
4628
|
const buf = cipher.update(payload);
|
|
4447
4629
|
const dst = Buffer.concat([
|
|
4448
|
-
|
|
4449
|
-
buf
|
|
4450
|
-
Buffer.alloc(size - header.payloadOffset - buf.length)
|
|
4630
|
+
encryptedPacket.subarray(0, header.payloadOffset),
|
|
4631
|
+
buf
|
|
4451
4632
|
]);
|
|
4452
|
-
return [
|
|
4633
|
+
return [
|
|
4634
|
+
dst,
|
|
4635
|
+
finalizeSrtpRtpHeader(header, dst, "Failed to authenticate SRTP packet")
|
|
4636
|
+
];
|
|
4453
4637
|
}
|
|
4454
4638
|
encryptRTCP(rtcpPacket, srtcpIndex) {
|
|
4455
4639
|
let out = Buffer.from(rtcpPacket);
|
|
@@ -4471,15 +4655,29 @@ var CipherAesCtr = class extends CipherAesBase {
|
|
|
4471
4655
|
return out;
|
|
4472
4656
|
}
|
|
4473
4657
|
decryptRTCP(encrypted) {
|
|
4474
|
-
const header =
|
|
4658
|
+
const header = parseSrtcpHeader(
|
|
4659
|
+
encrypted,
|
|
4660
|
+
this.authTagLength,
|
|
4661
|
+
srtcpIndexSize
|
|
4662
|
+
);
|
|
4475
4663
|
const tailOffset = encrypted.length - (this.authTagLength + srtcpIndexSize);
|
|
4664
|
+
const authenticatedPortion = encrypted.subarray(
|
|
4665
|
+
0,
|
|
4666
|
+
encrypted.length - this.authTagLength
|
|
4667
|
+
);
|
|
4668
|
+
const actualTag = encrypted.subarray(encrypted.length - this.authTagLength);
|
|
4669
|
+
const expectedTag = this.generateSrtcpAuthTag(authenticatedPortion);
|
|
4670
|
+
assertAuthTag(
|
|
4671
|
+
actualTag,
|
|
4672
|
+
expectedTag,
|
|
4673
|
+
"Failed to authenticate SRTCP packet"
|
|
4674
|
+
);
|
|
4476
4675
|
const out = Buffer.from(encrypted).slice(0, tailOffset);
|
|
4477
|
-
const isEncrypted = encrypted[tailOffset]
|
|
4676
|
+
const isEncrypted = encrypted[tailOffset] >>> 7;
|
|
4478
4677
|
if (isEncrypted === 0) return [out, header];
|
|
4479
4678
|
let srtcpIndex = encrypted.readUInt32BE(tailOffset);
|
|
4480
4679
|
srtcpIndex &= ~(1 << 31);
|
|
4481
4680
|
const ssrc = encrypted.readUInt32BE(4);
|
|
4482
|
-
const actualTag = encrypted.subarray(encrypted.length - 10);
|
|
4483
4681
|
const counter = this.generateCounter(
|
|
4484
4682
|
srtcpIndex & 65535,
|
|
4485
4683
|
srtcpIndex >> 16,
|
|
@@ -4520,6 +4718,11 @@ var CipherAesCtr = class extends CipherAesBase {
|
|
|
4520
4718
|
}
|
|
4521
4719
|
};
|
|
4522
4720
|
var srtcpIndexSize = 4;
|
|
4721
|
+
function assertAuthTag(actual, expected, message) {
|
|
4722
|
+
if (actual.length !== expected.length || !timingSafeEqual(actual, expected)) {
|
|
4723
|
+
throw new SrtpAuthenticationError(message);
|
|
4724
|
+
}
|
|
4725
|
+
}
|
|
4523
4726
|
|
|
4524
4727
|
// ../rtp/src/srtp/cipher/gcm.ts
|
|
4525
4728
|
import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv2 } from "crypto";
|
|
@@ -4542,20 +4745,25 @@ var CipherAesGcm = class extends CipherAesBase {
|
|
|
4542
4745
|
const dst = Buffer.concat([hdr, enc, authTag]);
|
|
4543
4746
|
return dst;
|
|
4544
4747
|
}
|
|
4545
|
-
decryptRtp(cipherText, rolloverCounter) {
|
|
4546
|
-
const
|
|
4748
|
+
decryptRtp(cipherText, rolloverCounter, header = parseSrtpRtpHeader(cipherText, this.aeadAuthTagLen)) {
|
|
4749
|
+
const headerBuffer = cipherText.subarray(0, header.payloadOffset);
|
|
4750
|
+
const authTagOffset = cipherText.length - this.aeadAuthTagLen;
|
|
4751
|
+
const authTag = cipherText.subarray(authTagOffset);
|
|
4547
4752
|
let dst = Buffer.from([]);
|
|
4548
4753
|
dst = growBufferSize(dst, cipherText.length - this.aeadAuthTagLen);
|
|
4549
|
-
|
|
4754
|
+
headerBuffer.copy(dst);
|
|
4550
4755
|
const iv = this.rtpInitializationVector(header, rolloverCounter);
|
|
4551
|
-
const enc = cipherText.slice(
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
);
|
|
4555
|
-
const
|
|
4556
|
-
|
|
4756
|
+
const enc = cipherText.slice(header.payloadOffset, authTagOffset);
|
|
4757
|
+
const decipher = createDecipheriv2("aes-128-gcm", this.srtpSessionKey, iv);
|
|
4758
|
+
decipher.setAAD(headerBuffer);
|
|
4759
|
+
decipher.setAuthTag(authTag);
|
|
4760
|
+
const dec = decipher.update(enc);
|
|
4761
|
+
finalizeAuthenticatedDecryption(decipher, "SRTP");
|
|
4557
4762
|
dec.copy(dst, header.payloadOffset);
|
|
4558
|
-
return [
|
|
4763
|
+
return [
|
|
4764
|
+
dst,
|
|
4765
|
+
finalizeSrtpRtpHeader(header, dst, "Failed to authenticate SRTP packet")
|
|
4766
|
+
];
|
|
4559
4767
|
}
|
|
4560
4768
|
encryptRTCP(rtcpPacket, srtcpIndex) {
|
|
4561
4769
|
const ssrc = rtcpPacket.readUInt32BE(4);
|
|
@@ -4576,19 +4784,38 @@ var CipherAesGcm = class extends CipherAesBase {
|
|
|
4576
4784
|
return dst;
|
|
4577
4785
|
}
|
|
4578
4786
|
decryptRTCP(encrypted) {
|
|
4579
|
-
const header =
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4787
|
+
const header = parseSrtcpHeader(
|
|
4788
|
+
encrypted,
|
|
4789
|
+
this.aeadAuthTagLen,
|
|
4790
|
+
srtcpIndexSize2
|
|
4791
|
+
);
|
|
4792
|
+
const srtcpIndexOffset = encrypted.length - srtcpIndexSize2;
|
|
4793
|
+
const authTagOffset = srtcpIndexOffset - this.aeadAuthTagLen;
|
|
4583
4794
|
const ssrc = encrypted.readUInt32BE(4);
|
|
4584
|
-
|
|
4585
|
-
|
|
4795
|
+
const encodedSrtcpIndex = encrypted.readUInt32BE(srtcpIndexOffset);
|
|
4796
|
+
const isEncrypted = encodedSrtcpIndex >>> 31 === 1;
|
|
4797
|
+
const srtcpIndex = encodedSrtcpIndex & ~(rtcpEncryptionFlag << 24);
|
|
4586
4798
|
const iv = this.rtcpInitializationVector(ssrc, srtcpIndex);
|
|
4587
|
-
const aad =
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4799
|
+
const aad = isEncrypted ? Buffer.concat([
|
|
4800
|
+
encrypted.subarray(0, 8),
|
|
4801
|
+
encrypted.subarray(srtcpIndexOffset)
|
|
4802
|
+
]) : Buffer.concat([
|
|
4803
|
+
encrypted.subarray(0, authTagOffset),
|
|
4804
|
+
encrypted.subarray(srtcpIndexOffset)
|
|
4805
|
+
]);
|
|
4806
|
+
const cipherText = isEncrypted ? encrypted.slice(8, authTagOffset) : Buffer.alloc(0);
|
|
4807
|
+
const dst = isEncrypted ? Buffer.alloc(authTagOffset) : Buffer.from(encrypted.subarray(0, authTagOffset));
|
|
4808
|
+
if (isEncrypted) {
|
|
4809
|
+
encrypted.slice(0, 8).copy(dst);
|
|
4810
|
+
}
|
|
4811
|
+
const decipher = createDecipheriv2("aes-128-gcm", this.srtcpSessionKey, iv);
|
|
4812
|
+
decipher.setAAD(aad);
|
|
4813
|
+
decipher.setAuthTag(encrypted.subarray(authTagOffset, srtcpIndexOffset));
|
|
4814
|
+
const dec = decipher.update(cipherText);
|
|
4815
|
+
finalizeAuthenticatedDecryption(decipher, "SRTCP");
|
|
4816
|
+
if (isEncrypted) {
|
|
4817
|
+
dec.copy(dst, 8);
|
|
4818
|
+
}
|
|
4592
4819
|
return [dst, header];
|
|
4593
4820
|
}
|
|
4594
4821
|
// https://tools.ietf.org/html/rfc7714#section-8.1
|
|
@@ -4624,6 +4851,15 @@ var CipherAesGcm = class extends CipherAesBase {
|
|
|
4624
4851
|
};
|
|
4625
4852
|
var srtcpIndexSize2 = 4;
|
|
4626
4853
|
var rtcpEncryptionFlag = 128;
|
|
4854
|
+
function finalizeAuthenticatedDecryption(decipher, packetType) {
|
|
4855
|
+
try {
|
|
4856
|
+
decipher.final();
|
|
4857
|
+
} catch {
|
|
4858
|
+
throw new SrtpAuthenticationError(
|
|
4859
|
+
`Failed to authenticate ${packetType} packet`
|
|
4860
|
+
);
|
|
4861
|
+
}
|
|
4862
|
+
}
|
|
4627
4863
|
|
|
4628
4864
|
// ../rtp/src/srtp/context/context.ts
|
|
4629
4865
|
var Context = class {
|
|
@@ -4881,12 +5117,29 @@ var SrtpContext = class extends Context {
|
|
|
4881
5117
|
return enc;
|
|
4882
5118
|
}
|
|
4883
5119
|
decryptRtp(cipherText) {
|
|
4884
|
-
const header =
|
|
4885
|
-
const
|
|
4886
|
-
|
|
4887
|
-
|
|
5120
|
+
const header = parseSrtpRtpHeader(cipherText, this.rtpAuthTagLength);
|
|
5121
|
+
const existingState = this.srtpSSRCStates[header.ssrc];
|
|
5122
|
+
const nextState = existingState ? { ...existingState } : {
|
|
5123
|
+
ssrc: header.ssrc,
|
|
5124
|
+
rolloverCounter: 0,
|
|
5125
|
+
lastSequenceNumber: 0
|
|
5126
|
+
};
|
|
5127
|
+
this.updateRolloverCount(header.sequenceNumber, nextState);
|
|
5128
|
+
const dec = this.cipher.decryptRtp(
|
|
5129
|
+
cipherText,
|
|
5130
|
+
nextState.rolloverCounter,
|
|
5131
|
+
header
|
|
5132
|
+
);
|
|
5133
|
+
if (existingState) {
|
|
5134
|
+
Object.assign(existingState, nextState);
|
|
5135
|
+
} else {
|
|
5136
|
+
this.srtpSSRCStates[header.ssrc] = nextState;
|
|
5137
|
+
}
|
|
4888
5138
|
return dec;
|
|
4889
5139
|
}
|
|
5140
|
+
get rtpAuthTagLength() {
|
|
5141
|
+
return this.profile === ProtectionProfileAeadAes128Gcm ? 16 : 10;
|
|
5142
|
+
}
|
|
4890
5143
|
};
|
|
4891
5144
|
|
|
4892
5145
|
// ../rtp/src/srtp/srtp.ts
|
|
@@ -8409,6 +8662,16 @@ handlers2[16 /* client_key_exchange_16 */] = ({ cipher, dtls }) => (message) =>
|
|
|
8409
8662
|
);
|
|
8410
8663
|
log18(dtls.sessionId, "setup cipher", cipher.cipher.summary);
|
|
8411
8664
|
};
|
|
8665
|
+
handlers2[11 /* certificate_11 */] = ({ cipher, dtls }) => (message) => {
|
|
8666
|
+
log18(dtls.sessionId, "handshake certificate", message);
|
|
8667
|
+
cipher.remoteCertificate = message.certificateList[0];
|
|
8668
|
+
};
|
|
8669
|
+
handlers2[15 /* certificate_verify_15 */] = ({ cipher, dtls }) => (message) => {
|
|
8670
|
+
if (!cipher.remoteCertificate) {
|
|
8671
|
+
throw new Error("client certificate missing before certificate verify");
|
|
8672
|
+
}
|
|
8673
|
+
log18(dtls.sessionId, "certificate_verify", message.algorithm);
|
|
8674
|
+
};
|
|
8412
8675
|
handlers2[20 /* finished_20 */] = ({ dtls }) => (message) => {
|
|
8413
8676
|
log18(dtls.sessionId, "finished", message);
|
|
8414
8677
|
};
|
|
@@ -8421,9 +8684,6 @@ var COOKIE = 554869826;
|
|
|
8421
8684
|
var IPV4_PROTOCOL = 1;
|
|
8422
8685
|
var IPV6_PROTOCOL = 2;
|
|
8423
8686
|
|
|
8424
|
-
// ../ice/src/stun/message.ts
|
|
8425
|
-
import crc32 from "buffer-crc32";
|
|
8426
|
-
|
|
8427
8687
|
// ../ice/src/stun/attributes.ts
|
|
8428
8688
|
import * as Int64 from "int64-buffer";
|
|
8429
8689
|
import nodeIp from "ip";
|
|
@@ -8808,7 +9068,6 @@ import { jspack as jspack6 } from "@shinyoshiaki/jspack";
|
|
|
8808
9068
|
import { jspack as jspack5 } from "@shinyoshiaki/jspack";
|
|
8809
9069
|
|
|
8810
9070
|
// ../sctp/src/chunk.ts
|
|
8811
|
-
import crc32c from "turbo-crc32/crc32c.js";
|
|
8812
9071
|
var Chunk = class _Chunk {
|
|
8813
9072
|
constructor(flags = 0, _body = Buffer.from("")) {
|
|
8814
9073
|
this.flags = flags;
|
|
@@ -9206,6 +9465,7 @@ var SCTP_TSN_MODULO = 2 ** 32;
|
|
|
9206
9465
|
|
|
9207
9466
|
// src/transport/sctp.ts
|
|
9208
9467
|
var log32 = debug("werift:packages/webrtc/src/transport/sctp.ts");
|
|
9468
|
+
var DEFAULT_MAX_MESSAGE_SIZE = 65536;
|
|
9209
9469
|
|
|
9210
9470
|
// src/media/rtpReceiver.ts
|
|
9211
9471
|
var log33 = debug("werift:packages/webrtc/src/media/rtpReceiver.ts");
|
|
@@ -9257,7 +9517,8 @@ function generateDefaultPeerConfig() {
|
|
|
9257
9517
|
bundlePolicy: "max-compat",
|
|
9258
9518
|
debug: {},
|
|
9259
9519
|
midSuffix: false,
|
|
9260
|
-
forceTurnTCP: false
|
|
9520
|
+
forceTurnTCP: false,
|
|
9521
|
+
maxMessageSize: DEFAULT_MAX_MESSAGE_SIZE
|
|
9261
9522
|
};
|
|
9262
9523
|
}
|
|
9263
9524
|
var defaultPeerConfig = generateDefaultPeerConfig();
|
|
@@ -9723,6 +9984,7 @@ export {
|
|
|
9723
9984
|
SourceDescriptionChunk,
|
|
9724
9985
|
SourceDescriptionItem,
|
|
9725
9986
|
SrtcpSession,
|
|
9987
|
+
SrtpAuthenticationError,
|
|
9726
9988
|
SrtpSession,
|
|
9727
9989
|
StatusVectorChunk,
|
|
9728
9990
|
TcpTransport,
|
|
@@ -9747,6 +10009,8 @@ export {
|
|
|
9747
10009
|
build,
|
|
9748
10010
|
bytes,
|
|
9749
10011
|
containerSupportedCodecs,
|
|
10012
|
+
crc32,
|
|
10013
|
+
crc32c,
|
|
9750
10014
|
createBufferWriter,
|
|
9751
10015
|
dePacketizeRtpPackets,
|
|
9752
10016
|
debug,
|
package/lib/rtp/src/index.d.ts
CHANGED
package/lib/rtp/src/index.js
CHANGED
|
@@ -38,5 +38,6 @@ __exportStar(require("./rtp/rtp"), exports);
|
|
|
38
38
|
__exportStar(require("./rtp/rtx"), exports);
|
|
39
39
|
__exportStar(require("./srtp/srtcp"), exports);
|
|
40
40
|
__exportStar(require("./srtp/srtp"), exports);
|
|
41
|
+
__exportStar(require("./srtp/error"), exports);
|
|
41
42
|
__exportStar(require("./util"), exports);
|
|
42
43
|
//# sourceMappingURL=index.js.map
|
package/lib/rtp/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../rtp/src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kBAAgB;AAChB,+CAA6B;AAC7B,mDAAiC;AACjC,0CAAwB;AACxB,2CAAyB;AACzB,gDAA8B;AAC9B,8CAA4B;AAC5B,oEAAkD;AAClD,mDAAiC;AACjC,4CAA0B;AAC1B,8CAA4B;AAC5B,+CAA6B;AAC7B,oDAAkC;AAClC,oDAAkC;AAClC,8CAA4B;AAC5B,4CAA0B;AAC1B,wDAAsC;AACtC,oDAAkC;AAClC,oDAAkC;AAClC,mDAAiC;AACjC,4CAA0B;AAC1B,4CAA0B;AAC1B,+CAA6B;AAC7B,8CAA4B;AAC5B,yCAAuB","sourcesContent":["import \"buffer\";\nexport * from \"./srtp/const\";\nexport * from \"../../common/src\";\nexport * from \"./codec\";\nexport * from \"./helper\";\nexport * from \"./rtcp/header\";\nexport * from \"./rtcp/psfb\";\nexport * from \"./rtcp/psfb/pictureLossIndication\";\nexport * from \"./rtcp/psfb/remb\";\nexport * from \"./rtcp/rr\";\nexport * from \"./rtcp/rtcp\";\nexport * from \"./rtcp/rtpfb\";\nexport * from \"./rtcp/rtpfb/nack\";\nexport * from \"./rtcp/rtpfb/twcc\";\nexport * from \"./rtcp/sdes\";\nexport * from \"./rtcp/sr\";\nexport * from \"./rtp/headerExtension\";\nexport * from \"./rtp/red/encoder\";\nexport * from \"./rtp/red/handler\";\nexport * from \"./rtp/red/packet\";\nexport * from \"./rtp/rtp\";\nexport * from \"./rtp/rtx\";\nexport * from \"./srtp/srtcp\";\nexport * from \"./srtp/srtp\";\nexport * from \"./util\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../rtp/src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kBAAgB;AAChB,+CAA6B;AAC7B,mDAAiC;AACjC,0CAAwB;AACxB,2CAAyB;AACzB,gDAA8B;AAC9B,8CAA4B;AAC5B,oEAAkD;AAClD,mDAAiC;AACjC,4CAA0B;AAC1B,8CAA4B;AAC5B,+CAA6B;AAC7B,oDAAkC;AAClC,oDAAkC;AAClC,8CAA4B;AAC5B,4CAA0B;AAC1B,wDAAsC;AACtC,oDAAkC;AAClC,oDAAkC;AAClC,mDAAiC;AACjC,4CAA0B;AAC1B,4CAA0B;AAC1B,+CAA6B;AAC7B,8CAA4B;AAC5B,+CAA6B;AAC7B,yCAAuB","sourcesContent":["import \"buffer\";\nexport * from \"./srtp/const\";\nexport * from \"../../common/src\";\nexport * from \"./codec\";\nexport * from \"./helper\";\nexport * from \"./rtcp/header\";\nexport * from \"./rtcp/psfb\";\nexport * from \"./rtcp/psfb/pictureLossIndication\";\nexport * from \"./rtcp/psfb/remb\";\nexport * from \"./rtcp/rr\";\nexport * from \"./rtcp/rtcp\";\nexport * from \"./rtcp/rtpfb\";\nexport * from \"./rtcp/rtpfb/nack\";\nexport * from \"./rtcp/rtpfb/twcc\";\nexport * from \"./rtcp/sdes\";\nexport * from \"./rtcp/sr\";\nexport * from \"./rtp/headerExtension\";\nexport * from \"./rtp/red/encoder\";\nexport * from \"./rtp/red/handler\";\nexport * from \"./rtp/red/packet\";\nexport * from \"./rtp/rtp\";\nexport * from \"./rtp/rtx\";\nexport * from \"./srtp/srtcp\";\nexport * from \"./srtp/srtp\";\nexport * from \"./srtp/error\";\nexport * from \"./util\";\n"]}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { CipherAesBase } from ".";
|
|
2
|
-
import { RtcpHeader } from "../../rtcp/header";
|
|
3
|
-
import { RtpHeader } from "../../rtp/rtp";
|
|
2
|
+
import type { RtcpHeader } from "../../rtcp/header";
|
|
3
|
+
import type { RtpHeader } from "../../rtp/rtp";
|
|
4
4
|
export declare class CipherAesCtr extends CipherAesBase {
|
|
5
5
|
private srtpSessionAuthTag;
|
|
6
6
|
private srtcpSessionAuthTag;
|
|
7
7
|
readonly authTagLength = 10;
|
|
8
8
|
constructor(srtpSessionKey: Buffer, srtpSessionSalt: Buffer, srtcpSessionKey: Buffer, srtcpSessionSalt: Buffer, srtpSessionAuthTag: Buffer, srtcpSessionAuthTag: Buffer);
|
|
9
9
|
encryptRtp(header: RtpHeader, payload: Buffer, rolloverCounter: number): Buffer<ArrayBuffer>;
|
|
10
|
-
decryptRtp(cipherText: Buffer, rolloverCounter: number): [Buffer, RtpHeader];
|
|
10
|
+
decryptRtp(cipherText: Buffer, rolloverCounter: number, header?: RtpHeader): [Buffer, RtpHeader];
|
|
11
11
|
encryptRTCP(rtcpPacket: Buffer, srtcpIndex: number): Buffer;
|
|
12
12
|
decryptRTCP(encrypted: Buffer): [Buffer, RtcpHeader];
|
|
13
13
|
generateSrtcpAuthTag(buf: Buffer): Buffer<ArrayBuffer>;
|
|
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.CipherAesCtr = void 0;
|
|
4
4
|
const crypto_1 = require("crypto");
|
|
5
5
|
const _1 = require(".");
|
|
6
|
-
const
|
|
7
|
-
const
|
|
6
|
+
const error_1 = require("../error");
|
|
7
|
+
const packet_1 = require("../packet");
|
|
8
8
|
class CipherAesCtr extends _1.CipherAesBase {
|
|
9
9
|
constructor(srtpSessionKey, srtpSessionSalt, srtcpSessionKey, srtcpSessionSalt, srtpSessionAuthTag, srtcpSessionAuthTag) {
|
|
10
10
|
super(srtpSessionKey, srtpSessionSalt, srtcpSessionKey, srtcpSessionSalt);
|
|
@@ -35,20 +35,24 @@ class CipherAesCtr extends _1.CipherAesBase {
|
|
|
35
35
|
const authTag = this.generateSrtpAuthTag(rolloverCounter, headerBuffer, enc);
|
|
36
36
|
return Buffer.concat([headerBuffer, enc, authTag]);
|
|
37
37
|
}
|
|
38
|
-
decryptRtp(cipherText, rolloverCounter) {
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
|
|
38
|
+
decryptRtp(cipherText, rolloverCounter, header = (0, packet_1.parseSrtpRtpHeader)(cipherText, this.authTagLength)) {
|
|
39
|
+
const authTagOffset = cipherText.length - this.authTagLength;
|
|
40
|
+
const encryptedPacket = cipherText.subarray(0, authTagOffset);
|
|
41
|
+
const actualAuthTag = cipherText.subarray(authTagOffset);
|
|
42
|
+
const expectedAuthTag = this.generateSrtpAuthTag(rolloverCounter, encryptedPacket.subarray(0, header.payloadOffset), encryptedPacket.subarray(header.payloadOffset));
|
|
43
|
+
assertAuthTag(actualAuthTag, expectedAuthTag, "Failed to authenticate SRTP packet");
|
|
42
44
|
const counter = this.generateCounter(header.sequenceNumber, rolloverCounter, header.ssrc, this.srtpSessionSalt);
|
|
43
45
|
const cipher = (0, crypto_1.createDecipheriv)("aes-128-ctr", this.srtpSessionKey, counter);
|
|
44
|
-
const payload =
|
|
46
|
+
const payload = encryptedPacket.subarray(header.payloadOffset);
|
|
45
47
|
const buf = cipher.update(payload);
|
|
46
48
|
const dst = Buffer.concat([
|
|
47
|
-
|
|
49
|
+
encryptedPacket.subarray(0, header.payloadOffset),
|
|
48
50
|
buf,
|
|
49
|
-
Buffer.alloc(size - header.payloadOffset - buf.length),
|
|
50
51
|
]);
|
|
51
|
-
return [
|
|
52
|
+
return [
|
|
53
|
+
dst,
|
|
54
|
+
(0, packet_1.finalizeSrtpRtpHeader)(header, dst, "Failed to authenticate SRTP packet"),
|
|
55
|
+
];
|
|
52
56
|
}
|
|
53
57
|
encryptRTCP(rtcpPacket, srtcpIndex) {
|
|
54
58
|
let out = Buffer.from(rtcpPacket);
|
|
@@ -66,17 +70,19 @@ class CipherAesCtr extends _1.CipherAesBase {
|
|
|
66
70
|
return out;
|
|
67
71
|
}
|
|
68
72
|
decryptRTCP(encrypted) {
|
|
69
|
-
const header =
|
|
73
|
+
const header = (0, packet_1.parseSrtcpHeader)(encrypted, this.authTagLength, srtcpIndexSize);
|
|
70
74
|
const tailOffset = encrypted.length - (this.authTagLength + srtcpIndexSize);
|
|
75
|
+
const authenticatedPortion = encrypted.subarray(0, encrypted.length - this.authTagLength);
|
|
76
|
+
const actualTag = encrypted.subarray(encrypted.length - this.authTagLength);
|
|
77
|
+
const expectedTag = this.generateSrtcpAuthTag(authenticatedPortion);
|
|
78
|
+
assertAuthTag(actualTag, expectedTag, "Failed to authenticate SRTCP packet");
|
|
71
79
|
const out = Buffer.from(encrypted).slice(0, tailOffset);
|
|
72
|
-
const isEncrypted = encrypted[tailOffset]
|
|
80
|
+
const isEncrypted = encrypted[tailOffset] >>> 7;
|
|
73
81
|
if (isEncrypted === 0)
|
|
74
82
|
return [out, header];
|
|
75
83
|
let srtcpIndex = encrypted.readUInt32BE(tailOffset);
|
|
76
84
|
srtcpIndex &= ~(1 << 31);
|
|
77
85
|
const ssrc = encrypted.readUInt32BE(4);
|
|
78
|
-
// todo impl compare
|
|
79
|
-
const actualTag = encrypted.subarray(encrypted.length - 10);
|
|
80
86
|
const counter = this.generateCounter(srtcpIndex & 0xffff, srtcpIndex >> 16, ssrc, this.srtcpSessionSalt);
|
|
81
87
|
const cipher = (0, crypto_1.createDecipheriv)("aes-128-ctr", this.srtcpSessionKey, counter);
|
|
82
88
|
const buf = cipher.update(out.subarray(8));
|
|
@@ -109,4 +115,9 @@ class CipherAesCtr extends _1.CipherAesBase {
|
|
|
109
115
|
}
|
|
110
116
|
exports.CipherAesCtr = CipherAesCtr;
|
|
111
117
|
const srtcpIndexSize = 4;
|
|
118
|
+
function assertAuthTag(actual, expected, message) {
|
|
119
|
+
if (actual.length !== expected.length || !(0, crypto_1.timingSafeEqual)(actual, expected)) {
|
|
120
|
+
throw new error_1.SrtpAuthenticationError(message);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
112
123
|
//# sourceMappingURL=ctr.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ctr.js","sourceRoot":"","sources":["../../../../../../rtp/src/srtp/cipher/ctr.ts"],"names":[],"mappings":"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","sourcesContent":["import { createCipheriv, createDecipheriv, createHmac } from \"crypto\";\n\nimport { CipherAesBase } from \".\";\nimport { RtcpHeader } from \"../../rtcp/header\";\nimport { RtpHeader } from \"../../rtp/rtp\";\n\nexport class CipherAesCtr extends CipherAesBase {\n readonly authTagLength = 10;\n\n constructor(\n srtpSessionKey: Buffer,\n srtpSessionSalt: Buffer,\n srtcpSessionKey: Buffer,\n srtcpSessionSalt: Buffer,\n private srtpSessionAuthTag: Buffer,\n private srtcpSessionAuthTag: Buffer,\n ) {\n super(srtpSessionKey, srtpSessionSalt, srtcpSessionKey, srtcpSessionSalt);\n }\n\n encryptRtp(header: RtpHeader, payload: Buffer, rolloverCounter: number) {\n const headerBuffer = header.serialize(header.serializeSize);\n\n const counter = this.generateCounter(\n header.sequenceNumber,\n rolloverCounter,\n header.ssrc,\n this.srtpSessionSalt,\n );\n\n const cipher = createCipheriv(\"aes-128-ctr\", this.srtpSessionKey, counter);\n const enc = cipher.update(payload);\n\n const authTag = this.generateSrtpAuthTag(\n rolloverCounter,\n headerBuffer,\n enc,\n );\n return Buffer.concat([headerBuffer, enc, authTag]);\n }\n\n decryptRtp(cipherText: Buffer, rolloverCounter: number): [Buffer, RtpHeader] {\n const header = RtpHeader.deSerialize(cipherText);\n\n const size = cipherText.length - this.authTagLength;\n\n cipherText = cipherText.subarray(0, cipherText.length - this.authTagLength);\n\n const counter = this.generateCounter(\n header.sequenceNumber,\n rolloverCounter,\n header.ssrc,\n this.srtpSessionSalt,\n );\n const cipher = createDecipheriv(\n \"aes-128-ctr\",\n this.srtpSessionKey,\n counter,\n );\n const payload = cipherText.subarray(header.payloadOffset);\n const buf = cipher.update(payload);\n\n const dst = Buffer.concat([\n cipherText.subarray(0, header.payloadOffset),\n buf,\n Buffer.alloc(size - header.payloadOffset - buf.length),\n ]);\n\n return [dst, header];\n }\n\n encryptRTCP(rtcpPacket: Buffer, srtcpIndex: number): Buffer {\n let out = Buffer.from(rtcpPacket);\n const ssrc = out.readUInt32BE(4);\n\n const counter = this.generateCounter(\n srtcpIndex & 0xffff,\n srtcpIndex >> 16,\n ssrc,\n this.srtcpSessionSalt,\n );\n const cipher = createCipheriv(\"aes-128-ctr\", this.srtcpSessionKey, counter);\n // Encrypt everything after header\n const buf = cipher.update(out.slice(8));\n buf.copy(out, 8);\n out = Buffer.concat([out, Buffer.alloc(4)]);\n out.writeUInt32BE(srtcpIndex, out.length - 4);\n out[out.length - 4] |= 0x80;\n const authTag = this.generateSrtcpAuthTag(out);\n out = Buffer.concat([out, authTag]);\n\n return out;\n }\n\n decryptRTCP(encrypted: Buffer): [Buffer, RtcpHeader] {\n const header = RtcpHeader.deSerialize(encrypted);\n\n const tailOffset = encrypted.length - (this.authTagLength + srtcpIndexSize);\n const out = Buffer.from(encrypted).slice(0, tailOffset);\n\n const isEncrypted = encrypted[tailOffset] >> 7;\n if (isEncrypted === 0) return [out, header];\n\n let srtcpIndex = encrypted.readUInt32BE(tailOffset);\n srtcpIndex &= ~(1 << 31);\n\n const ssrc = encrypted.readUInt32BE(4);\n\n // todo impl compare\n const actualTag = encrypted.subarray(encrypted.length - 10);\n\n const counter = this.generateCounter(\n srtcpIndex & 0xffff,\n srtcpIndex >> 16,\n ssrc,\n this.srtcpSessionSalt,\n );\n const cipher = createDecipheriv(\n \"aes-128-ctr\",\n this.srtcpSessionKey,\n counter,\n );\n const buf = cipher.update(out.subarray(8));\n buf.copy(out, 8);\n return [out, header];\n }\n\n generateSrtcpAuthTag(buf: Buffer) {\n const srtcpSessionAuth = createHmac(\"sha1\", this.srtcpSessionAuthTag);\n return srtcpSessionAuth.update(buf).digest().slice(0, 10);\n }\n\n generateCounter(\n sequenceNumber: number,\n rolloverCounter: number,\n ssrc: number,\n sessionSalt: Buffer,\n ) {\n const counter = Buffer.alloc(16);\n counter.writeUInt32BE(ssrc, 4);\n counter.writeUInt32BE(rolloverCounter, 8);\n counter.writeUInt32BE(Number(BigInt(sequenceNumber) << 16n), 12);\n\n for (let i = 0; i < sessionSalt.length; i++) {\n counter[i] ^= sessionSalt[i];\n }\n return counter;\n }\n\n generateSrtpAuthTag(roc: number, ...buffers: Buffer[]) {\n const srtpSessionAuth = createHmac(\"sha1\", this.srtpSessionAuthTag);\n const rocRaw = Buffer.alloc(4);\n rocRaw.writeUInt32BE(roc);\n\n for (const buf of buffers) {\n srtpSessionAuth.update(buf);\n }\n return srtpSessionAuth.update(rocRaw).digest().subarray(0, 10);\n }\n}\n\nconst srtcpIndexSize = 4;\n"]}
|
|
1
|
+
{"version":3,"file":"ctr.js","sourceRoot":"","sources":["../../../../../../rtp/src/srtp/cipher/ctr.ts"],"names":[],"mappings":";;;AAAA,mCAKgB;AAEhB,wBAAkC;AAGlC,oCAAmD;AACnD,sCAImB;AAEnB,MAAa,YAAa,SAAQ,gBAAa;IAG7C,YACE,cAAsB,EACtB,eAAuB,EACvB,eAAuB,EACvB,gBAAwB,EAChB,kBAA0B,EAC1B,mBAA2B;QAEnC,KAAK,CAAC,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,gBAAgB,CAAC,CAAC;QAH1E;;;;mBAAQ,kBAAkB;WAAQ;QAClC;;;;mBAAQ,mBAAmB;WAAQ;QAR5B;;;;mBAAgB,EAAE;WAAC;IAW5B,CAAC;IAED,UAAU,CAAC,MAAiB,EAAE,OAAe,EAAE,eAAuB;QACpE,MAAM,YAAY,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QAE5D,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAClC,MAAM,CAAC,cAAc,EACrB,eAAe,EACf,MAAM,CAAC,IAAI,EACX,IAAI,CAAC,eAAe,CACrB,CAAC;QAEF,MAAM,MAAM,GAAG,IAAA,uBAAc,EAAC,aAAa,EAAE,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;QAC3E,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAEnC,MAAM,OAAO,GAAG,IAAI,CAAC,mBAAmB,CACtC,eAAe,EACf,YAAY,EACZ,GAAG,CACJ,CAAC;QACF,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IACrD,CAAC;IAED,UAAU,CACR,UAAkB,EAClB,eAAuB,EACvB,MAAM,GAAG,IAAA,2BAAkB,EAAC,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC;QAE3D,MAAM,aAAa,GAAG,UAAU,CAAC,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC;QAC7D,MAAM,eAAe,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;QAC9D,MAAM,aAAa,GAAG,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QAEzD,MAAM,eAAe,GAAG,IAAI,CAAC,mBAAmB,CAC9C,eAAe,EACf,eAAe,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,aAAa,CAAC,EACjD,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,aAAa,CAAC,CAC/C,CAAC;QACF,aAAa,CACX,aAAa,EACb,eAAe,EACf,oCAAoC,CACrC,CAAC;QAEF,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAClC,MAAM,CAAC,cAAc,EACrB,eAAe,EACf,MAAM,CAAC,IAAI,EACX,IAAI,CAAC,eAAe,CACrB,CAAC;QACF,MAAM,MAAM,GAAG,IAAA,yBAAgB,EAC7B,aAAa,EACb,IAAI,CAAC,cAAc,EACnB,OAAO,CACR,CAAC;QACF,MAAM,OAAO,GAAG,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QAC/D,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAEnC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC;YACxB,eAAe,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,aAAa,CAAC;YACjD,GAAG;SACJ,CAAC,CAAC;QAEH,OAAO;YACL,GAAG;YACH,IAAA,8BAAqB,EAAC,MAAM,EAAE,GAAG,EAAE,oCAAoC,CAAC;SACzE,CAAC;IACJ,CAAC;IAED,WAAW,CAAC,UAAkB,EAAE,UAAkB;QAChD,IAAI,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAEjC,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAClC,UAAU,GAAG,MAAM,EACnB,UAAU,IAAI,EAAE,EAChB,IAAI,EACJ,IAAI,CAAC,gBAAgB,CACtB,CAAC;QACF,MAAM,MAAM,GAAG,IAAA,uBAAc,EAAC,aAAa,EAAE,IAAI,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;QAC5E,kCAAkC;QAClC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACxC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACjB,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5C,GAAG,CAAC,aAAa,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC9C,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC;QAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;QAC/C,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;QAEpC,OAAO,GAAG,CAAC;IACb,CAAC;IAED,WAAW,CAAC,SAAiB;QAC3B,MAAM,MAAM,GAAG,IAAA,yBAAgB,EAC7B,SAAS,EACT,IAAI,CAAC,aAAa,EAClB,cAAc,CACf,CAAC;QAEF,MAAM,UAAU,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,aAAa,GAAG,cAAc,CAAC,CAAC;QAC5E,MAAM,oBAAoB,GAAG,SAAS,CAAC,QAAQ,CAC7C,CAAC,EACD,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,aAAa,CACtC,CAAC;QACF,MAAM,SAAS,GAAG,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC;QAC5E,MAAM,WAAW,GAAG,IAAI,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,CAAC;QACpE,aAAa,CACX,SAAS,EACT,WAAW,EACX,qCAAqC,CACtC,CAAC;QAEF,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;QAExD,MAAM,WAAW,GAAG,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAChD,IAAI,WAAW,KAAK,CAAC;YAAE,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAE5C,IAAI,UAAU,GAAG,SAAS,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QACpD,UAAU,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAEzB,MAAM,IAAI,GAAG,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAEvC,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAClC,UAAU,GAAG,MAAM,EACnB,UAAU,IAAI,EAAE,EAChB,IAAI,EACJ,IAAI,CAAC,gBAAgB,CACtB,CAAC;QACF,MAAM,MAAM,GAAG,IAAA,yBAAgB,EAC7B,aAAa,EACb,IAAI,CAAC,eAAe,EACpB,OAAO,CACR,CAAC;QACF,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3C,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACjB,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACvB,CAAC;IAED,oBAAoB,CAAC,GAAW;QAC9B,MAAM,gBAAgB,GAAG,IAAA,mBAAU,EAAC,MAAM,EAAE,IAAI,CAAC,mBAAmB,CAAC,CAAC;QACtE,OAAO,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,eAAe,CACb,cAAsB,EACtB,eAAuB,EACvB,IAAY,EACZ,WAAmB;QAEnB,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACjC,OAAO,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAC/B,OAAO,CAAC,aAAa,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;QAC1C,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QAEjE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5C,OAAO,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC;QAC/B,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,mBAAmB,CAAC,GAAW,EAAE,GAAG,OAAiB;QACnD,MAAM,eAAe,GAAG,IAAA,mBAAU,EAAC,MAAM,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACpE,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QAE1B,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACjE,CAAC;CACF;AArLD,oCAqLC;AAED,MAAM,cAAc,GAAG,CAAC,CAAC;AAEzB,SAAS,aAAa,CAAC,MAAc,EAAE,QAAgB,EAAE,OAAe;IACtE,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAA,wBAAe,EAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC5E,MAAM,IAAI,+BAAuB,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC","sourcesContent":["import {\n createCipheriv,\n createDecipheriv,\n createHmac,\n timingSafeEqual,\n} from \"crypto\";\n\nimport { CipherAesBase } from \".\";\nimport type { RtcpHeader } from \"../../rtcp/header\";\nimport type { RtpHeader } from \"../../rtp/rtp\";\nimport { SrtpAuthenticationError } from \"../error\";\nimport {\n finalizeSrtpRtpHeader,\n parseSrtcpHeader,\n parseSrtpRtpHeader,\n} from \"../packet\";\n\nexport class CipherAesCtr extends CipherAesBase {\n readonly authTagLength = 10;\n\n constructor(\n srtpSessionKey: Buffer,\n srtpSessionSalt: Buffer,\n srtcpSessionKey: Buffer,\n srtcpSessionSalt: Buffer,\n private srtpSessionAuthTag: Buffer,\n private srtcpSessionAuthTag: Buffer,\n ) {\n super(srtpSessionKey, srtpSessionSalt, srtcpSessionKey, srtcpSessionSalt);\n }\n\n encryptRtp(header: RtpHeader, payload: Buffer, rolloverCounter: number) {\n const headerBuffer = header.serialize(header.serializeSize);\n\n const counter = this.generateCounter(\n header.sequenceNumber,\n rolloverCounter,\n header.ssrc,\n this.srtpSessionSalt,\n );\n\n const cipher = createCipheriv(\"aes-128-ctr\", this.srtpSessionKey, counter);\n const enc = cipher.update(payload);\n\n const authTag = this.generateSrtpAuthTag(\n rolloverCounter,\n headerBuffer,\n enc,\n );\n return Buffer.concat([headerBuffer, enc, authTag]);\n }\n\n decryptRtp(\n cipherText: Buffer,\n rolloverCounter: number,\n header = parseSrtpRtpHeader(cipherText, this.authTagLength),\n ): [Buffer, RtpHeader] {\n const authTagOffset = cipherText.length - this.authTagLength;\n const encryptedPacket = cipherText.subarray(0, authTagOffset);\n const actualAuthTag = cipherText.subarray(authTagOffset);\n\n const expectedAuthTag = this.generateSrtpAuthTag(\n rolloverCounter,\n encryptedPacket.subarray(0, header.payloadOffset),\n encryptedPacket.subarray(header.payloadOffset),\n );\n assertAuthTag(\n actualAuthTag,\n expectedAuthTag,\n \"Failed to authenticate SRTP packet\",\n );\n\n const counter = this.generateCounter(\n header.sequenceNumber,\n rolloverCounter,\n header.ssrc,\n this.srtpSessionSalt,\n );\n const cipher = createDecipheriv(\n \"aes-128-ctr\",\n this.srtpSessionKey,\n counter,\n );\n const payload = encryptedPacket.subarray(header.payloadOffset);\n const buf = cipher.update(payload);\n\n const dst = Buffer.concat([\n encryptedPacket.subarray(0, header.payloadOffset),\n buf,\n ]);\n\n return [\n dst,\n finalizeSrtpRtpHeader(header, dst, \"Failed to authenticate SRTP packet\"),\n ];\n }\n\n encryptRTCP(rtcpPacket: Buffer, srtcpIndex: number): Buffer {\n let out = Buffer.from(rtcpPacket);\n const ssrc = out.readUInt32BE(4);\n\n const counter = this.generateCounter(\n srtcpIndex & 0xffff,\n srtcpIndex >> 16,\n ssrc,\n this.srtcpSessionSalt,\n );\n const cipher = createCipheriv(\"aes-128-ctr\", this.srtcpSessionKey, counter);\n // Encrypt everything after header\n const buf = cipher.update(out.slice(8));\n buf.copy(out, 8);\n out = Buffer.concat([out, Buffer.alloc(4)]);\n out.writeUInt32BE(srtcpIndex, out.length - 4);\n out[out.length - 4] |= 0x80;\n const authTag = this.generateSrtcpAuthTag(out);\n out = Buffer.concat([out, authTag]);\n\n return out;\n }\n\n decryptRTCP(encrypted: Buffer): [Buffer, RtcpHeader] {\n const header = parseSrtcpHeader(\n encrypted,\n this.authTagLength,\n srtcpIndexSize,\n );\n\n const tailOffset = encrypted.length - (this.authTagLength + srtcpIndexSize);\n const authenticatedPortion = encrypted.subarray(\n 0,\n encrypted.length - this.authTagLength,\n );\n const actualTag = encrypted.subarray(encrypted.length - this.authTagLength);\n const expectedTag = this.generateSrtcpAuthTag(authenticatedPortion);\n assertAuthTag(\n actualTag,\n expectedTag,\n \"Failed to authenticate SRTCP packet\",\n );\n\n const out = Buffer.from(encrypted).slice(0, tailOffset);\n\n const isEncrypted = encrypted[tailOffset] >>> 7;\n if (isEncrypted === 0) return [out, header];\n\n let srtcpIndex = encrypted.readUInt32BE(tailOffset);\n srtcpIndex &= ~(1 << 31);\n\n const ssrc = encrypted.readUInt32BE(4);\n\n const counter = this.generateCounter(\n srtcpIndex & 0xffff,\n srtcpIndex >> 16,\n ssrc,\n this.srtcpSessionSalt,\n );\n const cipher = createDecipheriv(\n \"aes-128-ctr\",\n this.srtcpSessionKey,\n counter,\n );\n const buf = cipher.update(out.subarray(8));\n buf.copy(out, 8);\n return [out, header];\n }\n\n generateSrtcpAuthTag(buf: Buffer) {\n const srtcpSessionAuth = createHmac(\"sha1\", this.srtcpSessionAuthTag);\n return srtcpSessionAuth.update(buf).digest().slice(0, 10);\n }\n\n generateCounter(\n sequenceNumber: number,\n rolloverCounter: number,\n ssrc: number,\n sessionSalt: Buffer,\n ) {\n const counter = Buffer.alloc(16);\n counter.writeUInt32BE(ssrc, 4);\n counter.writeUInt32BE(rolloverCounter, 8);\n counter.writeUInt32BE(Number(BigInt(sequenceNumber) << 16n), 12);\n\n for (let i = 0; i < sessionSalt.length; i++) {\n counter[i] ^= sessionSalt[i];\n }\n return counter;\n }\n\n generateSrtpAuthTag(roc: number, ...buffers: Buffer[]) {\n const srtpSessionAuth = createHmac(\"sha1\", this.srtpSessionAuthTag);\n const rocRaw = Buffer.alloc(4);\n rocRaw.writeUInt32BE(roc);\n\n for (const buf of buffers) {\n srtpSessionAuth.update(buf);\n }\n return srtpSessionAuth.update(rocRaw).digest().subarray(0, 10);\n }\n}\n\nconst srtcpIndexSize = 4;\n\nfunction assertAuthTag(actual: Buffer, expected: Buffer, message: string) {\n if (actual.length !== expected.length || !timingSafeEqual(actual, expected)) {\n throw new SrtpAuthenticationError(message);\n }\n}\n"]}
|