From d27e86915ee81164b1b765dedf2bb78b0a8a62fe Mon Sep 17 00:00:00 2001 From: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> Date: Wed, 20 Sep 2023 13:21:54 -0700 Subject: [PATCH] Add encryption unit tests (#2243) --- azure-pipelines/build.yml | 14 ++ build.json | 3 + sqltoolsservice.sln | 9 ++ .../EncryptionUtilsTests.cs | 141 ++++++++++++++++++ .../GlobalUsings.cs | 7 + ...t.SqlTools.Authentication.UnitTests.csproj | 34 +++++ 6 files changed, 208 insertions(+) create mode 100644 test/Microsoft.SqlTools.Authentication.UnitTests/EncryptionUtilsTests.cs create mode 100644 test/Microsoft.SqlTools.Authentication.UnitTests/GlobalUsings.cs create mode 100644 test/Microsoft.SqlTools.Authentication.UnitTests/Microsoft.SqlTools.Authentication.UnitTests.csproj diff --git a/azure-pipelines/build.yml b/azure-pipelines/build.yml index 6be25f6f..ea914e9a 100644 --- a/azure-pipelines/build.yml +++ b/azure-pipelines/build.yml @@ -88,6 +88,12 @@ steps: command: restore projects: test/Microsoft.Kusto.ServiceLayer.UnitTests +- task: DotNetCoreCLI@2 + displayName: 'dotnet restore test/Microsoft.SqlTools.Authentication.UnitTests' + inputs: + command: restore + projects: test/Microsoft.SqlTools.Authentication.UnitTests + - task: DotNetCoreCLI@2 displayName: 'dotnet test test/Microsoft.SqlTools.ServiceLayer.UnitTests' inputs: @@ -104,6 +110,14 @@ steps: testRunTitle: Kusto.ServiceLayer.UnitTests arguments: '--configuration $(buildConfiguration) --collect "XPlat Code Coverage"' +- task: DotNetCoreCLI@2 + displayName: 'dotnet test test/Microsoft.SqlTools.Authentication.UnitTests' + inputs: + command: test + projects: test/Microsoft.SqlTools.Authentication.UnitTests + testRunTitle: SqlTools.Authentication.UnitTests + arguments: '--configuration $(buildConfiguration) --collect "XPlat Code Coverage"' + - script: | dotnet tool install -g dotnet-reportgenerator-globaltool reportgenerator -reports:$(Agent.TempDirectory)/**/coverage.cobertura.xml -targetdir:$(Agent.TempDirectory)/coverlet/reports -reporttypes:"Cobertura" diff --git a/build.json b/build.json index c657ca34..c309d5f4 100644 --- a/build.json +++ b/build.json @@ -14,6 +14,9 @@ "Microsoft.Kusto.ServiceLayer.UnitTests": [ "net7.0" ], + "Microsoft.SQlTools.Authentication.UnitTests": [ + "net7.0" + ], "Microsoft.SqlTools.ServiceLayer.TestEnvConfig": [ "net7.0" ], diff --git a/sqltoolsservice.sln b/sqltoolsservice.sln index 30025286..4769440b 100644 --- a/sqltoolsservice.sln +++ b/sqltoolsservice.sln @@ -101,6 +101,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.Migratio EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.Authentication", "src\Microsoft.SqlTools.Authentication\Microsoft.SqlTools.Authentication.csproj", "{2A32C3B6-3E9F-4A8E-BF98-59F9AEF6DAAC}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.Authentication.UnitTests", "test\Microsoft.SqlTools.Authentication.UnitTests\Microsoft.SqlTools.Authentication.UnitTests.csproj", "{D3960B1C-3191-4A0B-AD0C-3D5D0FFF60A9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -246,6 +248,12 @@ Global {2A32C3B6-3E9F-4A8E-BF98-59F9AEF6DAAC}.Integration|Any CPU.Build.0 = Debug|Any CPU {2A32C3B6-3E9F-4A8E-BF98-59F9AEF6DAAC}.Release|Any CPU.ActiveCfg = Release|Any CPU {2A32C3B6-3E9F-4A8E-BF98-59F9AEF6DAAC}.Release|Any CPU.Build.0 = Release|Any CPU + {D3960B1C-3191-4A0B-AD0C-3D5D0FFF60A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D3960B1C-3191-4A0B-AD0C-3D5D0FFF60A9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D3960B1C-3191-4A0B-AD0C-3D5D0FFF60A9}.Integration|Any CPU.ActiveCfg = Debug|Any CPU + {D3960B1C-3191-4A0B-AD0C-3D5D0FFF60A9}.Integration|Any CPU.Build.0 = Debug|Any CPU + {D3960B1C-3191-4A0B-AD0C-3D5D0FFF60A9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D3960B1C-3191-4A0B-AD0C-3D5D0FFF60A9}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -275,6 +283,7 @@ Global {22DB0C12-6848-4503-AD1C-DAD6A1D631AE} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} {5C7F4DAC-F794-4C21-A031-DCAAFAF3C0A9} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4} {2A32C3B6-3E9F-4A8E-BF98-59F9AEF6DAAC} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} + {D3960B1C-3191-4A0B-AD0C-3D5D0FFF60A9} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {B31CDF4B-2851-45E5-8C5F-BE97125D9DD8} diff --git a/test/Microsoft.SqlTools.Authentication.UnitTests/EncryptionUtilsTests.cs b/test/Microsoft.SqlTools.Authentication.UnitTests/EncryptionUtilsTests.cs new file mode 100644 index 00000000..442dabd1 --- /dev/null +++ b/test/Microsoft.SqlTools.Authentication.UnitTests/EncryptionUtilsTests.cs @@ -0,0 +1,141 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Authentication.Utility; + +namespace Microsoft.SqlTools.Authentication.UnitTests +{ + [TestFixture] + public class EncryptionUtilsTests + { + [Test] + public void AesEncryptDecrypt_ValidData_EncryptionDecryptionSuccessful() + { + // Arrange + byte[] originalData = new byte[] { 0, 1, 2, 3, 4 }; + byte[] key = new byte[32]; // 256-bit key + byte[] iv = new byte[16]; // 128-bit IV + + // Act + byte[] encryptedData = EncryptionUtils.AesEncrypt(originalData, key, iv); + byte[] decryptedData = EncryptionUtils.AesDecrypt(encryptedData, key, iv); + + // Assert + CollectionAssert.AreEqual(originalData, decryptedData); + } + + [Test] + public void AesEncrypt_PaddingIsCorrectlyAdded() + { + // Arrange + byte[] originalData = new byte[] { 0, 1, 2, 3, 4, 5 }; + byte[] key = new byte[32]; // 256-bit key + byte[] iv = new byte[16]; // 128-bit IV + + // Act + byte[] encryptedData = EncryptionUtils.AesEncrypt(originalData, key, iv); + + // Assert + // Check if the encrypted data length is a multiple of the block size (128 bits or 16 bytes) + int blockSizeInBytes = 16; + int expectedPaddedLength = ((originalData.Length / blockSizeInBytes) + 1) * blockSizeInBytes; + Assert.AreEqual(expectedPaddedLength, encryptedData.Length); + } + + [Test] + public void AesEncryptDecrypt_LargeData_PaddingIsCorrectlyAdded_TransformationIsSuccessful() + { + // Arrange + byte[] originalData = new byte[2096]; + for (int i = 0; i < 2096; i++) + { + originalData[i] = (byte)Random.Shared.Next(0, 4); + } + byte[] key = new byte[32]; // 256-bit key + byte[] iv = new byte[16]; // 128-bit IV + + // Act + byte[] encryptedData = EncryptionUtils.AesEncrypt(originalData, key, iv); + + // Assert + // Check if the encrypted data length is a multiple of the block size (128 bits or 16 bytes) + int blockSizeInBytes = 16; + int expectedPaddedLength = ((originalData.Length / blockSizeInBytes) + 1) * blockSizeInBytes; + Assert.AreEqual(expectedPaddedLength, encryptedData.Length); + + // Act + byte[] decryptedData = EncryptionUtils.AesDecrypt(encryptedData, key, iv); + + //Assert + CollectionAssert.AreEqual(originalData, decryptedData); + } + + [Test] + public void AesEncrypt_NullPlainText_ThrowsArgumentNullException() + { + // Arrange + byte[] key = new byte[32]; // 256-bit key + byte[] iv = new byte[16]; // 128-bit IV + + // Act + Assert.Throws(() => EncryptionUtils.AesEncrypt(null, key, iv)); + } + + [Test] + public void AesEncrypt_NullIV_ThrowsArgumentNullException() + { + // Arrange + byte[] key = new byte[32]; // 256-bit key + byte[] data = new byte[32]; // 256-bit data + + // Act + Assert.Throws(() => EncryptionUtils.AesEncrypt(data, key, null)); + } + + [Test] + public void AesEncrypt_NullKey_ThrowsArgumentNullException() + { + // Arrange + byte[] iv = new byte[16]; // 128-bit IV + byte[] data = new byte[32]; // 256-bit data + + // Act + Assert.Throws(() => EncryptionUtils.AesEncrypt(data, null, iv)); + } + + [Test] + public void AesDecrypt_NullCipherText_ThrowsArgumentNullException() + { + // Arrange + byte[] key = new byte[32]; // 256-bit key + byte[] iv = new byte[16]; // 128-bit IV + + // Act + Assert.Throws(() => EncryptionUtils.AesDecrypt(null, key, iv)); + } + + [Test] + public void AesDecrypt_NullIV_ThrowsArgumentNullException() + { + // Arrange + byte[] key = new byte[32]; // 256-bit key + byte[] data = new byte[32]; // 256-bit data + + // Act + Assert.Throws(() => EncryptionUtils.AesDecrypt(data, key, null)); + } + + [Test] + public void AesDecrypt_NullKey_ThrowsArgumentNullException() + { + // Arrange + byte[] iv = new byte[16]; // 128-bit IV + byte[] data = new byte[32]; // 256-bit data + + // Act + Assert.Throws(() => EncryptionUtils.AesDecrypt(data, null, iv)); + } + } +} diff --git a/test/Microsoft.SqlTools.Authentication.UnitTests/GlobalUsings.cs b/test/Microsoft.SqlTools.Authentication.UnitTests/GlobalUsings.cs new file mode 100644 index 00000000..a6e68c1e --- /dev/null +++ b/test/Microsoft.SqlTools.Authentication.UnitTests/GlobalUsings.cs @@ -0,0 +1,7 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +global using System; +global using NUnit.Framework; diff --git a/test/Microsoft.SqlTools.Authentication.UnitTests/Microsoft.SqlTools.Authentication.UnitTests.csproj b/test/Microsoft.SqlTools.Authentication.UnitTests/Microsoft.SqlTools.Authentication.UnitTests.csproj new file mode 100644 index 00000000..6b529a3a --- /dev/null +++ b/test/Microsoft.SqlTools.Authentication.UnitTests/Microsoft.SqlTools.Authentication.UnitTests.csproj @@ -0,0 +1,34 @@ + + + Exe + false + $(DefineConstants);NETCOREAPP1_0;TRACE + false + + + + $(NoWarn);CS8795 + net7.0 + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + +