diff --git a/src/Discord.Net/Audio/Sodium/SecretBox.cs b/src/Discord.Net/Audio/Sodium/SecretBox.cs index ba4bc2e62..4f4de6fdf 100644 --- a/src/Discord.Net/Audio/Sodium/SecretBox.cs +++ b/src/Discord.Net/Audio/Sodium/SecretBox.cs @@ -1,9 +1,67 @@ -using System.Runtime.InteropServices; +using System; +using System.Runtime.InteropServices; namespace Discord.Audio { public unsafe static class SecretBox { + // from crypto_secretbox.h and crypto_secretbox_xsalsa20poly1305.h + private const uint crypto_secretbox_KEYBYTES = 32U; + private const uint crypto_secretbox_NONCEBYTES = 24U; + private const uint crypto_secretbox_MACBYTES = 16U; + + [DllImport("libsodium", CallingConvention = CallingConvention.Cdecl)] + private static extern int crypto_secretbox_easy( + [Out] byte[] c, // ciphertext + [In] byte[] m, // message + [MarshalAs(UnmanagedType.U8)] ulong mlen, // length of message + [In] byte[] n, // nonce + [In] byte[] k // key + ); + + [DllImport("libsodium", CallingConvention = CallingConvention.Cdecl)] + private static extern int crypto_secretbox_open_easy( + [Out] byte[] m, // message + [In] byte[] c, // ciphertext + [MarshalAs(UnmanagedType.U8)] ulong clen, // length of ciphertext + [In] byte[] n, // nonce + [In] byte[] k // key + ); + + // Both of the above functions return 0 on success, -1 on error + + public static void Encrypt(byte[] input, int inputOffset, ulong inputLength, byte[] output, int outputOffset, byte[] nonce, byte[] secret) + { + byte[] _input = new byte[inputLength]; + Buffer.BlockCopy(input, inputOffset, _input, 0, (int)inputLength); // TODO: this will probably cause an overflow or throw an exception... + + byte[] _output = new byte[crypto_secretbox_MACBYTES + inputLength]; + int result = crypto_secretbox_easy(_output, _input, inputLength, nonce, secret); + + if (result == -1) + throw new InvalidOperationException("Failed to encrypt the provided payload"); + + Buffer.BlockCopy(_output, 0, output, outputOffset, _output.Length); + } + + public static void Decrypt(byte[] input, int inputOffset, ulong inputLength, byte[] output, int outputOffset, byte[] nonce, byte[] secret) + { + if (inputLength < crypto_secretbox_MACBYTES) + throw new ArgumentException($"the length of the input arary must be greater than {crypto_secretbox_MACBYTES} bytes", "inputLength"); + + byte[] _input = new byte[inputLength]; + Buffer.BlockCopy(input, inputOffset, _input, 0, (int)inputLength); // TODO: this will also probably overflow or throw an exception + + byte[] _output = new byte[inputLength - crypto_secretbox_MACBYTES]; + int result = crypto_secretbox_open_easy(_output, _input, inputLength, nonce, secret); + + if (result == -1) + throw new InvalidOperationException("Failed to verify the decrypted payload"); + + Buffer.BlockCopy(_output, 0, output, outputOffset, _output.Length); + } + + /* I kept the old code here to refer to in case it is needed [DllImport("libsodium", EntryPoint = "crypto_secretbox_easy", CallingConvention = CallingConvention.Cdecl)] private static extern int SecretBoxEasy(byte* output, byte* input, long inputLength, byte[] nonce, byte[] secret); [DllImport("libsodium", EntryPoint = "crypto_secretbox_open_easy", CallingConvention = CallingConvention.Cdecl)] @@ -21,5 +79,6 @@ namespace Discord.Audio fixed (byte* outPtr = output) return SecretBoxOpenEasy(outPtr + outputOffset, inPtr + inputOffset, inputLength, nonce, secret); } + */ } } diff --git a/src/Discord.Net/Audio/Streams/RTPReadStream.cs b/src/Discord.Net/Audio/Streams/RTPReadStream.cs index 4bf7f5e1b..67bbd5734 100644 --- a/src/Discord.Net/Audio/Streams/RTPReadStream.cs +++ b/src/Discord.Net/Audio/Streams/RTPReadStream.cs @@ -32,7 +32,7 @@ namespace Discord.Audio public override void Write(byte[] buffer, int offset, int count) { Buffer.BlockCopy(buffer, 0, _nonce, 0, 12); - count = SecretBox.Decrypt(buffer, offset, count, _buffer, 0, _nonce, _secretKey); + SecretBox.Decrypt(buffer, offset, (ulong)count, _buffer, 0, _nonce, _secretKey); var newBuffer = new byte[count]; Buffer.BlockCopy(_buffer, 0, newBuffer, 0, count); _queuedData.Add(newBuffer); diff --git a/src/Discord.Net/Audio/Streams/RTPWriteStream.cs b/src/Discord.Net/Audio/Streams/RTPWriteStream.cs index f871ded0d..ecb25e348 100644 --- a/src/Discord.Net/Audio/Streams/RTPWriteStream.cs +++ b/src/Discord.Net/Audio/Streams/RTPWriteStream.cs @@ -46,7 +46,7 @@ namespace Discord.Audio } Buffer.BlockCopy(buffer, 0, _nonce, 0, 12); - count = SecretBox.Encrypt(buffer, offset, count, _buffer, 12, _nonce, _secretKey); + SecretBox.Encrypt(buffer, offset, (ulong)count, _buffer, 12, _nonce, _secretKey); _audioClient.Send(_buffer, count); }