Browse Source

Initial encryption support

tags/docs-0.9
RogueException 9 years ago
parent
commit
7ab708a43f
7 changed files with 58 additions and 6 deletions
  1. +6
    -0
      src/Discord.Net.Net45/Discord.Net.csproj
  2. BIN
      src/Discord.Net.Net45/lib/libsodium.dll
  3. +1
    -1
      src/Discord.Net/Audio/Opus.cs
  4. +15
    -0
      src/Discord.Net/Audio/Sodium.cs
  5. +5
    -1
      src/Discord.Net/DiscordClientConfig.cs
  6. +31
    -4
      src/Discord.Net/WebSockets/Voice/VoiceWebSocket.cs
  7. BIN
      src/Discord.Net/lib/libsodium.dll

+ 6
- 0
src/Discord.Net.Net45/Discord.Net.csproj View File

@@ -62,6 +62,9 @@
<Content Include="lib\libopus.so">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="lib\libsodium.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="lib\opus.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -101,6 +104,9 @@
<Compile Include="..\Discord.Net\Audio\OpusEncoder.cs">
<Link>Audio\OpusEncoder.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Audio\Sodium.cs">
<Link>Audio\Sodium.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Collections\AsyncCollection.cs">
<Link>Collections\AsyncCollection.cs</Link>
</Compile>


BIN
src/Discord.Net.Net45/lib/libsodium.dll View File


+ 1
- 1
src/Discord.Net/Audio/Opus.cs View File

@@ -3,7 +3,7 @@ using System.Runtime.InteropServices;

