mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-10 00:23:30 +01:00
voice: support xsalsa20_poly1305_lite and xsalsa20_poly1305_suffix
This commit is contained in:
@@ -8,6 +8,12 @@ const EventEmitter = require('events');
|
||||
const { Error } = require('../../errors');
|
||||
const PlayInterface = require('./util/PlayInterface');
|
||||
|
||||
const SUPPORTED_MODES = [
|
||||
'xsalsa20_poly1305_lite',
|
||||
'xsalsa20_poly1305_suffix',
|
||||
'xsalsa20_poly1305',
|
||||
];
|
||||
|
||||
/**
|
||||
* Represents a connection to a guild's voice server.
|
||||
* ```js
|
||||
@@ -382,9 +388,16 @@ class VoiceConnection extends EventEmitter {
|
||||
* @param {Object} data The received data
|
||||
* @private
|
||||
*/
|
||||
onReady({ port, ssrc, ip }) {
|
||||
onReady({ port, ssrc, ip, modes }) {
|
||||
this.authentication.port = port;
|
||||
this.authentication.ssrc = ssrc;
|
||||
for (let mode of modes) {
|
||||
if (SUPPORTED_MODES.includes(mode)) {
|
||||
this.authentication.encryptionMode = mode;
|
||||
this.emit('debug', `Selecting the ${mode} mode`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.sockets.udp.createUDPSocket(ip);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ const FRAME_LENGTH = 20;
|
||||
const CHANNELS = 2;
|
||||
const TIMESTAMP_INC = (48000 / 100) * CHANNELS;
|
||||
|
||||
const MAX_NONCE_SIZE = (2 ** 32) - 1;
|
||||
const nonce = Buffer.alloc(24);
|
||||
nonce.fill(0);
|
||||
|
||||
/**
|
||||
* @external WritableStream
|
||||
@@ -42,6 +42,9 @@ class StreamDispatcher extends Writable {
|
||||
this.streamOptions = streamOptions;
|
||||
this.streams = streams;
|
||||
|
||||
this._nonce = 0;
|
||||
this._nonceBuffer = Buffer.alloc(24);
|
||||
|
||||
/**
|
||||
* The time that the stream was paused at (null if not paused)
|
||||
* @type {?number}
|
||||
@@ -217,9 +220,26 @@ class StreamDispatcher extends Writable {
|
||||
this._sendPacket(this._createPacket(this._sdata.sequence, this._sdata.timestamp, chunk));
|
||||
}
|
||||
|
||||
_encrypt(buffer) {
|
||||
const { secretKey, encryptionMode } = this.player.voiceConnection.authentication;
|
||||
if (encryptionMode === 'xsalsa20_poly1305_lite') {
|
||||
this._nonce++;
|
||||
if (this._nonce > MAX_NONCE_SIZE) this._nonce = 0;
|
||||
this._nonceBuffer.writeUInt32BE(this._nonce, 0);
|
||||
return [
|
||||
secretbox.methods.close(buffer, this._nonceBuffer, secretKey),
|
||||
this._nonceBuffer.slice(0, 4),
|
||||
];
|
||||
} else if (encryptionMode === 'xsalsa20_poly1305_suffix') {
|
||||
const random = secretbox.methods.random(24);
|
||||
return [secretbox.methods.close(buffer, random, secretKey), random];
|
||||
} else {
|
||||
return [secretbox.methods.close(buffer, nonce, secretKey)];
|
||||
}
|
||||
}
|
||||
|
||||
_createPacket(sequence, timestamp, buffer) {
|
||||
const packetBuffer = Buffer.alloc(buffer.length + 28);
|
||||
packetBuffer.fill(0);
|
||||
const packetBuffer = Buffer.alloc(12);
|
||||
packetBuffer[0] = 0x80;
|
||||
packetBuffer[1] = 0x78;
|
||||
|
||||
@@ -228,10 +248,7 @@ class StreamDispatcher extends Writable {
|
||||
packetBuffer.writeUIntBE(this.player.voiceConnection.authentication.ssrc, 8, 4);
|
||||
|
||||
packetBuffer.copy(nonce, 0, 0, 12);
|
||||
buffer = secretbox.methods.close(buffer, nonce, this.player.voiceConnection.authentication.secretKey);
|
||||
for (let i = 0; i < buffer.length; i++) packetBuffer[i + 12] = buffer[i];
|
||||
|
||||
return packetBuffer;
|
||||
return Buffer.concat([packetBuffer, ...this._encrypt(buffer, sequence)]);
|
||||
}
|
||||
|
||||
_sendPacket(packet) {
|
||||
|
||||
@@ -104,7 +104,7 @@ class VoiceConnectionUDPClient extends EventEmitter {
|
||||
data: {
|
||||
address: packet.address,
|
||||
port: packet.port,
|
||||
mode: 'xsalsa20_poly1305',
|
||||
mode: this.voiceConnection.authentication.encryptionMode,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2,14 +2,17 @@ const libs = {
|
||||
sodium: sodium => ({
|
||||
open: sodium.api.crypto_secretbox_open_easy,
|
||||
close: sodium.api.crypto_secretbox_easy,
|
||||
random: n => sodium.randombytes_buf(n),
|
||||
}),
|
||||
'libsodium-wrappers': sodium => ({
|
||||
open: sodium.crypto_secretbox_open_easy,
|
||||
close: sodium.crypto_secretbox_easy,
|
||||
random: n => sodium.randombytes_buf(n),
|
||||
}),
|
||||
tweetnacl: tweetnacl => ({
|
||||
open: tweetnacl.secretbox.open,
|
||||
close: tweetnacl.secretbox,
|
||||
random: n => tweetnacl.randomBytes(n),
|
||||
}),
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user