namespace Discord.Audio
{
internal unsafe class Opus
internal static unsafe class Opus
{
[DllImport("lib/opus", EntryPoint = "opus_encoder_create", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr CreateEncoder(int Fs, int channels, int application, out Error error);


+ 15
- 0
src/Discord.Net/Audio/Sodium.cs View File

@@ -0,0 +1,15 @@
using System.Runtime.InteropServices;

namespace Discord.Audio
{
internal static class Sodium
{
[DllImport("lib/libsodium", EntryPoint = "crypto_stream_xor", CallingConvention = CallingConvention.Cdecl)]
private static extern int StreamXOR(byte[] output, byte[] msg, long msgLength, byte[] nonce, byte[] secret);

public static int Encrypt(byte[] buffer, int inputLength, byte[] output, byte[] nonce, byte[] secret)
{
return StreamXOR(output, buffer, inputLength, nonce, secret);
}
}
}

+ 5
- 1
src/Discord.Net/DiscordClientConfig.cs View File

@@ -4,7 +4,7 @@ namespace Discord
{
public class DiscordClientConfig
{
/// <summary> Specifies the minimum log level severity that will be sent to the LogMessage event. Warning: setting this to verbose will hinder performance but should help investigate any internal issues. </summary>
/// <summary> Specifies the minimum log level severity that will be sent to the LogMessage event. Warning: setting this to debug will really hurt performance but should help investigate any internal issues. </summary>
public LogMessageSeverity LogLevel { get { return _logLevel; } set { SetValue(ref _logLevel, value); } }
private LogMessageSeverity _logLevel = LogMessageSeverity.Info;

@@ -36,8 +36,12 @@ namespace Discord
/// <summary> (Experimental) Enables the voice websocket and UDP client. This option requires the opus .dll or .so be in the local lib/ folder. </summary>
public bool EnableVoice { get { return _enableVoice; } set { SetValue(ref _enableVoice, value); } }
private bool _enableVoice = false;
/// <summary> (Experimental) Enables the voice websocket and UDP client. This option requires the libsodium .dll or .so be in the local lib/ folder. </summary>
public bool EnableVoiceEncryption { get { return _enableVoiceEncryption; } set { SetValue(ref _enableVoiceEncryption, value); } }
private bool _enableVoiceEncryption = false;
#else
internal bool EnableVoice => false;
internal bool EnableVoiceEncryption => false;
#endif
/// <summary> (Experimental) Enables or disables the internal message queue. This will allow SendMessage to return immediately and handle messages internally. Messages will set the IsQueued and HasFailed properties to show their progress. </summary>
public bool UseMessageQueue { get { return _useMessageQueue; } set { SetValue(ref _useMessageQueue, value); } }


+ 31
- 4
src/Discord.Net/WebSockets/Voice/VoiceWebSocket.cs View File

@@ -33,7 +33,7 @@ namespace Discord.WebSockets.Voice
private byte[] _secretKey;
private ushort _sequence;
private byte[] _encodingBuffer;
private string _serverId, _userId, _sessionId, _token;
private string _serverId, _userId, _sessionId, _token, _encryptionMode;

#if USE_THREAD
private Thread _sendThread;
@@ -213,12 +213,18 @@ namespace Discord.WebSockets.Voice
Stopwatch sw = Stopwatch.StartNew();

byte[] rtpPacket = new byte[_encodingBuffer.Length + 12];
byte[] nonce = null;
rtpPacket[0] = 0x80; //Flags;
rtpPacket[1] = 0x78; //Payload Type
rtpPacket[8] = (byte)((_ssrc >> 24) & 0xFF);
rtpPacket[9] = (byte)((_ssrc >> 16) & 0xFF);
rtpPacket[10] = (byte)((_ssrc >> 8) & 0xFF);
rtpPacket[11] = (byte)((_ssrc >> 0) & 0xFF);
if (_isEncrypted)
{
nonce = new byte[24];
Buffer.BlockCopy(rtpPacket, 0, nonce, 0, 12);
}

while (!cancelToken.IsCancellationRequested)
{
@@ -238,6 +244,13 @@ namespace Discord.WebSockets.Voice
rtpPacket[5] = (byte)((timestamp >> 16) & 0xFF);
rtpPacket[6] = (byte)((timestamp >> 8) & 0xFF);
rtpPacket[7] = (byte)((timestamp >> 0) & 0xFF);
if (_isEncrypted)
{
Buffer.BlockCopy(rtpPacket, 2, nonce, 2, 6); //Update nonce
int ret = Sodium.Encrypt(packet, packet.Length, packet, nonce, _secretKey);
if (ret != 0)
continue;
}
Buffer.BlockCopy(packet, 0, rtpPacket, 12, packet.Length);
#if USE_THREAD
_udp.Send(rtpPacket, packet.Length + 12);
@@ -298,8 +311,22 @@ namespace Discord.WebSockets.Voice
_heartbeatInterval = payload.HeartbeatInterval;
_ssrc = payload.SSRC;
_endpoint = new IPEndPoint((await Dns.GetHostAddressesAsync(Host.Replace("wss://", "")).ConfigureAwait(false)).FirstOrDefault(), payload.Port);
//_mode = payload.Modes.LastOrDefault();
_isEncrypted = !payload.Modes.Contains("plain");
if (_client.Config.EnableVoiceEncryption)
{
if (payload.Modes.Contains(EncryptedMode))
{
_encryptionMode = EncryptedMode;
_isEncrypted = true;
}
else
throw new InvalidOperationException("Unexpected encryption format.");
}
else
{
_encryptionMode = UnencryptedMode;
_isEncrypted = false;
}
_udp.Connect(_endpoint);

_sequence = (ushort)_rand.Next(0, ushort.MaxValue);
@@ -361,7 +388,7 @@ namespace Discord.WebSockets.Voice
var login2 = new Login2Command();
login2.Payload.Protocol = "udp";
login2.Payload.SocketData.Address = ip;
login2.Payload.SocketData.Mode = _isEncrypted ? EncryptedMode : UnencryptedMode;
login2.Payload.SocketData.Mode = _encryptionMode;
login2.Payload.SocketData.Port = port;
QueueMessage(login2);
}


BIN
src/Discord.Net/lib/libsodium.dll View File


Loading…
Cancel
Save