From 4d73b1af73f2346b53446bef0b9d8c6de4a712d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Dugr=C3=A9?= Date: Mon, 18 Nov 2024 15:47:47 -0500 Subject: [PATCH 01/15] Initial commit --- .gitignore | 3 + XTS.NET.csproj | 18 + XTS.NET.sln | 28 + src/XTS.cs | 237 ++++ test_case_gen/.gitignore | 2 + test_case_gen/README.md | 18 + test_case_gen/requirements.txt | 1 + test_case_gen/template.cs | 33 + test_case_gen/test_case_gen.py | 58 + tests/GlobalUsings.cs | 2 + tests/IeeeVectorsTests.cs | 2160 ++++++++++++++++++++++++++++++++ tests/Tests.cs | 118 ++ tests/XTS.NET.Tests.csproj | 27 + 13 files changed, 2705 insertions(+) create mode 100644 .gitignore create mode 100644 XTS.NET.csproj create mode 100644 XTS.NET.sln create mode 100644 src/XTS.cs create mode 100644 test_case_gen/.gitignore create mode 100644 test_case_gen/README.md create mode 100644 test_case_gen/requirements.txt create mode 100644 test_case_gen/template.cs create mode 100644 test_case_gen/test_case_gen.py create mode 100644 tests/GlobalUsings.cs create mode 100644 tests/IeeeVectorsTests.cs create mode 100644 tests/Tests.cs create mode 100644 tests/XTS.NET.Tests.csproj diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cfbfc32 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vs/ +**/bin/ +**/obj/ \ No newline at end of file diff --git a/XTS.NET.csproj b/XTS.NET.csproj new file mode 100644 index 0000000..b2dfc7c --- /dev/null +++ b/XTS.NET.csproj @@ -0,0 +1,18 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + diff --git a/XTS.NET.sln b/XTS.NET.sln new file mode 100644 index 0000000..9de33bf --- /dev/null +++ b/XTS.NET.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XTS.NET", "XTS.NET.csproj", "{DB2D8001-9562-4042-883D-69D4C75E647C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XTS.NET.Tests", "tests\XTS.NET.Tests.csproj", "{AE300E49-FCCD-45D6-A32C-6E133148DF02}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DB2D8001-9562-4042-883D-69D4C75E647C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DB2D8001-9562-4042-883D-69D4C75E647C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DB2D8001-9562-4042-883D-69D4C75E647C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DB2D8001-9562-4042-883D-69D4C75E647C}.Release|Any CPU.Build.0 = Release|Any CPU + {AE300E49-FCCD-45D6-A32C-6E133148DF02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AE300E49-FCCD-45D6-A32C-6E133148DF02}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AE300E49-FCCD-45D6-A32C-6E133148DF02}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AE300E49-FCCD-45D6-A32C-6E133148DF02}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/src/XTS.cs b/src/XTS.cs new file mode 100644 index 0000000..7e75a05 --- /dev/null +++ b/src/XTS.cs @@ -0,0 +1,237 @@ +using System; +using System.Numerics; +using System.Security.Cryptography; + +namespace XTS.NET; + +public static class XTS +{ + public static void EncryptXts(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum, int sectorSize) + { + SetupRawCipher(alg); + + // Set K1 and create encryptor + ICryptoTransform encryptor = alg.CreateEncryptor(key[..(key.Length / 2)].ToArray(), null); + + int nSectors = (buffer.Length - 1) / sectorSize + 1; + + int currentSectorSize = sectorSize; + // This for apply on each sectors + for (int i = 0; i < nSectors; i += 1) + { + // Last sector is likely shorter + if (i == nSectors - 1) + { + currentSectorSize = (buffer.Length - 1) % sectorSize + 1; + } + + // Encrypt the tweak + byte[] tweak = EncryptTweak(alg, key, sectorNum); + + // Process the sector + ProcessXtsSector(encryptor, buffer, i * sectorSize, currentSectorSize, tweak, false); + + // We advance the counter for the next sector + sectorNum += 1; + } + } + + public static void DecryptXts(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum, int sectorSize) + { + SetupRawCipher(alg); + + // Set K1 and create decryptor + ICryptoTransform encryptor = alg.CreateDecryptor(key[..(key.Length / 2)].ToArray(), null); + + int nSectors = (buffer.Length - 1) / sectorSize + 1; + + int currentSectorSize = sectorSize; + // This for apply on each sectors + for (int i = 0; i < nSectors; i += 1) + { + // Last sector is likely shorter + if (i == nSectors - 1) + { + currentSectorSize = (buffer.Length - 1) % sectorSize + 1; + } + + // Encrypt the tweak + byte[] tweak = EncryptTweak(alg, key, sectorNum); + + // Process the sector + ProcessXtsSector(encryptor, buffer, i * sectorSize, currentSectorSize, tweak, true); + + // We advance the counter for the next sector + sectorNum += 1; + } + } + + public static void EncryptXtsSector(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum) + { + SetupRawCipher(alg); + + // Set K1 and create encryptor + ICryptoTransform encryptor = alg.CreateEncryptor(key[..(key.Length / 2)].ToArray(), null); + + // Encrypt the tweak + byte[] tweak = EncryptTweak(alg, key, sectorNum); + + // Encrypt Sector + ProcessXtsSector(encryptor, buffer, 0, buffer.Length, tweak, false); + } + + public static void DecryptXtsSector(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum) + { + SetupRawCipher(alg); + + // Set K1 and create decryptor + ICryptoTransform decryptor = alg.CreateDecryptor(key[..(key.Length / 2)].ToArray(), null); + + // Encrypt the tweak + byte[] tweak = EncryptTweak(alg, key, sectorNum); + + // Decrypt Sector + ProcessXtsSector(decryptor, buffer, 0, buffer.Length, tweak, true); + } + + private static void ProcessXtsSector(ICryptoTransform alg, byte[] buffer, int bufferOffset, int bufferLength, Span tweak, bool decrypt) + { + int blockSize = alg.InputBlockSize; + int nFullBlocks = bufferLength / blockSize; + + if (bufferLength < blockSize) + { + throw new ArgumentException("You cannot encrypt less then a block in a sector using XTS"); + } + + for (int j = 0; j < nFullBlocks - 1; j += 1) + { + int blockStart = bufferOffset + j * blockSize; + TransformBlock(alg, buffer, blockStart, tweak); + + // Multiply tweak by two for next block + GaloisMultiplyByTwo(tweak); + } + + // If we decrypt and we need to do ciphertext stealing, we need to skip a GF multiplication here and roll back after + int remainingBytes = bufferLength - nFullBlocks * blockSize; + bool needsCiphertextStealing = remainingBytes > 0; + + if (decrypt && needsCiphertextStealing) + { + // We backup the tweak, re-multiply it and restore it after + byte[] oldTweak = tweak.ToArray(); + GaloisMultiplyByTwo(tweak); + + int blockStart = bufferOffset + (nFullBlocks - 1) * blockSize; + TransformBlock(alg, buffer, blockStart, tweak); + + tweak = oldTweak; + } + else + { + int blockStart = bufferOffset + (nFullBlocks - 1) * blockSize; + TransformBlock(alg, buffer, blockStart, tweak); + + if (needsCiphertextStealing) + { + // We will need another decryption after this + GaloisMultiplyByTwo(tweak); + } + } + + if (needsCiphertextStealing) + { + // We need to do ciphertext stealing since the sector size does not align with the blocksize + int previousBlockStart = bufferOffset + (nFullBlocks - 1) * blockSize; + int currentBlockStart = previousBlockStart + blockSize; + + Span bufferSpan = buffer.AsSpan(); + Span previousBlockSpan = bufferSpan[previousBlockStart..currentBlockStart]; + Span currentBlockSpan = bufferSpan[currentBlockStart..(bufferOffset + bufferLength)]; + + // Buffer last bytes + byte[] remainingBytesArray = currentBlockSpan.ToArray(); + + // We copy part of the previous ciphertext at the end + previousBlockSpan[..remainingBytes].CopyTo(currentBlockSpan); + + // We compute the last block on the previous block + // We only need to copy the start of the last block, as the end of the previous block is already there + remainingBytesArray.AsSpan().CopyTo(previousBlockSpan); + + TransformBlock(alg, buffer, previousBlockStart, tweak); + } + } + + private static byte[] EncryptTweak(SymmetricAlgorithm alg, ReadOnlySpan key, BigInteger sectorNum) + { + int blockSize = alg.BlockSize / 8; + + // Set K2 to create tweak encryptor + ICryptoTransform tweaker = alg.CreateEncryptor(key[(key.Length / 2)..].ToArray(), null); + + // Convert sector number to little endian block + byte[] tweak = sectorNum.ToByteArray(isUnsigned: true, isBigEndian: false); + Array.Resize(ref tweak, blockSize); + + // Encrypt tweak + tweaker.TransformBlock(tweak, 0, blockSize, tweak, 0); + + return tweak; + } + + private static void SetupRawCipher(SymmetricAlgorithm alg) + { + // Setup for raw cipher, without mode or padding + alg.Mode = CipherMode.ECB; + alg.Padding = PaddingMode.None; + } + + private static void TransformBlock(ICryptoTransform alg, byte[] buffer, int bufferOffset, ReadOnlySpan tweak) + { + // Get block size from the transform + int blockSize = alg.InputBlockSize; + + // Cast as span for easier manipulation + Span outputSpan = buffer.AsSpan()[bufferOffset..(bufferOffset + blockSize)]; + + // XEX part + XorBlocksInPlace(tweak, outputSpan); + alg.TransformBlock(buffer, bufferOffset, blockSize, buffer, bufferOffset); + XorBlocksInPlace(tweak, outputSpan); + } + + private static void XorBlocksInPlace(ReadOnlySpan input, Span output) + { + for (int i = 0; i < output.Length; i++) + { + output[i] ^= input[i]; + } + } + + private static void GaloisMultiplyByTwo(Span tweak) + { + bool carry = false; + for (int i = 0; i < tweak.Length; i++) + { + // Save carry from previous byte + byte oldCarry = (byte)(carry ? 1 : 0); + + // Check if there is a carry for this shift + carry = (tweak[i] & 0x80) > 0; + + // Shift left + tweak[i] <<= 1; + + // Carry over bit from last carry + tweak[i] |= oldCarry; + } + + if (carry) + { + // Derived from polynomial x^128 + x^7 + x^2 + x + 1 + tweak[0] ^= 135; + } + } +} diff --git a/test_case_gen/.gitignore b/test_case_gen/.gitignore new file mode 100644 index 0000000..82446ec --- /dev/null +++ b/test_case_gen/.gitignore @@ -0,0 +1,2 @@ +venv/ +test_case_input.txt \ No newline at end of file diff --git a/test_case_gen/README.md b/test_case_gen/README.md new file mode 100644 index 0000000..1ac3a8a --- /dev/null +++ b/test_case_gen/README.md @@ -0,0 +1,18 @@ +# Test cases generator +This generator takes the test vectors specified in the IEEE1619-2018 standard and generates test cases for the library. +For copyright reasons, we cannot provide the input file itself. + +## How to use +### Setup +First, install the required dependencies: +```sh +pip install -r ./requirements.txt +``` + +Then, copy and paste the test vectors from the standard into a text file named `test_case_input.txt`. Then, remove the irrelevant lines(section headers, headers, footers, etc.) and make sure the file ends with a newline, or else the last test case will not be captured by the regex. + +### Run +Run the following command: +```sh +python ./test_case_gen.py +``` \ No newline at end of file diff --git a/test_case_gen/requirements.txt b/test_case_gen/requirements.txt new file mode 100644 index 0000000..cf6aded --- /dev/null +++ b/test_case_gen/requirements.txt @@ -0,0 +1 @@ +Jinja2 \ No newline at end of file diff --git a/test_case_gen/template.cs b/test_case_gen/template.cs new file mode 100644 index 0000000..c198df5 --- /dev/null +++ b/test_case_gen/template.cs @@ -0,0 +1,33 @@ +namespace XTS.NET.Tests; + +public class IeeeVectorsTests +{ {% for test in test_cases %} + [Test] + public void Vector{{ test.vectorNum }}Test() + { + byte[] key = [ + {{ test.key }} + ]; + + ulong sector = {{ test.sector }}; + + byte[] expectedPlaintext = [ + {{ test.expectedPlaintext }} + ]; + + byte[] expectedCiphertext = [ + {{ test.expectedCiphertext }} + ]; + + SymmetricAlgorithm aes = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + + aes.EncryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); + + aes.DecryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } +{% endfor %} +} \ No newline at end of file diff --git a/test_case_gen/test_case_gen.py b/test_case_gen/test_case_gen.py new file mode 100644 index 0000000..2d3a09a --- /dev/null +++ b/test_case_gen/test_case_gen.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +import struct +import jinja2 +import re +from math import ceil + +def generate_test(input_text: str) -> str: + matches = re.findall(r"Vector (\d+)\nKey1 ([0-9a-fA-F]+)\nKey2 ([0-9a-fA-F]+)\nData .nit .equence .umber ([0-9a-fA-F]+)\n((PTX [0-9a-fA-F]+\n)+)((TWK [0-9a-fA-F]+\n)*)((CTX [0-9a-fA-F]+\n)+)", input_text) + + test_cases = [ \ + { \ + "key": format_bytes(bytes.fromhex(m[1]) + bytes.fromhex(m[2])), \ + "vectorNum": m[0], \ + "sector": hex(get_big_endian(m[3])), \ + "expectedPlaintext": format_bytes(parse_multiline_hex(m[4])), \ + "expectedCiphertext": format_bytes(parse_multiline_hex(m[8])), \ + } for m in matches \ + ] + + templateLoader = jinja2.FileSystemLoader(searchpath="./") + templateEnv = jinja2.Environment(loader=templateLoader) + TEMPLATE_FILE = "template.cs" + template = templateEnv.get_template(TEMPLATE_FILE) + + return template.render(test_cases=test_cases) + +def get_big_endian(data: str) -> int: + data = bytes.fromhex(data.rjust(2, '0')) + data = data.ljust(8, b'\0') + + return struct.unpack(" bytes: + input = input.replace("PTX ", "").replace("CTX ", "").replace(",\n","") + return bytes.fromhex(input) + +def format_bytes(input: bytes) -> str: + padding = " " * 12 + input_bytes = ["0x%02x" % i for i in input] + input_bytes = chunk(input_bytes, 8) + + input_bytes = [", ".join(b) for b in input_bytes] + return (",\n" + padding).join(input_bytes) + +def chunk(lst, size: int): + return list( + map(lambda x: lst[x * size:x * size + size], + list(range(ceil(len(lst) / size))))) + +if __name__ == "__main__": + text = "" + with open("./test_case_input.txt") as f: + text = f.read() + + text = generate_test(text) + + with open("../tests/IeeeVectorsTests.cs", "w") as f: + f.write(text) diff --git a/tests/GlobalUsings.cs b/tests/GlobalUsings.cs new file mode 100644 index 0000000..aa4565e --- /dev/null +++ b/tests/GlobalUsings.cs @@ -0,0 +1,2 @@ +global using NUnit.Framework; +global using System.Security.Cryptography; \ No newline at end of file diff --git a/tests/IeeeVectorsTests.cs b/tests/IeeeVectorsTests.cs new file mode 100644 index 0000000..51cfed4 --- /dev/null +++ b/tests/IeeeVectorsTests.cs @@ -0,0 +1,2160 @@ +namespace XTS.NET.Tests; + +public class IeeeVectorsTests +{ + [Test] + public void Vector1Test() + { + byte[] key = [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + ]; + + ulong sector = 0x0; + + byte[] expectedPlaintext = [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + ]; + + byte[] expectedCiphertext = [ + 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec, + 0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92, + 0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85, + 0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e + ]; + + SymmetricAlgorithm aes = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + + aes.EncryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); + + aes.DecryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } + + [Test] + public void Vector2Test() + { + byte[] key = [ + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 + ]; + + ulong sector = 0x3333333333; + + byte[] expectedPlaintext = [ + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 + ]; + + byte[] expectedCiphertext = [ + 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e, + 0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b, + 0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4, + 0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 + ]; + + SymmetricAlgorithm aes = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + + aes.EncryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); + + aes.DecryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } + + [Test] + public void Vector3Test() + { + byte[] key = [ + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 + ]; + + ulong sector = 0x3333333333; + + byte[] expectedPlaintext = [ + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 + ]; + + byte[] expectedCiphertext = [ + 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a, + 0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2, + 0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53, + 0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 + ]; + + SymmetricAlgorithm aes = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + + aes.EncryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); + + aes.DecryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } + + [Test] + public void Vector4Test() + { + byte[] key = [ + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95 + ]; + + ulong sector = 0x0; + + byte[] expectedPlaintext = [ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + ]; + + byte[] expectedCiphertext = [ + 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76, + 0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2, + 0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25, + 0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c, + 0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f, + 0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00, + 0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad, + 0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12, + 0x32, 0x80, 0x63, 0xfd, 0x2a, 0xab, 0x53, 0xe5, + 0xea, 0x1e, 0x0a, 0x9f, 0x33, 0x25, 0x00, 0xa5, + 0xdf, 0x94, 0x87, 0xd0, 0x7a, 0x5c, 0x92, 0xcc, + 0x51, 0x2c, 0x88, 0x66, 0xc7, 0xe8, 0x60, 0xce, + 0x93, 0xfd, 0xf1, 0x66, 0xa2, 0x49, 0x12, 0xb4, + 0x22, 0x97, 0x61, 0x46, 0xae, 0x20, 0xce, 0x84, + 0x6b, 0xb7, 0xdc, 0x9b, 0xa9, 0x4a, 0x76, 0x7a, + 0xae, 0xf2, 0x0c, 0x0d, 0x61, 0xad, 0x02, 0x65, + 0x5e, 0xa9, 0x2d, 0xc4, 0xc4, 0xe4, 0x1a, 0x89, + 0x52, 0xc6, 0x51, 0xd3, 0x31, 0x74, 0xbe, 0x51, + 0xa1, 0x0c, 0x42, 0x11, 0x10, 0xe6, 0xd8, 0x15, + 0x88, 0xed, 0xe8, 0x21, 0x03, 0xa2, 0x52, 0xd8, + 0xa7, 0x50, 0xe8, 0x76, 0x8d, 0xef, 0xff, 0xed, + 0x91, 0x22, 0x81, 0x0a, 0xae, 0xb9, 0x9f, 0x91, + 0x72, 0xaf, 0x82, 0xb6, 0x04, 0xdc, 0x4b, 0x8e, + 0x51, 0xbc, 0xb0, 0x82, 0x35, 0xa6, 0xf4, 0x34, + 0x13, 0x32, 0xe4, 0xca, 0x60, 0x48, 0x2a, 0x4b, + 0xa1, 0xa0, 0x3b, 0x3e, 0x65, 0x00, 0x8f, 0xc5, + 0xda, 0x76, 0xb7, 0x0b, 0xf1, 0x69, 0x0d, 0xb4, + 0xea, 0xe2, 0x9c, 0x5f, 0x1b, 0xad, 0xd0, 0x3c, + 0x5c, 0xcf, 0x2a, 0x55, 0xd7, 0x05, 0xdd, 0xcd, + 0x86, 0xd4, 0x49, 0x51, 0x1c, 0xeb, 0x7e, 0xc3, + 0x0b, 0xf1, 0x2b, 0x1f, 0xa3, 0x5b, 0x91, 0x3f, + 0x9f, 0x74, 0x7a, 0x8a, 0xfd, 0x1b, 0x13, 0x0e, + 0x94, 0xbf, 0xf9, 0x4e, 0xff, 0xd0, 0x1a, 0x91, + 0x73, 0x5c, 0xa1, 0x72, 0x6a, 0xcd, 0x0b, 0x19, + 0x7c, 0x4e, 0x5b, 0x03, 0x39, 0x36, 0x97, 0xe1, + 0x26, 0x82, 0x6f, 0xb6, 0xbb, 0xde, 0x8e, 0xcc, + 0x1e, 0x08, 0x29, 0x85, 0x16, 0xe2, 0xc9, 0xed, + 0x03, 0xff, 0x3c, 0x1b, 0x78, 0x60, 0xf6, 0xde, + 0x76, 0xd4, 0xce, 0xcd, 0x94, 0xc8, 0x11, 0x98, + 0x55, 0xef, 0x52, 0x97, 0xca, 0x67, 0xe9, 0xf3, + 0xe7, 0xff, 0x72, 0xb1, 0xe9, 0x97, 0x85, 0xca, + 0x0a, 0x7e, 0x77, 0x20, 0xc5, 0xb3, 0x6d, 0xc6, + 0xd7, 0x2c, 0xac, 0x95, 0x74, 0xc8, 0xcb, 0xbc, + 0x2f, 0x80, 0x1e, 0x23, 0xe5, 0x6f, 0xd3, 0x44, + 0xb0, 0x7f, 0x22, 0x15, 0x4b, 0xeb, 0xa0, 0xf0, + 0x8c, 0xe8, 0x89, 0x1e, 0x64, 0x3e, 0xd9, 0x95, + 0xc9, 0x4d, 0x9a, 0x69, 0xc9, 0xf1, 0xb5, 0xf4, + 0x99, 0x02, 0x7a, 0x78, 0x57, 0x2a, 0xee, 0xbd, + 0x74, 0xd2, 0x0c, 0xc3, 0x98, 0x81, 0xc2, 0x13, + 0xee, 0x77, 0x0b, 0x10, 0x10, 0xe4, 0xbe, 0xa7, + 0x18, 0x84, 0x69, 0x77, 0xae, 0x11, 0x9f, 0x7a, + 0x02, 0x3a, 0xb5, 0x8c, 0xca, 0x0a, 0xd7, 0x52, + 0xaf, 0xe6, 0x56, 0xbb, 0x3c, 0x17, 0x25, 0x6a, + 0x9f, 0x6e, 0x9b, 0xf1, 0x9f, 0xdd, 0x5a, 0x38, + 0xfc, 0x82, 0xbb, 0xe8, 0x72, 0xc5, 0x53, 0x9e, + 0xdb, 0x60, 0x9e, 0xf4, 0xf7, 0x9c, 0x20, 0x3e, + 0xbb, 0x14, 0x0f, 0x2e, 0x58, 0x3c, 0xb2, 0xad, + 0x15, 0xb4, 0xaa, 0x5b, 0x65, 0x50, 0x16, 0xa8, + 0x44, 0x92, 0x77, 0xdb, 0xd4, 0x77, 0xef, 0x2c, + 0x8d, 0x6c, 0x01, 0x7d, 0xb7, 0x38, 0xb1, 0x8d, + 0xeb, 0x4a, 0x42, 0x7d, 0x19, 0x23, 0xce, 0x3f, + 0xf2, 0x62, 0x73, 0x57, 0x79, 0xa4, 0x18, 0xf2, + 0x0a, 0x28, 0x2d, 0xf9, 0x20, 0x14, 0x7b, 0xea, + 0xbe, 0x42, 0x1e, 0xe5, 0x31, 0x9d, 0x05, 0x68 + ]; + + SymmetricAlgorithm aes = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + + aes.EncryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); + + aes.DecryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } + + [Test] + public void Vector5Test() + { + byte[] key = [ + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95 + ]; + + ulong sector = 0x1; + + byte[] expectedPlaintext = [ + 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76, + 0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2, + 0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25, + 0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c, + 0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f, + 0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00, + 0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad, + 0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12, + 0x32, 0x80, 0x63, 0xfd, 0x2a, 0xab, 0x53, 0xe5, + 0xea, 0x1e, 0x0a, 0x9f, 0x33, 0x25, 0x00, 0xa5, + 0xdf, 0x94, 0x87, 0xd0, 0x7a, 0x5c, 0x92, 0xcc, + 0x51, 0x2c, 0x88, 0x66, 0xc7, 0xe8, 0x60, 0xce, + 0x93, 0xfd, 0xf1, 0x66, 0xa2, 0x49, 0x12, 0xb4, + 0x22, 0x97, 0x61, 0x46, 0xae, 0x20, 0xce, 0x84, + 0x6b, 0xb7, 0xdc, 0x9b, 0xa9, 0x4a, 0x76, 0x7a, + 0xae, 0xf2, 0x0c, 0x0d, 0x61, 0xad, 0x02, 0x65, + 0x5e, 0xa9, 0x2d, 0xc4, 0xc4, 0xe4, 0x1a, 0x89, + 0x52, 0xc6, 0x51, 0xd3, 0x31, 0x74, 0xbe, 0x51, + 0xa1, 0x0c, 0x42, 0x11, 0x10, 0xe6, 0xd8, 0x15, + 0x88, 0xed, 0xe8, 0x21, 0x03, 0xa2, 0x52, 0xd8, + 0xa7, 0x50, 0xe8, 0x76, 0x8d, 0xef, 0xff, 0xed, + 0x91, 0x22, 0x81, 0x0a, 0xae, 0xb9, 0x9f, 0x91, + 0x72, 0xaf, 0x82, 0xb6, 0x04, 0xdc, 0x4b, 0x8e, + 0x51, 0xbc, 0xb0, 0x82, 0x35, 0xa6, 0xf4, 0x34, + 0x13, 0x32, 0xe4, 0xca, 0x60, 0x48, 0x2a, 0x4b, + 0xa1, 0xa0, 0x3b, 0x3e, 0x65, 0x00, 0x8f, 0xc5, + 0xda, 0x76, 0xb7, 0x0b, 0xf1, 0x69, 0x0d, 0xb4, + 0xea, 0xe2, 0x9c, 0x5f, 0x1b, 0xad, 0xd0, 0x3c, + 0x5c, 0xcf, 0x2a, 0x55, 0xd7, 0x05, 0xdd, 0xcd, + 0x86, 0xd4, 0x49, 0x51, 0x1c, 0xeb, 0x7e, 0xc3, + 0x0b, 0xf1, 0x2b, 0x1f, 0xa3, 0x5b, 0x91, 0x3f, + 0x9f, 0x74, 0x7a, 0x8a, 0xfd, 0x1b, 0x13, 0x0e, + 0x94, 0xbf, 0xf9, 0x4e, 0xff, 0xd0, 0x1a, 0x91, + 0x73, 0x5c, 0xa1, 0x72, 0x6a, 0xcd, 0x0b, 0x19, + 0x7c, 0x4e, 0x5b, 0x03, 0x39, 0x36, 0x97, 0xe1, + 0x26, 0x82, 0x6f, 0xb6, 0xbb, 0xde, 0x8e, 0xcc, + 0x1e, 0x08, 0x29, 0x85, 0x16, 0xe2, 0xc9, 0xed, + 0x03, 0xff, 0x3c, 0x1b, 0x78, 0x60, 0xf6, 0xde, + 0x76, 0xd4, 0xce, 0xcd, 0x94, 0xc8, 0x11, 0x98, + 0x55, 0xef, 0x52, 0x97, 0xca, 0x67, 0xe9, 0xf3, + 0xe7, 0xff, 0x72, 0xb1, 0xe9, 0x97, 0x85, 0xca, + 0x0a, 0x7e, 0x77, 0x20, 0xc5, 0xb3, 0x6d, 0xc6, + 0xd7, 0x2c, 0xac, 0x95, 0x74, 0xc8, 0xcb, 0xbc, + 0x2f, 0x80, 0x1e, 0x23, 0xe5, 0x6f, 0xd3, 0x44, + 0xb0, 0x7f, 0x22, 0x15, 0x4b, 0xeb, 0xa0, 0xf0, + 0x8c, 0xe8, 0x89, 0x1e, 0x64, 0x3e, 0xd9, 0x95, + 0xc9, 0x4d, 0x9a, 0x69, 0xc9, 0xf1, 0xb5, 0xf4, + 0x99, 0x02, 0x7a, 0x78, 0x57, 0x2a, 0xee, 0xbd, + 0x74, 0xd2, 0x0c, 0xc3, 0x98, 0x81, 0xc2, 0x13, + 0xee, 0x77, 0x0b, 0x10, 0x10, 0xe4, 0xbe, 0xa7, + 0x18, 0x84, 0x69, 0x77, 0xae, 0x11, 0x9f, 0x7a, + 0x02, 0x3a, 0xb5, 0x8c, 0xca, 0x0a, 0xd7, 0x52, + 0xaf, 0xe6, 0x56, 0xbb, 0x3c, 0x17, 0x25, 0x6a, + 0x9f, 0x6e, 0x9b, 0xf1, 0x9f, 0xdd, 0x5a, 0x38, + 0xfc, 0x82, 0xbb, 0xe8, 0x72, 0xc5, 0x53, 0x9e, + 0xdb, 0x60, 0x9e, 0xf4, 0xf7, 0x9c, 0x20, 0x3e, + 0xbb, 0x14, 0x0f, 0x2e, 0x58, 0x3c, 0xb2, 0xad, + 0x15, 0xb4, 0xaa, 0x5b, 0x65, 0x50, 0x16, 0xa8, + 0x44, 0x92, 0x77, 0xdb, 0xd4, 0x77, 0xef, 0x2c, + 0x8d, 0x6c, 0x01, 0x7d, 0xb7, 0x38, 0xb1, 0x8d, + 0xeb, 0x4a, 0x42, 0x7d, 0x19, 0x23, 0xce, 0x3f, + 0xf2, 0x62, 0x73, 0x57, 0x79, 0xa4, 0x18, 0xf2, + 0x0a, 0x28, 0x2d, 0xf9, 0x20, 0x14, 0x7b, 0xea, + 0xbe, 0x42, 0x1e, 0xe5, 0x31, 0x9d, 0x05, 0x68 + ]; + + byte[] expectedCiphertext = [ + 0x26, 0x4d, 0x3c, 0xa8, 0x51, 0x21, 0x94, 0xfe, + 0xc3, 0x12, 0xc8, 0xc9, 0x89, 0x1f, 0x27, 0x9f, + 0xef, 0xdd, 0x60, 0x8d, 0x0c, 0x02, 0x7b, 0x60, + 0x48, 0x3a, 0x3f, 0xa8, 0x11, 0xd6, 0x5e, 0xe5, + 0x9d, 0x52, 0xd9, 0xe4, 0x0e, 0xc5, 0x67, 0x2d, + 0x81, 0x53, 0x2b, 0x38, 0xb6, 0xb0, 0x89, 0xce, + 0x95, 0x1f, 0x0f, 0x9c, 0x35, 0x59, 0x0b, 0x8b, + 0x97, 0x8d, 0x17, 0x52, 0x13, 0xf3, 0x29, 0xbb, + 0x1c, 0x2f, 0xd3, 0x0f, 0x2f, 0x7f, 0x30, 0x49, + 0x2a, 0x61, 0xa5, 0x32, 0xa7, 0x9f, 0x51, 0xd3, + 0x6f, 0x5e, 0x31, 0xa7, 0xc9, 0xa1, 0x2c, 0x28, + 0x60, 0x82, 0xff, 0x7d, 0x23, 0x94, 0xd1, 0x8f, + 0x78, 0x3e, 0x1a, 0x8e, 0x72, 0xc7, 0x22, 0xca, + 0xaa, 0xa5, 0x2d, 0x8f, 0x06, 0x56, 0x57, 0xd2, + 0x63, 0x1f, 0xd2, 0x5b, 0xfd, 0x8e, 0x5b, 0xaa, + 0xd6, 0xe5, 0x27, 0xd7, 0x63, 0x51, 0x75, 0x01, + 0xc6, 0x8c, 0x5e, 0xdc, 0x3c, 0xdd, 0x55, 0x43, + 0x5c, 0x53, 0x2d, 0x71, 0x25, 0xc8, 0x61, 0x4d, + 0xee, 0xd9, 0xad, 0xaa, 0x3a, 0xca, 0xde, 0x58, + 0x88, 0xb8, 0x7b, 0xef, 0x64, 0x1c, 0x4c, 0x99, + 0x4c, 0x80, 0x91, 0xb5, 0xbc, 0xd3, 0x87, 0xf3, + 0x96, 0x3f, 0xb5, 0xbc, 0x37, 0xaa, 0x92, 0x2f, + 0xbf, 0xe3, 0xdf, 0x4e, 0x5b, 0x91, 0x5e, 0x6e, + 0xb5, 0x14, 0x71, 0x7b, 0xdd, 0x2a, 0x74, 0x07, + 0x9a, 0x50, 0x73, 0xf5, 0xc4, 0xbf, 0xd4, 0x6a, + 0xdf, 0x7d, 0x28, 0x2e, 0x7a, 0x39, 0x3a, 0x52, + 0x57, 0x9d, 0x11, 0xa0, 0x28, 0xda, 0x4d, 0x9c, + 0xd9, 0xc7, 0x71, 0x24, 0xf9, 0x64, 0x8e, 0xe3, + 0x83, 0xb1, 0xac, 0x76, 0x39, 0x30, 0xe7, 0x16, + 0x2a, 0x8d, 0x37, 0xf3, 0x50, 0xb2, 0xf7, 0x4b, + 0x84, 0x72, 0xcf, 0x09, 0x90, 0x20, 0x63, 0xc6, + 0xb3, 0x2e, 0x8c, 0x2d, 0x92, 0x90, 0xce, 0xfb, + 0xd7, 0x34, 0x6d, 0x1c, 0x77, 0x9a, 0x0d, 0xf5, + 0x0e, 0xdc, 0xde, 0x45, 0x31, 0xda, 0x07, 0xb0, + 0x99, 0xc6, 0x38, 0xe8, 0x3a, 0x75, 0x59, 0x44, + 0xdf, 0x2a, 0xef, 0x1a, 0xa3, 0x17, 0x52, 0xfd, + 0x32, 0x3d, 0xcb, 0x71, 0x0f, 0xb4, 0xbf, 0xbb, + 0x9d, 0x22, 0xb9, 0x25, 0xbc, 0x35, 0x77, 0xe1, + 0xb8, 0x94, 0x9e, 0x72, 0x9a, 0x90, 0xbb, 0xaf, + 0xea, 0xcf, 0x7f, 0x78, 0x79, 0xe7, 0xb1, 0x14, + 0x7e, 0x28, 0xba, 0x0b, 0xae, 0x94, 0x0d, 0xb7, + 0x95, 0xa6, 0x1b, 0x15, 0xec, 0xf4, 0xdf, 0x8d, + 0xb0, 0x7b, 0x82, 0x4b, 0xb0, 0x62, 0x80, 0x2c, + 0xc9, 0x8a, 0x95, 0x45, 0xbb, 0x2a, 0xae, 0xed, + 0x77, 0xcb, 0x3f, 0xc6, 0xdb, 0x15, 0xdc, 0xd7, + 0xd8, 0x0d, 0x7d, 0x5b, 0xc4, 0x06, 0xc4, 0x97, + 0x0a, 0x34, 0x78, 0xad, 0xa8, 0x89, 0x9b, 0x32, + 0x91, 0x98, 0xeb, 0x61, 0xc1, 0x93, 0xfb, 0x62, + 0x75, 0xaa, 0x8c, 0xa3, 0x40, 0x34, 0x4a, 0x75, + 0xa8, 0x62, 0xae, 0xbe, 0x92, 0xee, 0xe1, 0xce, + 0x03, 0x2f, 0xd9, 0x50, 0xb4, 0x7d, 0x77, 0x04, + 0xa3, 0x87, 0x69, 0x23, 0xb4, 0xad, 0x62, 0x84, + 0x4b, 0xf4, 0xa0, 0x9c, 0x4d, 0xbe, 0x8b, 0x43, + 0x97, 0x18, 0x4b, 0x74, 0x71, 0x36, 0x0c, 0x95, + 0x64, 0x88, 0x0a, 0xed, 0xdd, 0xb9, 0xba, 0xa4, + 0xaf, 0x2e, 0x75, 0x39, 0x4b, 0x08, 0xcd, 0x32, + 0xff, 0x47, 0x9c, 0x57, 0xa0, 0x7d, 0x3e, 0xab, + 0x5d, 0x54, 0xde, 0x5f, 0x97, 0x38, 0xb8, 0xd2, + 0x7f, 0x27, 0xa9, 0xf0, 0xab, 0x11, 0x79, 0x9d, + 0x7b, 0x7f, 0xfe, 0xfb, 0x27, 0x04, 0xc9, 0x5c, + 0x6a, 0xd1, 0x2c, 0x39, 0xf1, 0xe8, 0x67, 0xa4, + 0xb7, 0xb1, 0xd7, 0x81, 0x8a, 0x4b, 0x75, 0x3d, + 0xfd, 0x2a, 0x89, 0xcc, 0xb4, 0x5e, 0x00, 0x1a, + 0x03, 0xa8, 0x67, 0xb1, 0x87, 0xf2, 0x25, 0xdd + ]; + + SymmetricAlgorithm aes = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + + aes.EncryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); + + aes.DecryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } + + [Test] + public void Vector6Test() + { + byte[] key = [ + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95 + ]; + + ulong sector = 0x2; + + byte[] expectedPlaintext = [ + 0x26, 0x4d, 0x3c, 0xa8, 0x51, 0x21, 0x94, 0xfe, + 0xc3, 0x12, 0xc8, 0xc9, 0x89, 0x1f, 0x27, 0x9f, + 0xef, 0xdd, 0x60, 0x8d, 0x0c, 0x02, 0x7b, 0x60, + 0x48, 0x3a, 0x3f, 0xa8, 0x11, 0xd6, 0x5e, 0xe5, + 0x9d, 0x52, 0xd9, 0xe4, 0x0e, 0xc5, 0x67, 0x2d, + 0x81, 0x53, 0x2b, 0x38, 0xb6, 0xb0, 0x89, 0xce, + 0x95, 0x1f, 0x0f, 0x9c, 0x35, 0x59, 0x0b, 0x8b, + 0x97, 0x8d, 0x17, 0x52, 0x13, 0xf3, 0x29, 0xbb, + 0x1c, 0x2f, 0xd3, 0x0f, 0x2f, 0x7f, 0x30, 0x49, + 0x2a, 0x61, 0xa5, 0x32, 0xa7, 0x9f, 0x51, 0xd3, + 0x6f, 0x5e, 0x31, 0xa7, 0xc9, 0xa1, 0x2c, 0x28, + 0x60, 0x82, 0xff, 0x7d, 0x23, 0x94, 0xd1, 0x8f, + 0x78, 0x3e, 0x1a, 0x8e, 0x72, 0xc7, 0x22, 0xca, + 0xaa, 0xa5, 0x2d, 0x8f, 0x06, 0x56, 0x57, 0xd2, + 0x63, 0x1f, 0xd2, 0x5b, 0xfd, 0x8e, 0x5b, 0xaa, + 0xd6, 0xe5, 0x27, 0xd7, 0x63, 0x51, 0x75, 0x01, + 0xc6, 0x8c, 0x5e, 0xdc, 0x3c, 0xdd, 0x55, 0x43, + 0x5c, 0x53, 0x2d, 0x71, 0x25, 0xc8, 0x61, 0x4d, + 0xee, 0xd9, 0xad, 0xaa, 0x3a, 0xca, 0xde, 0x58, + 0x88, 0xb8, 0x7b, 0xef, 0x64, 0x1c, 0x4c, 0x99, + 0x4c, 0x80, 0x91, 0xb5, 0xbc, 0xd3, 0x87, 0xf3, + 0x96, 0x3f, 0xb5, 0xbc, 0x37, 0xaa, 0x92, 0x2f, + 0xbf, 0xe3, 0xdf, 0x4e, 0x5b, 0x91, 0x5e, 0x6e, + 0xb5, 0x14, 0x71, 0x7b, 0xdd, 0x2a, 0x74, 0x07, + 0x9a, 0x50, 0x73, 0xf5, 0xc4, 0xbf, 0xd4, 0x6a, + 0xdf, 0x7d, 0x28, 0x2e, 0x7a, 0x39, 0x3a, 0x52, + 0x57, 0x9d, 0x11, 0xa0, 0x28, 0xda, 0x4d, 0x9c, + 0xd9, 0xc7, 0x71, 0x24, 0xf9, 0x64, 0x8e, 0xe3, + 0x83, 0xb1, 0xac, 0x76, 0x39, 0x30, 0xe7, 0x16, + 0x2a, 0x8d, 0x37, 0xf3, 0x50, 0xb2, 0xf7, 0x4b, + 0x84, 0x72, 0xcf, 0x09, 0x90, 0x20, 0x63, 0xc6, + 0xb3, 0x2e, 0x8c, 0x2d, 0x92, 0x90, 0xce, 0xfb, + 0xd7, 0x34, 0x6d, 0x1c, 0x77, 0x9a, 0x0d, 0xf5, + 0x0e, 0xdc, 0xde, 0x45, 0x31, 0xda, 0x07, 0xb0, + 0x99, 0xc6, 0x38, 0xe8, 0x3a, 0x75, 0x59, 0x44, + 0xdf, 0x2a, 0xef, 0x1a, 0xa3, 0x17, 0x52, 0xfd, + 0x32, 0x3d, 0xcb, 0x71, 0x0f, 0xb4, 0xbf, 0xbb, + 0x9d, 0x22, 0xb9, 0x25, 0xbc, 0x35, 0x77, 0xe1, + 0xb8, 0x94, 0x9e, 0x72, 0x9a, 0x90, 0xbb, 0xaf, + 0xea, 0xcf, 0x7f, 0x78, 0x79, 0xe7, 0xb1, 0x14, + 0x7e, 0x28, 0xba, 0x0b, 0xae, 0x94, 0x0d, 0xb7, + 0x95, 0xa6, 0x1b, 0x15, 0xec, 0xf4, 0xdf, 0x8d, + 0xb0, 0x7b, 0x82, 0x4b, 0xb0, 0x62, 0x80, 0x2c, + 0xc9, 0x8a, 0x95, 0x45, 0xbb, 0x2a, 0xae, 0xed, + 0x77, 0xcb, 0x3f, 0xc6, 0xdb, 0x15, 0xdc, 0xd7, + 0xd8, 0x0d, 0x7d, 0x5b, 0xc4, 0x06, 0xc4, 0x97, + 0x0a, 0x34, 0x78, 0xad, 0xa8, 0x89, 0x9b, 0x32, + 0x91, 0x98, 0xeb, 0x61, 0xc1, 0x93, 0xfb, 0x62, + 0x75, 0xaa, 0x8c, 0xa3, 0x40, 0x34, 0x4a, 0x75, + 0xa8, 0x62, 0xae, 0xbe, 0x92, 0xee, 0xe1, 0xce, + 0x03, 0x2f, 0xd9, 0x50, 0xb4, 0x7d, 0x77, 0x04, + 0xa3, 0x87, 0x69, 0x23, 0xb4, 0xad, 0x62, 0x84, + 0x4b, 0xf4, 0xa0, 0x9c, 0x4d, 0xbe, 0x8b, 0x43, + 0x97, 0x18, 0x4b, 0x74, 0x71, 0x36, 0x0c, 0x95, + 0x64, 0x88, 0x0a, 0xed, 0xdd, 0xb9, 0xba, 0xa4, + 0xaf, 0x2e, 0x75, 0x39, 0x4b, 0x08, 0xcd, 0x32, + 0xff, 0x47, 0x9c, 0x57, 0xa0, 0x7d, 0x3e, 0xab, + 0x5d, 0x54, 0xde, 0x5f, 0x97, 0x38, 0xb8, 0xd2, + 0x7f, 0x27, 0xa9, 0xf0, 0xab, 0x11, 0x79, 0x9d, + 0x7b, 0x7f, 0xfe, 0xfb, 0x27, 0x04, 0xc9, 0x5c, + 0x6a, 0xd1, 0x2c, 0x39, 0xf1, 0xe8, 0x67, 0xa4, + 0xb7, 0xb1, 0xd7, 0x81, 0x8a, 0x4b, 0x75, 0x3d, + 0xfd, 0x2a, 0x89, 0xcc, 0xb4, 0x5e, 0x00, 0x1a, + 0x03, 0xa8, 0x67, 0xb1, 0x87, 0xf2, 0x25, 0xdd + ]; + + byte[] expectedCiphertext = [ + 0xfa, 0x76, 0x2a, 0x36, 0x80, 0xb7, 0x60, 0x07, + 0x92, 0x8e, 0xd4, 0xa4, 0xf4, 0x9a, 0x94, 0x56, + 0x03, 0x1b, 0x70, 0x47, 0x82, 0xe6, 0x5e, 0x16, + 0xce, 0xcb, 0x54, 0xed, 0x7d, 0x01, 0x7b, 0x5e, + 0x18, 0xab, 0xd6, 0x7b, 0x33, 0x8e, 0x81, 0x07, + 0x8f, 0x21, 0xed, 0xb7, 0x86, 0x8d, 0x90, 0x1e, + 0xbe, 0x9c, 0x73, 0x1a, 0x7c, 0x18, 0xb5, 0xe6, + 0xde, 0xc1, 0xd6, 0xa7, 0x2e, 0x07, 0x8a, 0xc9, + 0xa4, 0x26, 0x2f, 0x86, 0x0b, 0xee, 0xfa, 0x14, + 0xf4, 0xe8, 0x21, 0x01, 0x82, 0x72, 0xe4, 0x11, + 0xa9, 0x51, 0x50, 0x2b, 0x6e, 0x79, 0x06, 0x6e, + 0x84, 0x25, 0x2c, 0x33, 0x46, 0xf3, 0xaa, 0x62, + 0x34, 0x43, 0x51, 0xa2, 0x91, 0xd4, 0xbe, 0xdc, + 0x7a, 0x07, 0x61, 0x8b, 0xde, 0xa2, 0xaf, 0x63, + 0x14, 0x5c, 0xc7, 0xa4, 0xb8, 0xd4, 0x07, 0x06, + 0x91, 0xae, 0x89, 0x0c, 0xd6, 0x57, 0x33, 0xe7, + 0x94, 0x6e, 0x90, 0x21, 0xa1, 0xdf, 0xfc, 0x4c, + 0x59, 0xf1, 0x59, 0x42, 0x5e, 0xe6, 0xd5, 0x0c, + 0xa9, 0xb1, 0x35, 0xfa, 0x61, 0x62, 0xce, 0xa1, + 0x8a, 0x93, 0x98, 0x38, 0xdc, 0x00, 0x0f, 0xb3, + 0x86, 0xfa, 0xd0, 0x86, 0xac, 0xce, 0x5a, 0xc0, + 0x7c, 0xb2, 0xec, 0xe7, 0xfd, 0x58, 0x0b, 0x00, + 0xcf, 0xa5, 0xe9, 0x85, 0x89, 0x63, 0x1d, 0xc2, + 0x5e, 0x8e, 0x2a, 0x3d, 0xaf, 0x2f, 0xfd, 0xec, + 0x26, 0x53, 0x16, 0x59, 0x91, 0x2c, 0x9d, 0x8f, + 0x7a, 0x15, 0xe5, 0x86, 0x5e, 0xa8, 0xfb, 0x58, + 0x16, 0xd6, 0x20, 0x70, 0x52, 0xbd, 0x71, 0x28, + 0xcd, 0x74, 0x3c, 0x12, 0xc8, 0x11, 0x87, 0x91, + 0xa4, 0x73, 0x68, 0x11, 0x93, 0x5e, 0xb9, 0x82, + 0xa5, 0x32, 0x34, 0x9e, 0x31, 0xdd, 0x40, 0x1e, + 0x0b, 0x66, 0x0a, 0x56, 0x8c, 0xb1, 0xa4, 0x71, + 0x1f, 0x55, 0x2f, 0x55, 0xde, 0xd5, 0x9f, 0x1f, + 0x15, 0xbf, 0x71, 0x96, 0xb3, 0xca, 0x12, 0xa9, + 0x1e, 0x48, 0x8e, 0xf5, 0x9d, 0x64, 0xf3, 0xa0, + 0x2b, 0xf4, 0x52, 0x39, 0x49, 0x9a, 0xc6, 0x17, + 0x6a, 0xe3, 0x21, 0xc4, 0xa2, 0x11, 0xec, 0x54, + 0x53, 0x65, 0x97, 0x1c, 0x5d, 0x3f, 0x4f, 0x09, + 0xd4, 0xeb, 0x13, 0x9b, 0xfd, 0xf2, 0x07, 0x3d, + 0x33, 0x18, 0x0b, 0x21, 0x00, 0x2b, 0x65, 0xcc, + 0x98, 0x65, 0xe7, 0x6c, 0xb2, 0x4c, 0xd9, 0x2c, + 0x87, 0x4c, 0x24, 0xc1, 0x83, 0x50, 0x39, 0x9a, + 0x93, 0x6a, 0xb3, 0x63, 0x70, 0x79, 0x29, 0x5d, + 0x76, 0xc4, 0x17, 0x77, 0x6b, 0x94, 0xef, 0xce, + 0x3a, 0x0e, 0xf7, 0x20, 0x6b, 0x15, 0x11, 0x05, + 0x19, 0x65, 0x5c, 0x95, 0x6c, 0xbd, 0x8b, 0x24, + 0x89, 0x40, 0x5e, 0xe2, 0xb0, 0x9a, 0x6b, 0x6e, + 0xeb, 0xe0, 0xc5, 0x37, 0x90, 0xa1, 0x2a, 0x89, + 0x98, 0x37, 0x8b, 0x33, 0xa5, 0xb7, 0x11, 0x59, + 0x62, 0x5f, 0x4b, 0xa4, 0x9d, 0x2a, 0x2f, 0xdb, + 0xa5, 0x9f, 0xbf, 0x08, 0x97, 0xbc, 0x7a, 0xab, + 0xd8, 0xd7, 0x07, 0xdc, 0x14, 0x0a, 0x80, 0xf0, + 0xf3, 0x09, 0xf8, 0x35, 0xd3, 0xda, 0x54, 0xab, + 0x58, 0x4e, 0x50, 0x1d, 0xfa, 0x0e, 0xe9, 0x77, + 0xfe, 0xc5, 0x43, 0xf7, 0x41, 0x86, 0xa8, 0x02, + 0xb9, 0xa3, 0x7a, 0xdb, 0x3e, 0x82, 0x91, 0xec, + 0xa0, 0x4d, 0x66, 0x52, 0x0d, 0x22, 0x9e, 0x60, + 0x40, 0x1e, 0x72, 0x82, 0xbe, 0xf4, 0x86, 0xae, + 0x05, 0x9a, 0xa7, 0x06, 0x96, 0xe0, 0xe3, 0x05, + 0xd7, 0x77, 0x14, 0x0a, 0x7a, 0x88, 0x3e, 0xcd, + 0xcb, 0x69, 0xb9, 0xff, 0x93, 0x8e, 0x8a, 0x42, + 0x31, 0x86, 0x4c, 0x69, 0xca, 0x2c, 0x20, 0x43, + 0xbe, 0xd0, 0x07, 0xff, 0x3e, 0x60, 0x5e, 0x01, + 0x4b, 0xcf, 0x51, 0x81, 0x38, 0xdc, 0x3a, 0x25, + 0xc5, 0xe2, 0x36, 0x17, 0x1a, 0x2d, 0x01, 0xd6 + ]; + + SymmetricAlgorithm aes = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + + aes.EncryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); + + aes.DecryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } + + [Test] + public void Vector7Test() + { + byte[] key = [ + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95 + ]; + + ulong sector = 0xfd; + + byte[] expectedPlaintext = [ + 0x8e, 0x41, 0xb7, 0x8c, 0x39, 0x0b, 0x5a, 0xf9, + 0xd7, 0x58, 0xbb, 0x21, 0x4a, 0x67, 0xe9, 0xf6, + 0xbf, 0x77, 0x27, 0xb0, 0x9a, 0xc6, 0x12, 0x40, + 0x84, 0xc3, 0x76, 0x11, 0x39, 0x8f, 0xa4, 0x5d, + 0xaa, 0xd9, 0x48, 0x68, 0x60, 0x0e, 0xd3, 0x91, + 0xfb, 0x1a, 0xcd, 0x48, 0x57, 0xa9, 0x5b, 0x46, + 0x6e, 0x62, 0xef, 0x9f, 0x4b, 0x37, 0x72, 0x44, + 0xd1, 0xc1, 0x52, 0xe7, 0xb3, 0x0d, 0x73, 0x1a, + 0xad, 0x30, 0xc7, 0x16, 0xd2, 0x14, 0xb7, 0x07, + 0xae, 0xd9, 0x9e, 0xb5, 0xb5, 0xe5, 0x80, 0xb3, + 0xe8, 0x87, 0xcf, 0x74, 0x97, 0x46, 0x56, 0x51, + 0xd4, 0xb6, 0x0e, 0x60, 0x42, 0x05, 0x1d, 0xa3, + 0x69, 0x3c, 0x3b, 0x78, 0xc1, 0x44, 0x89, 0x54, + 0x3b, 0xe8, 0xb6, 0xad, 0x0b, 0xa6, 0x29, 0x56, + 0x5b, 0xba, 0x20, 0x23, 0x13, 0xba, 0x7b, 0x0d, + 0x0c, 0x94, 0xa3, 0x25, 0x2b, 0x67, 0x6f, 0x46, + 0xcc, 0x02, 0xce, 0x0f, 0x8a, 0x7d, 0x34, 0xc0, + 0xed, 0x22, 0x91, 0x29, 0x67, 0x3c, 0x1f, 0x61, + 0xae, 0xd5, 0x79, 0xd0, 0x8a, 0x92, 0x03, 0xa2, + 0x5a, 0xac, 0x3a, 0x77, 0xe9, 0xdb, 0x60, 0x26, + 0x79, 0x96, 0xdb, 0x38, 0xdf, 0x63, 0x73, 0x56, + 0xd9, 0xdc, 0xd1, 0x63, 0x2e, 0x36, 0x99, 0x39, + 0xf2, 0xa2, 0x9d, 0x89, 0x34, 0x5c, 0x66, 0xe0, + 0x50, 0x66, 0xf1, 0xa3, 0x67, 0x7a, 0xef, 0x18, + 0xde, 0xa4, 0x11, 0x3f, 0xae, 0xb6, 0x29, 0xe4, + 0x67, 0x21, 0xa6, 0x6d, 0x0a, 0x7e, 0x78, 0x5d, + 0x3e, 0x29, 0xaf, 0x25, 0x94, 0xeb, 0x67, 0xdf, + 0xa9, 0x82, 0xaf, 0xfe, 0x0a, 0xac, 0x05, 0x8f, + 0x6e, 0x15, 0x86, 0x42, 0x69, 0xb1, 0x35, 0x41, + 0x82, 0x61, 0xfc, 0x3a, 0xfb, 0x08, 0x94, 0x72, + 0xcf, 0x68, 0xc4, 0x5d, 0xd7, 0xf2, 0x31, 0xc6, + 0x24, 0x9b, 0xa0, 0x25, 0x5e, 0x1e, 0x03, 0x38, + 0x33, 0xfc, 0x4d, 0x00, 0xa3, 0xfe, 0x02, 0x13, + 0x2d, 0x7b, 0xc3, 0x87, 0x36, 0x14, 0xb8, 0xae, + 0xe3, 0x42, 0x73, 0x58, 0x1e, 0xa0, 0x32, 0x5c, + 0x81, 0xf0, 0x27, 0x0a, 0xff, 0xa1, 0x36, 0x41, + 0xd0, 0x52, 0xd3, 0x6f, 0x07, 0x57, 0xd4, 0x84, + 0x01, 0x43, 0x54, 0xd0, 0x2d, 0x68, 0x83, 0xca, + 0x15, 0xc2, 0x4d, 0x8c, 0x39, 0x56, 0xb1, 0xbd, + 0x02, 0x7b, 0xcf, 0x41, 0xf1, 0x51, 0xfd, 0x80, + 0x23, 0xc5, 0x34, 0x0e, 0x56, 0x06, 0xf3, 0x7e, + 0x90, 0xfd, 0xb8, 0x7c, 0x86, 0xfb, 0x4f, 0xa6, + 0x34, 0xb3, 0x71, 0x8a, 0x30, 0xba, 0xce, 0x06, + 0xa6, 0x6e, 0xaf, 0x8f, 0x63, 0xc4, 0xaa, 0x3b, + 0x63, 0x78, 0x26, 0xa8, 0x7f, 0xe8, 0xcf, 0xa4, + 0x42, 0x82, 0xe9, 0x2c, 0xb1, 0x61, 0x5a, 0xf3, + 0xa2, 0x8e, 0x53, 0xbc, 0x74, 0xc7, 0xcb, 0xa1, + 0xa0, 0x97, 0x7b, 0xe9, 0x06, 0x5d, 0x0c, 0x1a, + 0x5d, 0xec, 0x6c, 0x54, 0xae, 0x38, 0xd3, 0x7f, + 0x37, 0xaa, 0x35, 0x28, 0x3e, 0x04, 0x8e, 0x55, + 0x30, 0xa8, 0x5c, 0x4e, 0x7a, 0x29, 0xd7, 0xb9, + 0x2e, 0xc0, 0xc3, 0x16, 0x9c, 0xdf, 0x2a, 0x80, + 0x5c, 0x76, 0x04, 0xbc, 0xe6, 0x00, 0x49, 0xb9, + 0xfb, 0x7b, 0x8e, 0xaa, 0xc1, 0x0f, 0x51, 0xae, + 0x23, 0x79, 0x4c, 0xeb, 0xa6, 0x8b, 0xb5, 0x81, + 0x12, 0xe2, 0x93, 0xb9, 0xb6, 0x92, 0xca, 0x72, + 0x1b, 0x37, 0xc6, 0x62, 0xf8, 0x57, 0x4e, 0xd4, + 0xdb, 0xa6, 0xf8, 0x8e, 0x17, 0x08, 0x81, 0xc8, + 0x2c, 0xdd, 0xc1, 0x03, 0x4a, 0x0c, 0xa7, 0xe2, + 0x84, 0xbf, 0x09, 0x62, 0xb6, 0xb2, 0x62, 0x92, + 0xd8, 0x36, 0xfa, 0x9f, 0x73, 0xc1, 0xac, 0x77, + 0x0e, 0xef, 0x0f, 0x2d, 0x3a, 0x1e, 0xaf, 0x61, + 0xd3, 0xe0, 0x35, 0x55, 0xfd, 0x42, 0x4e, 0xed, + 0xd6, 0x7e, 0x18, 0xa1, 0x80, 0x94, 0xf8, 0x88 + ]; + + byte[] expectedCiphertext = [ + 0xd5, 0x5f, 0x68, 0x4f, 0x81, 0xf4, 0x42, 0x6e, + 0x9f, 0xde, 0x92, 0xa5, 0xff, 0x02, 0xdf, 0x2a, + 0xc8, 0x96, 0xaf, 0x63, 0x96, 0x28, 0x88, 0xa9, + 0x79, 0x10, 0xc1, 0x37, 0x9e, 0x20, 0xb0, 0xa3, + 0xb1, 0xdb, 0x61, 0x3f, 0xb7, 0xfe, 0x2e, 0x07, + 0x00, 0x43, 0x29, 0xea, 0x5c, 0x22, 0xbf, 0xd3, + 0x3e, 0x3d, 0xbe, 0x4c, 0xf5, 0x8c, 0xc6, 0x08, + 0xc2, 0xc2, 0x6c, 0x19, 0xa2, 0xe2, 0xfe, 0x22, + 0xf9, 0x87, 0x32, 0xc2, 0xb5, 0xcb, 0x84, 0x4c, + 0xc6, 0xc0, 0x70, 0x2d, 0x91, 0xe1, 0xd5, 0x0f, + 0xc4, 0x38, 0x2a, 0x7e, 0xba, 0x56, 0x35, 0xcd, + 0x60, 0x24, 0x32, 0xa2, 0x30, 0x6a, 0xc4, 0xce, + 0x82, 0xf8, 0xd7, 0x0c, 0x8d, 0x9b, 0xc1, 0x5f, + 0x91, 0x8f, 0xe7, 0x1e, 0x74, 0xc6, 0x22, 0xd5, + 0xcf, 0x71, 0x17, 0x8b, 0xf6, 0xe0, 0xb9, 0xcc, + 0x9f, 0x2b, 0x41, 0xdd, 0x8d, 0xbe, 0x44, 0x1c, + 0x41, 0xcd, 0x0c, 0x73, 0xa6, 0xdc, 0x47, 0xa3, + 0x48, 0xf6, 0x70, 0x2f, 0x9d, 0x0e, 0x9b, 0x1b, + 0x14, 0x31, 0xe9, 0x48, 0xe2, 0x99, 0xb9, 0xec, + 0x22, 0x72, 0xab, 0x2c, 0x5f, 0x0c, 0x7b, 0xe8, + 0x6a, 0xff, 0xa5, 0xde, 0xc8, 0x7a, 0x0b, 0xee, + 0x81, 0xd3, 0xd5, 0x00, 0x07, 0xed, 0xaa, 0x2b, + 0xcf, 0xcc, 0xb3, 0x56, 0x05, 0x15, 0x5f, 0xf3, + 0x6e, 0xd8, 0xed, 0xd4, 0xa4, 0x0d, 0xcd, 0x4b, + 0x24, 0x3a, 0xcd, 0x11, 0xb2, 0xb9, 0x87, 0xbd, + 0xbf, 0xaf, 0x91, 0xa7, 0xca, 0xc2, 0x7e, 0x9c, + 0x5a, 0xea, 0x52, 0x5e, 0xe5, 0x3d, 0xe7, 0xb2, + 0xd3, 0x33, 0x2c, 0x86, 0x44, 0x40, 0x2b, 0x82, + 0x3e, 0x94, 0xa7, 0xdb, 0x26, 0x27, 0x6d, 0x2d, + 0x23, 0xaa, 0x07, 0x18, 0x0f, 0x76, 0xb4, 0xfd, + 0x29, 0xb9, 0xc0, 0x82, 0x30, 0x99, 0xc9, 0xd6, + 0x2c, 0x51, 0x98, 0x80, 0xae, 0xe7, 0xe9, 0x69, + 0x76, 0x17, 0xc1, 0x49, 0x7d, 0x47, 0xbf, 0x3e, + 0x57, 0x19, 0x50, 0x31, 0x14, 0x21, 0xb6, 0xb7, + 0x34, 0xd3, 0x8b, 0x0d, 0xb9, 0x1e, 0xb8, 0x53, + 0x31, 0xb9, 0x1e, 0xa9, 0xf6, 0x15, 0x30, 0xf5, + 0x45, 0x12, 0xa5, 0xa5, 0x2a, 0x4b, 0xad, 0x58, + 0x9e, 0xb6, 0x97, 0x81, 0xd5, 0x37, 0xf2, 0x32, + 0x97, 0xbb, 0x45, 0x9b, 0xda, 0xd2, 0x94, 0x8a, + 0x29, 0xe1, 0x55, 0x0b, 0xf4, 0x78, 0x7e, 0x0b, + 0xe9, 0x5b, 0xb1, 0x73, 0xcf, 0x5f, 0xab, 0x17, + 0xda, 0xb7, 0xa1, 0x3a, 0x05, 0x2a, 0x63, 0x45, + 0x3d, 0x97, 0xcc, 0xec, 0x1a, 0x32, 0x19, 0x54, + 0x88, 0x6b, 0x7a, 0x12, 0x99, 0xfa, 0xae, 0xec, + 0xae, 0x35, 0xc6, 0xea, 0xac, 0xa7, 0x53, 0xb0, + 0x41, 0xb5, 0xe5, 0xf0, 0x93, 0xbf, 0x83, 0x39, + 0x7f, 0xd2, 0x1d, 0xd6, 0xb3, 0x01, 0x20, 0x66, + 0xfc, 0xc0, 0x58, 0xcc, 0x32, 0xc3, 0xb0, 0x9d, + 0x75, 0x62, 0xde, 0xe2, 0x95, 0x09, 0xb5, 0x83, + 0x93, 0x92, 0xc9, 0xff, 0x05, 0xf5, 0x1f, 0x31, + 0x66, 0xaa, 0xac, 0x4a, 0xc5, 0xf2, 0x38, 0x03, + 0x8a, 0x30, 0x45, 0xe6, 0xf7, 0x2e, 0x48, 0xef, + 0x0f, 0xe8, 0xbc, 0x67, 0x5e, 0x82, 0xc3, 0x18, + 0xa2, 0x68, 0xe4, 0x39, 0x70, 0x27, 0x1b, 0xf1, + 0x19, 0xb8, 0x1b, 0xf6, 0xa9, 0x82, 0x74, 0x65, + 0x54, 0xf8, 0x4e, 0x72, 0xb9, 0xf0, 0x02, 0x80, + 0xa3, 0x20, 0xa0, 0x81, 0x42, 0x92, 0x3c, 0x23, + 0xc8, 0x83, 0x42, 0x3f, 0xf9, 0x49, 0x82, 0x7f, + 0x29, 0xbb, 0xac, 0xdc, 0x1c, 0xcd, 0xb0, 0x49, + 0x38, 0xce, 0x60, 0x98, 0xc9, 0x5b, 0xa6, 0xb3, + 0x25, 0x28, 0xf4, 0xef, 0x78, 0xee, 0xd7, 0x78, + 0xb2, 0xe1, 0x22, 0xdd, 0xfd, 0x1c, 0xbd, 0xd1, + 0x1d, 0x1c, 0x0a, 0x67, 0x83, 0xe0, 0x11, 0xfc, + 0x53, 0x6d, 0x63, 0xd0, 0x53, 0x26, 0x06, 0x37 + ]; + + SymmetricAlgorithm aes = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + + aes.EncryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); + + aes.DecryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } + + [Test] + public void Vector8Test() + { + byte[] key = [ + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95 + ]; + + ulong sector = 0xfe; + + byte[] expectedPlaintext = [ + 0xd5, 0x5f, 0x68, 0x4f, 0x81, 0xf4, 0x42, 0x6e, + 0x9f, 0xde, 0x92, 0xa5, 0xff, 0x02, 0xdf, 0x2a, + 0xc8, 0x96, 0xaf, 0x63, 0x96, 0x28, 0x88, 0xa9, + 0x79, 0x10, 0xc1, 0x37, 0x9e, 0x20, 0xb0, 0xa3, + 0xb1, 0xdb, 0x61, 0x3f, 0xb7, 0xfe, 0x2e, 0x07, + 0x00, 0x43, 0x29, 0xea, 0x5c, 0x22, 0xbf, 0xd3, + 0x3e, 0x3d, 0xbe, 0x4c, 0xf5, 0x8c, 0xc6, 0x08, + 0xc2, 0xc2, 0x6c, 0x19, 0xa2, 0xe2, 0xfe, 0x22, + 0xf9, 0x87, 0x32, 0xc2, 0xb5, 0xcb, 0x84, 0x4c, + 0xc6, 0xc0, 0x70, 0x2d, 0x91, 0xe1, 0xd5, 0x0f, + 0xc4, 0x38, 0x2a, 0x7e, 0xba, 0x56, 0x35, 0xcd, + 0x60, 0x24, 0x32, 0xa2, 0x30, 0x6a, 0xc4, 0xce, + 0x82, 0xf8, 0xd7, 0x0c, 0x8d, 0x9b, 0xc1, 0x5f, + 0x91, 0x8f, 0xe7, 0x1e, 0x74, 0xc6, 0x22, 0xd5, + 0xcf, 0x71, 0x17, 0x8b, 0xf6, 0xe0, 0xb9, 0xcc, + 0x9f, 0x2b, 0x41, 0xdd, 0x8d, 0xbe, 0x44, 0x1c, + 0x41, 0xcd, 0x0c, 0x73, 0xa6, 0xdc, 0x47, 0xa3, + 0x48, 0xf6, 0x70, 0x2f, 0x9d, 0x0e, 0x9b, 0x1b, + 0x14, 0x31, 0xe9, 0x48, 0xe2, 0x99, 0xb9, 0xec, + 0x22, 0x72, 0xab, 0x2c, 0x5f, 0x0c, 0x7b, 0xe8, + 0x6a, 0xff, 0xa5, 0xde, 0xc8, 0x7a, 0x0b, 0xee, + 0x81, 0xd3, 0xd5, 0x00, 0x07, 0xed, 0xaa, 0x2b, + 0xcf, 0xcc, 0xb3, 0x56, 0x05, 0x15, 0x5f, 0xf3, + 0x6e, 0xd8, 0xed, 0xd4, 0xa4, 0x0d, 0xcd, 0x4b, + 0x24, 0x3a, 0xcd, 0x11, 0xb2, 0xb9, 0x87, 0xbd, + 0xbf, 0xaf, 0x91, 0xa7, 0xca, 0xc2, 0x7e, 0x9c, + 0x5a, 0xea, 0x52, 0x5e, 0xe5, 0x3d, 0xe7, 0xb2, + 0xd3, 0x33, 0x2c, 0x86, 0x44, 0x40, 0x2b, 0x82, + 0x3e, 0x94, 0xa7, 0xdb, 0x26, 0x27, 0x6d, 0x2d, + 0x23, 0xaa, 0x07, 0x18, 0x0f, 0x76, 0xb4, 0xfd, + 0x29, 0xb9, 0xc0, 0x82, 0x30, 0x99, 0xc9, 0xd6, + 0x2c, 0x51, 0x98, 0x80, 0xae, 0xe7, 0xe9, 0x69, + 0x76, 0x17, 0xc1, 0x49, 0x7d, 0x47, 0xbf, 0x3e, + 0x57, 0x19, 0x50, 0x31, 0x14, 0x21, 0xb6, 0xb7, + 0x34, 0xd3, 0x8b, 0x0d, 0xb9, 0x1e, 0xb8, 0x53, + 0x31, 0xb9, 0x1e, 0xa9, 0xf6, 0x15, 0x30, 0xf5, + 0x45, 0x12, 0xa5, 0xa5, 0x2a, 0x4b, 0xad, 0x58, + 0x9e, 0xb6, 0x97, 0x81, 0xd5, 0x37, 0xf2, 0x32, + 0x97, 0xbb, 0x45, 0x9b, 0xda, 0xd2, 0x94, 0x8a, + 0x29, 0xe1, 0x55, 0x0b, 0xf4, 0x78, 0x7e, 0x0b, + 0xe9, 0x5b, 0xb1, 0x73, 0xcf, 0x5f, 0xab, 0x17, + 0xda, 0xb7, 0xa1, 0x3a, 0x05, 0x2a, 0x63, 0x45, + 0x3d, 0x97, 0xcc, 0xec, 0x1a, 0x32, 0x19, 0x54, + 0x88, 0x6b, 0x7a, 0x12, 0x99, 0xfa, 0xae, 0xec, + 0xae, 0x35, 0xc6, 0xea, 0xac, 0xa7, 0x53, 0xb0, + 0x41, 0xb5, 0xe5, 0xf0, 0x93, 0xbf, 0x83, 0x39, + 0x7f, 0xd2, 0x1d, 0xd6, 0xb3, 0x01, 0x20, 0x66, + 0xfc, 0xc0, 0x58, 0xcc, 0x32, 0xc3, 0xb0, 0x9d, + 0x75, 0x62, 0xde, 0xe2, 0x95, 0x09, 0xb5, 0x83, + 0x93, 0x92, 0xc9, 0xff, 0x05, 0xf5, 0x1f, 0x31, + 0x66, 0xaa, 0xac, 0x4a, 0xc5, 0xf2, 0x38, 0x03, + 0x8a, 0x30, 0x45, 0xe6, 0xf7, 0x2e, 0x48, 0xef, + 0x0f, 0xe8, 0xbc, 0x67, 0x5e, 0x82, 0xc3, 0x18, + 0xa2, 0x68, 0xe4, 0x39, 0x70, 0x27, 0x1b, 0xf1, + 0x19, 0xb8, 0x1b, 0xf6, 0xa9, 0x82, 0x74, 0x65, + 0x54, 0xf8, 0x4e, 0x72, 0xb9, 0xf0, 0x02, 0x80, + 0xa3, 0x20, 0xa0, 0x81, 0x42, 0x92, 0x3c, 0x23, + 0xc8, 0x83, 0x42, 0x3f, 0xf9, 0x49, 0x82, 0x7f, + 0x29, 0xbb, 0xac, 0xdc, 0x1c, 0xcd, 0xb0, 0x49, + 0x38, 0xce, 0x60, 0x98, 0xc9, 0x5b, 0xa6, 0xb3, + 0x25, 0x28, 0xf4, 0xef, 0x78, 0xee, 0xd7, 0x78, + 0xb2, 0xe1, 0x22, 0xdd, 0xfd, 0x1c, 0xbd, 0xd1, + 0x1d, 0x1c, 0x0a, 0x67, 0x83, 0xe0, 0x11, 0xfc, + 0x53, 0x6d, 0x63, 0xd0, 0x53, 0x26, 0x06, 0x37 + ]; + + byte[] expectedCiphertext = [ + 0x72, 0xef, 0xc1, 0xeb, 0xfe, 0x1e, 0xe2, 0x59, + 0x75, 0xa6, 0xeb, 0x3a, 0xa8, 0x58, 0x9d, 0xda, + 0x2b, 0x26, 0x1f, 0x1c, 0x85, 0xbd, 0xab, 0x44, + 0x2a, 0x9e, 0x5b, 0x2d, 0xd1, 0xd7, 0xc3, 0x95, + 0x7a, 0x16, 0xfc, 0x08, 0xe5, 0x26, 0xd4, 0xb1, + 0x22, 0x3f, 0x1b, 0x12, 0x32, 0xa1, 0x1a, 0xf2, + 0x74, 0xc3, 0xd7, 0x0d, 0xac, 0x57, 0xf8, 0x3e, + 0x09, 0x83, 0xc4, 0x98, 0xf1, 0xa6, 0xf1, 0xae, + 0xcb, 0x02, 0x1c, 0x3e, 0x70, 0x08, 0x5a, 0x1e, + 0x52, 0x7f, 0x1c, 0xe4, 0x1e, 0xe5, 0x91, 0x1a, + 0x82, 0x02, 0x01, 0x61, 0x52, 0x9c, 0xd8, 0x27, + 0x73, 0x76, 0x2d, 0xaf, 0x54, 0x59, 0xde, 0x94, + 0xa0, 0xa8, 0x2a, 0xda, 0xe7, 0xe1, 0x70, 0x3c, + 0x80, 0x85, 0x43, 0xc2, 0x9e, 0xd6, 0xfb, 0x32, + 0xd9, 0xe0, 0x04, 0x32, 0x7c, 0x13, 0x55, 0x18, + 0x0c, 0x99, 0x5a, 0x07, 0x74, 0x14, 0x93, 0xa0, + 0x9c, 0x21, 0xba, 0x01, 0xa3, 0x87, 0x88, 0x2d, + 0xa4, 0xf6, 0x25, 0x34, 0xb8, 0x7b, 0xb1, 0x5d, + 0x60, 0xd1, 0x97, 0x20, 0x1c, 0x0f, 0xd3, 0xbf, + 0x30, 0xc1, 0x50, 0x0a, 0x3e, 0xcf, 0xec, 0xdd, + 0x66, 0xd8, 0x72, 0x1f, 0x90, 0xbc, 0xc4, 0xc1, + 0x7e, 0xe9, 0x25, 0xc6, 0x1b, 0x0a, 0x03, 0x72, + 0x7a, 0x9c, 0x0d, 0x5f, 0x5c, 0xa4, 0x62, 0xfb, + 0xfa, 0x0a, 0xf1, 0xc2, 0x51, 0x3a, 0x9d, 0x9d, + 0x4b, 0x53, 0x45, 0xbd, 0x27, 0xa5, 0xf6, 0xe6, + 0x53, 0xf7, 0x51, 0x69, 0x3e, 0x6b, 0x6a, 0x2b, + 0x8e, 0xad, 0x57, 0xd5, 0x11, 0xe0, 0x0e, 0x58, + 0xc4, 0x5b, 0x7b, 0x8d, 0x00, 0x5a, 0xf7, 0x92, + 0x88, 0xf5, 0xc7, 0xc2, 0x2f, 0xd4, 0xf1, 0xbf, + 0x7a, 0x89, 0x8b, 0x03, 0xa5, 0x63, 0x4c, 0x6a, + 0x1a, 0xe3, 0xf9, 0xfa, 0xe5, 0xde, 0x4f, 0x29, + 0x6a, 0x28, 0x96, 0xb2, 0x3e, 0x7e, 0xd4, 0x3e, + 0xd1, 0x4f, 0xa5, 0xa2, 0x80, 0x3f, 0x4d, 0x28, + 0xf0, 0xd3, 0xff, 0xcf, 0x24, 0x75, 0x76, 0x77, + 0xae, 0xbd, 0xb4, 0x7b, 0xb3, 0x88, 0x37, 0x87, + 0x08, 0x94, 0x8a, 0x8d, 0x41, 0x26, 0xed, 0x18, + 0x39, 0xe0, 0xda, 0x29, 0xa5, 0x37, 0xa8, 0xc1, + 0x98, 0xb3, 0xc6, 0x6a, 0xb0, 0x07, 0x12, 0xdd, + 0x26, 0x16, 0x74, 0xbf, 0x45, 0xa7, 0x3d, 0x67, + 0xf7, 0x69, 0x14, 0xf8, 0x30, 0xca, 0x01, 0x4b, + 0x65, 0x59, 0x6f, 0x27, 0xe4, 0xcf, 0x62, 0xde, + 0x66, 0x12, 0x5a, 0x55, 0x66, 0xdf, 0x99, 0x75, + 0x15, 0x56, 0x28, 0xb4, 0x00, 0xfb, 0xfb, 0x3a, + 0x29, 0x04, 0x0e, 0xd5, 0x0f, 0xaf, 0xfd, 0xbb, + 0x18, 0xae, 0xce, 0x7c, 0x5c, 0x44, 0x69, 0x32, + 0x60, 0xaa, 0xb3, 0x86, 0xc0, 0xa3, 0x7b, 0x11, + 0xb1, 0x14, 0xf1, 0xc4, 0x15, 0xae, 0xbb, 0x65, + 0x3b, 0xe4, 0x68, 0x17, 0x94, 0x28, 0xd4, 0x3a, + 0x4d, 0x8b, 0xc3, 0xec, 0x38, 0x81, 0x3e, 0xca, + 0x30, 0xa1, 0x3c, 0xf1, 0xbb, 0x18, 0xd5, 0x24, + 0xf1, 0x99, 0x2d, 0x44, 0xd8, 0xb1, 0xa4, 0x2e, + 0xa3, 0x0b, 0x22, 0xe6, 0xc9, 0x5b, 0x19, 0x9d, + 0x8d, 0x18, 0x2f, 0x88, 0x40, 0xb0, 0x9d, 0x05, + 0x95, 0x85, 0xc3, 0x1a, 0xd6, 0x91, 0xfa, 0x06, + 0x19, 0xff, 0x03, 0x8a, 0xca, 0x2c, 0x39, 0xa9, + 0x43, 0x42, 0x11, 0x57, 0x36, 0x17, 0x17, 0xc4, + 0x9d, 0x32, 0x20, 0x28, 0xa7, 0x46, 0x48, 0x11, + 0x3b, 0xd8, 0xc9, 0xd7, 0xec, 0x77, 0xcf, 0x3c, + 0x89, 0xc1, 0xec, 0x87, 0x18, 0xce, 0xff, 0x85, + 0x16, 0xd9, 0x6b, 0x34, 0xc3, 0xc6, 0x14, 0xf1, + 0x06, 0x99, 0xc9, 0xab, 0xc4, 0xed, 0x04, 0x11, + 0x50, 0x62, 0x23, 0xbe, 0xa1, 0x6a, 0xf3, 0x5c, + 0x88, 0x3a, 0xcc, 0xdb, 0xe1, 0x10, 0x4e, 0xef, + 0x0c, 0xfd, 0xb5, 0x4e, 0x12, 0xfb, 0x23, 0x0a + ]; + + SymmetricAlgorithm aes = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + + aes.EncryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); + + aes.DecryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } + + [Test] + public void Vector9Test() + { + byte[] key = [ + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95 + ]; + + ulong sector = 0xff; + + byte[] expectedPlaintext = [ + 0x72, 0xef, 0xc1, 0xeb, 0xfe, 0x1e, 0xe2, 0x59, + 0x75, 0xa6, 0xeb, 0x3a, 0xa8, 0x58, 0x9d, 0xda, + 0x2b, 0x26, 0x1f, 0x1c, 0x85, 0xbd, 0xab, 0x44, + 0x2a, 0x9e, 0x5b, 0x2d, 0xd1, 0xd7, 0xc3, 0x95, + 0x7a, 0x16, 0xfc, 0x08, 0xe5, 0x26, 0xd4, 0xb1, + 0x22, 0x3f, 0x1b, 0x12, 0x32, 0xa1, 0x1a, 0xf2, + 0x74, 0xc3, 0xd7, 0x0d, 0xac, 0x57, 0xf8, 0x3e, + 0x09, 0x83, 0xc4, 0x98, 0xf1, 0xa6, 0xf1, 0xae, + 0xcb, 0x02, 0x1c, 0x3e, 0x70, 0x08, 0x5a, 0x1e, + 0x52, 0x7f, 0x1c, 0xe4, 0x1e, 0xe5, 0x91, 0x1a, + 0x82, 0x02, 0x01, 0x61, 0x52, 0x9c, 0xd8, 0x27, + 0x73, 0x76, 0x2d, 0xaf, 0x54, 0x59, 0xde, 0x94, + 0xa0, 0xa8, 0x2a, 0xda, 0xe7, 0xe1, 0x70, 0x3c, + 0x80, 0x85, 0x43, 0xc2, 0x9e, 0xd6, 0xfb, 0x32, + 0xd9, 0xe0, 0x04, 0x32, 0x7c, 0x13, 0x55, 0x18, + 0x0c, 0x99, 0x5a, 0x07, 0x74, 0x14, 0x93, 0xa0, + 0x9c, 0x21, 0xba, 0x01, 0xa3, 0x87, 0x88, 0x2d, + 0xa4, 0xf6, 0x25, 0x34, 0xb8, 0x7b, 0xb1, 0x5d, + 0x60, 0xd1, 0x97, 0x20, 0x1c, 0x0f, 0xd3, 0xbf, + 0x30, 0xc1, 0x50, 0x0a, 0x3e, 0xcf, 0xec, 0xdd, + 0x66, 0xd8, 0x72, 0x1f, 0x90, 0xbc, 0xc4, 0xc1, + 0x7e, 0xe9, 0x25, 0xc6, 0x1b, 0x0a, 0x03, 0x72, + 0x7a, 0x9c, 0x0d, 0x5f, 0x5c, 0xa4, 0x62, 0xfb, + 0xfa, 0x0a, 0xf1, 0xc2, 0x51, 0x3a, 0x9d, 0x9d, + 0x4b, 0x53, 0x45, 0xbd, 0x27, 0xa5, 0xf6, 0xe6, + 0x53, 0xf7, 0x51, 0x69, 0x3e, 0x6b, 0x6a, 0x2b, + 0x8e, 0xad, 0x57, 0xd5, 0x11, 0xe0, 0x0e, 0x58, + 0xc4, 0x5b, 0x7b, 0x8d, 0x00, 0x5a, 0xf7, 0x92, + 0x88, 0xf5, 0xc7, 0xc2, 0x2f, 0xd4, 0xf1, 0xbf, + 0x7a, 0x89, 0x8b, 0x03, 0xa5, 0x63, 0x4c, 0x6a, + 0x1a, 0xe3, 0xf9, 0xfa, 0xe5, 0xde, 0x4f, 0x29, + 0x6a, 0x28, 0x96, 0xb2, 0x3e, 0x7e, 0xd4, 0x3e, + 0xd1, 0x4f, 0xa5, 0xa2, 0x80, 0x3f, 0x4d, 0x28, + 0xf0, 0xd3, 0xff, 0xcf, 0x24, 0x75, 0x76, 0x77, + 0xae, 0xbd, 0xb4, 0x7b, 0xb3, 0x88, 0x37, 0x87, + 0x08, 0x94, 0x8a, 0x8d, 0x41, 0x26, 0xed, 0x18, + 0x39, 0xe0, 0xda, 0x29, 0xa5, 0x37, 0xa8, 0xc1, + 0x98, 0xb3, 0xc6, 0x6a, 0xb0, 0x07, 0x12, 0xdd, + 0x26, 0x16, 0x74, 0xbf, 0x45, 0xa7, 0x3d, 0x67, + 0xf7, 0x69, 0x14, 0xf8, 0x30, 0xca, 0x01, 0x4b, + 0x65, 0x59, 0x6f, 0x27, 0xe4, 0xcf, 0x62, 0xde, + 0x66, 0x12, 0x5a, 0x55, 0x66, 0xdf, 0x99, 0x75, + 0x15, 0x56, 0x28, 0xb4, 0x00, 0xfb, 0xfb, 0x3a, + 0x29, 0x04, 0x0e, 0xd5, 0x0f, 0xaf, 0xfd, 0xbb, + 0x18, 0xae, 0xce, 0x7c, 0x5c, 0x44, 0x69, 0x32, + 0x60, 0xaa, 0xb3, 0x86, 0xc0, 0xa3, 0x7b, 0x11, + 0xb1, 0x14, 0xf1, 0xc4, 0x15, 0xae, 0xbb, 0x65, + 0x3b, 0xe4, 0x68, 0x17, 0x94, 0x28, 0xd4, 0x3a, + 0x4d, 0x8b, 0xc3, 0xec, 0x38, 0x81, 0x3e, 0xca, + 0x30, 0xa1, 0x3c, 0xf1, 0xbb, 0x18, 0xd5, 0x24, + 0xf1, 0x99, 0x2d, 0x44, 0xd8, 0xb1, 0xa4, 0x2e, + 0xa3, 0x0b, 0x22, 0xe6, 0xc9, 0x5b, 0x19, 0x9d, + 0x8d, 0x18, 0x2f, 0x88, 0x40, 0xb0, 0x9d, 0x05, + 0x95, 0x85, 0xc3, 0x1a, 0xd6, 0x91, 0xfa, 0x06, + 0x19, 0xff, 0x03, 0x8a, 0xca, 0x2c, 0x39, 0xa9, + 0x43, 0x42, 0x11, 0x57, 0x36, 0x17, 0x17, 0xc4, + 0x9d, 0x32, 0x20, 0x28, 0xa7, 0x46, 0x48, 0x11, + 0x3b, 0xd8, 0xc9, 0xd7, 0xec, 0x77, 0xcf, 0x3c, + 0x89, 0xc1, 0xec, 0x87, 0x18, 0xce, 0xff, 0x85, + 0x16, 0xd9, 0x6b, 0x34, 0xc3, 0xc6, 0x14, 0xf1, + 0x06, 0x99, 0xc9, 0xab, 0xc4, 0xed, 0x04, 0x11, + 0x50, 0x62, 0x23, 0xbe, 0xa1, 0x6a, 0xf3, 0x5c, + 0x88, 0x3a, 0xcc, 0xdb, 0xe1, 0x10, 0x4e, 0xef, + 0x0c, 0xfd, 0xb5, 0x4e, 0x12, 0xfb, 0x23, 0x0a + ]; + + byte[] expectedCiphertext = [ + 0x32, 0x60, 0xae, 0x8d, 0xad, 0x1f, 0x4a, 0x32, + 0xc5, 0xca, 0xfe, 0x3a, 0xb0, 0xeb, 0x95, 0x54, + 0x9d, 0x46, 0x1a, 0x67, 0xce, 0xb9, 0xe5, 0xaa, + 0x2d, 0x3a, 0xfb, 0x62, 0xde, 0xce, 0x05, 0x53, + 0x19, 0x3b, 0xa5, 0x0c, 0x75, 0xbe, 0x25, 0x1e, + 0x08, 0xd1, 0xd0, 0x8f, 0x10, 0x88, 0x57, 0x6c, + 0x7e, 0xfd, 0xfa, 0xaf, 0x3f, 0x45, 0x95, 0x59, + 0x57, 0x1e, 0x12, 0x51, 0x17, 0x53, 0xb0, 0x7a, + 0xf0, 0x73, 0xf3, 0x5d, 0xa0, 0x6a, 0xf0, 0xce, + 0x0b, 0xbf, 0x6b, 0x8f, 0x5c, 0xcc, 0x5c, 0xea, + 0x50, 0x0e, 0xc1, 0xb2, 0x11, 0xbd, 0x51, 0xf6, + 0x3b, 0x60, 0x6b, 0xf6, 0x52, 0x87, 0x96, 0xca, + 0x12, 0x17, 0x3b, 0xa3, 0x9b, 0x89, 0x35, 0xee, + 0x44, 0xcc, 0xce, 0x64, 0x6f, 0x90, 0xa4, 0x5b, + 0xf9, 0xcc, 0xc5, 0x67, 0xf0, 0xac, 0xe1, 0x3d, + 0xc2, 0xd5, 0x3e, 0xbe, 0xed, 0xc8, 0x1f, 0x58, + 0xb2, 0xe4, 0x11, 0x79, 0xdd, 0xdf, 0x0d, 0x5a, + 0x5c, 0x42, 0xf5, 0xd8, 0x50, 0x6c, 0x1a, 0x5d, + 0x2f, 0x8f, 0x59, 0xf3, 0xea, 0x87, 0x3c, 0xbc, + 0xd0, 0xee, 0xc1, 0x9a, 0xcb, 0xf3, 0x25, 0x42, + 0x3b, 0xd3, 0xdc, 0xb8, 0xc2, 0xb1, 0xbf, 0x1d, + 0x1e, 0xae, 0xd0, 0xeb, 0xa7, 0xf0, 0x69, 0x8e, + 0x43, 0x14, 0xfb, 0xeb, 0x2f, 0x15, 0x66, 0xd1, + 0xb9, 0x25, 0x30, 0x08, 0xcb, 0xcc, 0xf4, 0x5a, + 0x2b, 0x0d, 0x9c, 0x5c, 0x9c, 0x21, 0x47, 0x4f, + 0x40, 0x76, 0xe0, 0x2b, 0xe2, 0x60, 0x50, 0xb9, + 0x9d, 0xee, 0x4f, 0xd6, 0x8a, 0x4c, 0xf8, 0x90, + 0xe4, 0x96, 0xe4, 0xfc, 0xae, 0x7b, 0x70, 0xf9, + 0x4e, 0xa5, 0xa9, 0x06, 0x2d, 0xa0, 0xda, 0xeb, + 0xa1, 0x99, 0x3d, 0x2c, 0xcd, 0x1d, 0xd3, 0xc2, + 0x44, 0xb8, 0x42, 0x88, 0x01, 0x49, 0x5a, 0x58, + 0xb2, 0x16, 0x54, 0x7e, 0x7e, 0x84, 0x7c, 0x46, + 0xd1, 0xd7, 0x56, 0x37, 0x7b, 0x62, 0x42, 0xd2, + 0xe5, 0xfb, 0x83, 0xbf, 0x75, 0x2b, 0x54, 0xe0, + 0xdf, 0x71, 0xe8, 0x89, 0xf3, 0xa2, 0xbb, 0x0f, + 0x4c, 0x10, 0x80, 0x5b, 0xf3, 0xc5, 0x90, 0x37, + 0x6e, 0x3c, 0x24, 0xe2, 0x2f, 0xf5, 0x7f, 0x7f, + 0xa9, 0x65, 0x57, 0x73, 0x75, 0x32, 0x5c, 0xea, + 0x5d, 0x92, 0x0d, 0xb9, 0x4b, 0x9c, 0x33, 0x6b, + 0x45, 0x5f, 0x6e, 0x89, 0x4c, 0x01, 0x86, 0x6f, + 0xe9, 0xfb, 0xb8, 0xc8, 0xd3, 0xf7, 0x0a, 0x29, + 0x57, 0x28, 0x5f, 0x6d, 0xfb, 0x5d, 0xcd, 0x8c, + 0xbf, 0x54, 0x78, 0x2f, 0x8f, 0xe7, 0x76, 0x6d, + 0x47, 0x23, 0x81, 0x99, 0x13, 0xac, 0x77, 0x34, + 0x21, 0xe3, 0xa3, 0x10, 0x95, 0x86, 0x6b, 0xad, + 0x22, 0xc8, 0x6a, 0x60, 0x36, 0xb2, 0x51, 0x8b, + 0x20, 0x59, 0xb4, 0x22, 0x9d, 0x18, 0xc8, 0xc2, + 0xcc, 0xbd, 0xf9, 0x06, 0xc6, 0xcc, 0x6e, 0x82, + 0x46, 0x4e, 0xe5, 0x7b, 0xdd, 0xb0, 0xbe, 0xbc, + 0xb1, 0xdc, 0x64, 0x53, 0x25, 0xbf, 0xb3, 0xe6, + 0x65, 0xef, 0x72, 0x51, 0x08, 0x2c, 0x88, 0xeb, + 0xb1, 0xcf, 0x20, 0x3b, 0xd7, 0x79, 0xfd, 0xd3, + 0x86, 0x75, 0x71, 0x3c, 0x8d, 0xaa, 0xdd, 0x17, + 0xe1, 0xca, 0xbe, 0xe4, 0x32, 0xb0, 0x97, 0x87, + 0xb6, 0xdd, 0xf3, 0x30, 0x4e, 0x38, 0xb7, 0x31, + 0xb4, 0x5d, 0xf5, 0xdf, 0x51, 0xb7, 0x8f, 0xcf, + 0xb3, 0xd3, 0x24, 0x66, 0x02, 0x8d, 0x0b, 0xa3, + 0x65, 0x55, 0xe7, 0xe1, 0x1a, 0xb0, 0xee, 0x06, + 0x66, 0x06, 0x1d, 0x16, 0x45, 0xd9, 0x62, 0x44, + 0x4b, 0xc4, 0x7a, 0x38, 0x18, 0x89, 0x30, 0xa8, + 0x4b, 0x4d, 0x56, 0x13, 0x95, 0xc7, 0x3c, 0x08, + 0x70, 0x21, 0x92, 0x7c, 0xa6, 0x38, 0xb7, 0xaf, + 0xc8, 0xa8, 0x67, 0x9c, 0xcb, 0x84, 0xc2, 0x65, + 0x55, 0x44, 0x0e, 0xc7, 0xf1, 0x04, 0x45, 0xcd + ]; + + SymmetricAlgorithm aes = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + + aes.EncryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); + + aes.DecryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } + + [Test] + public void Vector10Test() + { + byte[] key = [ + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, + 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, + 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27, + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, + 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, + 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 + ]; + + ulong sector = 0xff; + + byte[] expectedPlaintext = [ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + ]; + + byte[] expectedCiphertext = [ + 0x1c, 0x3b, 0x3a, 0x10, 0x2f, 0x77, 0x03, 0x86, + 0xe4, 0x83, 0x6c, 0x99, 0xe3, 0x70, 0xcf, 0x9b, + 0xea, 0x00, 0x80, 0x3f, 0x5e, 0x48, 0x23, 0x57, + 0xa4, 0xae, 0x12, 0xd4, 0x14, 0xa3, 0xe6, 0x3b, + 0x5d, 0x31, 0xe2, 0x76, 0xf8, 0xfe, 0x4a, 0x8d, + 0x66, 0xb3, 0x17, 0xf9, 0xac, 0x68, 0x3f, 0x44, + 0x68, 0x0a, 0x86, 0xac, 0x35, 0xad, 0xfc, 0x33, + 0x45, 0xbe, 0xfe, 0xcb, 0x4b, 0xb1, 0x88, 0xfd, + 0x57, 0x76, 0x92, 0x6c, 0x49, 0xa3, 0x09, 0x5e, + 0xb1, 0x08, 0xfd, 0x10, 0x98, 0xba, 0xec, 0x70, + 0xaa, 0xa6, 0x69, 0x99, 0xa7, 0x2a, 0x82, 0xf2, + 0x7d, 0x84, 0x8b, 0x21, 0xd4, 0xa7, 0x41, 0xb0, + 0xc5, 0xcd, 0x4d, 0x5f, 0xff, 0x9d, 0xac, 0x89, + 0xae, 0xba, 0x12, 0x29, 0x61, 0xd0, 0x3a, 0x75, + 0x71, 0x23, 0xe9, 0x87, 0x0f, 0x8a, 0xcf, 0x10, + 0x00, 0x02, 0x08, 0x87, 0x89, 0x14, 0x29, 0xca, + 0x2a, 0x3e, 0x7a, 0x7d, 0x7d, 0xf7, 0xb1, 0x03, + 0x55, 0x16, 0x5c, 0x8b, 0x9a, 0x6d, 0x0a, 0x7d, + 0xe8, 0xb0, 0x62, 0xc4, 0x50, 0x0d, 0xc4, 0xcd, + 0x12, 0x0c, 0x0f, 0x74, 0x18, 0xda, 0xe3, 0xd0, + 0xb5, 0x78, 0x1c, 0x34, 0x80, 0x3f, 0xa7, 0x54, + 0x21, 0xc7, 0x90, 0xdf, 0xe1, 0xde, 0x18, 0x34, + 0xf2, 0x80, 0xd7, 0x66, 0x7b, 0x32, 0x7f, 0x6c, + 0x8c, 0xd7, 0x55, 0x7e, 0x12, 0xac, 0x3a, 0x0f, + 0x93, 0xec, 0x05, 0xc5, 0x2e, 0x04, 0x93, 0xef, + 0x31, 0xa1, 0x2d, 0x3d, 0x92, 0x60, 0xf7, 0x9a, + 0x28, 0x9d, 0x6a, 0x37, 0x9b, 0xc7, 0x0c, 0x50, + 0x84, 0x14, 0x73, 0xd1, 0xa8, 0xcc, 0x81, 0xec, + 0x58, 0x3e, 0x96, 0x45, 0xe0, 0x7b, 0x8d, 0x96, + 0x70, 0x65, 0x5b, 0xa5, 0xbb, 0xcf, 0xec, 0xc6, + 0xdc, 0x39, 0x66, 0x38, 0x0a, 0xd8, 0xfe, 0xcb, + 0x17, 0xb6, 0xba, 0x02, 0x46, 0x9a, 0x02, 0x0a, + 0x84, 0xe1, 0x8e, 0x8f, 0x84, 0x25, 0x20, 0x70, + 0xc1, 0x3e, 0x9f, 0x1f, 0x28, 0x9b, 0xe5, 0x4f, + 0xbc, 0x48, 0x14, 0x57, 0x77, 0x8f, 0x61, 0x60, + 0x15, 0xe1, 0x32, 0x7a, 0x02, 0xb1, 0x40, 0xf1, + 0x50, 0x5e, 0xb3, 0x09, 0x32, 0x6d, 0x68, 0x37, + 0x8f, 0x83, 0x74, 0x59, 0x5c, 0x84, 0x9d, 0x84, + 0xf4, 0xc3, 0x33, 0xec, 0x44, 0x23, 0x88, 0x51, + 0x43, 0xcb, 0x47, 0xbd, 0x71, 0xc5, 0xed, 0xae, + 0x9b, 0xe6, 0x9a, 0x2f, 0xfe, 0xce, 0xb1, 0xbe, + 0xc9, 0xde, 0x24, 0x4f, 0xbe, 0x15, 0x99, 0x2b, + 0x11, 0xb7, 0x7c, 0x04, 0x0f, 0x12, 0xbd, 0x8f, + 0x6a, 0x97, 0x5a, 0x44, 0xa0, 0xf9, 0x0c, 0x29, + 0xa9, 0xab, 0xc3, 0xd4, 0xd8, 0x93, 0x92, 0x72, + 0x84, 0xc5, 0x87, 0x54, 0xcc, 0xe2, 0x94, 0x52, + 0x9f, 0x86, 0x14, 0xdc, 0xd2, 0xab, 0xa9, 0x91, + 0x92, 0x5f, 0xed, 0xc4, 0xae, 0x74, 0xff, 0xac, + 0x6e, 0x33, 0x3b, 0x93, 0xeb, 0x4a, 0xff, 0x04, + 0x79, 0xda, 0x9a, 0x41, 0x0e, 0x44, 0x50, 0xe0, + 0xdd, 0x7a, 0xe4, 0xc6, 0xe2, 0x91, 0x09, 0x00, + 0x57, 0x5d, 0xa4, 0x01, 0xfc, 0x07, 0x05, 0x9f, + 0x64, 0x5e, 0x8b, 0x7e, 0x9b, 0xfd, 0xef, 0x33, + 0x94, 0x30, 0x54, 0xff, 0x84, 0x01, 0x14, 0x93, + 0xc2, 0x7b, 0x34, 0x29, 0xea, 0xed, 0xb4, 0xed, + 0x53, 0x76, 0x44, 0x1a, 0x77, 0xed, 0x43, 0x85, + 0x1a, 0xd7, 0x7f, 0x16, 0xf5, 0x41, 0xdf, 0xd2, + 0x69, 0xd5, 0x0d, 0x6a, 0x5f, 0x14, 0xfb, 0x0a, + 0xab, 0x1c, 0xbb, 0x4c, 0x15, 0x50, 0xbe, 0x97, + 0xf7, 0xab, 0x40, 0x66, 0x19, 0x3c, 0x4c, 0xaa, + 0x77, 0x3d, 0xad, 0x38, 0x01, 0x4b, 0xd2, 0x09, + 0x2f, 0xa7, 0x55, 0xc8, 0x24, 0xbb, 0x5e, 0x54, + 0xc4, 0xf3, 0x6f, 0xfd, 0xa9, 0xfc, 0xea, 0x70, + 0xb9, 0xc6, 0xe6, 0x93, 0xe1, 0x48, 0xc1, 0x51 + ]; + + SymmetricAlgorithm aes = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + + aes.EncryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); + + aes.DecryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } + + [Test] + public void Vector11Test() + { + byte[] key = [ + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, + 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, + 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27, + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, + 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, + 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 + ]; + + ulong sector = 0xffff; + + byte[] expectedPlaintext = [ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + ]; + + byte[] expectedCiphertext = [ + 0x77, 0xa3, 0x12, 0x51, 0x61, 0x8a, 0x15, 0xe6, + 0xb9, 0x2d, 0x1d, 0x66, 0xdf, 0xfe, 0x7b, 0x50, + 0xb5, 0x0b, 0xad, 0x55, 0x23, 0x05, 0xba, 0x02, + 0x17, 0xa6, 0x10, 0x68, 0x8e, 0xff, 0x7e, 0x11, + 0xe1, 0xd0, 0x22, 0x54, 0x38, 0xe0, 0x93, 0x24, + 0x2d, 0x6d, 0xb2, 0x74, 0xfd, 0xe8, 0x01, 0xd4, + 0xca, 0xe0, 0x6f, 0x20, 0x92, 0xc7, 0x28, 0xb2, + 0x47, 0x85, 0x59, 0xdf, 0x58, 0xe8, 0x37, 0xc2, + 0x46, 0x9e, 0xe4, 0xa4, 0xfa, 0x79, 0x4e, 0x4b, + 0xbc, 0x7f, 0x39, 0xbc, 0x02, 0x6e, 0x3c, 0xb7, + 0x2c, 0x33, 0xb0, 0x88, 0x8f, 0x25, 0xb4, 0xac, + 0xf5, 0x6a, 0x2a, 0x98, 0x04, 0xf1, 0xce, 0x6d, + 0x3d, 0x6e, 0x1d, 0xc6, 0xca, 0x18, 0x1d, 0x4b, + 0x54, 0x61, 0x79, 0xd5, 0x55, 0x44, 0xaa, 0x77, + 0x60, 0xc4, 0x0d, 0x06, 0x74, 0x15, 0x39, 0xc7, + 0xe3, 0xcd, 0x9d, 0x2f, 0x66, 0x50, 0xb2, 0x01, + 0x3f, 0xd0, 0xee, 0xb8, 0xc2, 0xb8, 0xe3, 0xd8, + 0xd2, 0x40, 0xcc, 0xae, 0x2d, 0x4c, 0x98, 0x32, + 0x0a, 0x74, 0x42, 0xe1, 0xc8, 0xd7, 0x5a, 0x42, + 0xd6, 0xe6, 0xcf, 0xa4, 0xc2, 0xec, 0xa1, 0x79, + 0x8d, 0x15, 0x8c, 0x7a, 0xec, 0xdf, 0x82, 0x49, + 0x0f, 0x24, 0xbb, 0x9b, 0x38, 0xe1, 0x08, 0xbc, + 0xda, 0x12, 0xc3, 0xfa, 0xf9, 0xa2, 0x11, 0x41, + 0xc3, 0x61, 0x3b, 0x58, 0x36, 0x7f, 0x92, 0x2a, + 0xaa, 0x26, 0xcd, 0x22, 0xf2, 0x3d, 0x70, 0x8d, + 0xae, 0x69, 0x9a, 0xd7, 0xcb, 0x40, 0xa8, 0xad, + 0x0b, 0x6e, 0x27, 0x84, 0x97, 0x3d, 0xcb, 0x60, + 0x56, 0x84, 0xc0, 0x8b, 0x8d, 0x69, 0x98, 0xc6, + 0x9a, 0xac, 0x04, 0x99, 0x21, 0x87, 0x1e, 0xbb, + 0x65, 0x30, 0x1a, 0x46, 0x19, 0xca, 0x80, 0xec, + 0xb4, 0x85, 0xa3, 0x1d, 0x74, 0x42, 0x23, 0xce, + 0x8d, 0xdc, 0x23, 0x94, 0x82, 0x8d, 0x6a, 0x80, + 0x47, 0x0c, 0x09, 0x2f, 0x5b, 0xa4, 0x13, 0xc3, + 0x37, 0x8f, 0xa6, 0x05, 0x42, 0x55, 0xc6, 0xf9, + 0xdf, 0x44, 0x95, 0x86, 0x2b, 0xbb, 0x32, 0x87, + 0x68, 0x1f, 0x93, 0x1b, 0x68, 0x7c, 0x88, 0x8a, + 0xbf, 0x84, 0x4d, 0xfc, 0x8f, 0xc2, 0x83, 0x31, + 0xe5, 0x79, 0x92, 0x8c, 0xd1, 0x2b, 0xd2, 0x39, + 0x0a, 0xe1, 0x23, 0xcf, 0x03, 0x81, 0x8d, 0x14, + 0xde, 0xdd, 0xe5, 0xc0, 0xc2, 0x4c, 0x8a, 0xb0, + 0x18, 0xbf, 0xca, 0x75, 0xca, 0x09, 0x6f, 0x2d, + 0x53, 0x1f, 0x3d, 0x16, 0x19, 0xe7, 0x85, 0xf1, + 0xad, 0xa4, 0x37, 0xca, 0xb9, 0x2e, 0x98, 0x05, + 0x58, 0xb3, 0xdc, 0xe1, 0x47, 0x4a, 0xfb, 0x75, + 0xbf, 0xed, 0xbf, 0x8f, 0xf5, 0x4c, 0xb2, 0x61, + 0x8e, 0x02, 0x44, 0xc9, 0xac, 0x0d, 0x3c, 0x66, + 0xfb, 0x51, 0x59, 0x8c, 0xd2, 0xdb, 0x11, 0xf9, + 0xbe, 0x39, 0x79, 0x1a, 0xbe, 0x44, 0x7c, 0x63, + 0x09, 0x4f, 0x7c, 0x45, 0x3b, 0x7f, 0xf8, 0x7c, + 0xb5, 0xbb, 0x36, 0xb7, 0xc7, 0x9e, 0xfb, 0x08, + 0x72, 0xd1, 0x70, 0x58, 0xb8, 0x3b, 0x15, 0xab, + 0x08, 0x66, 0xad, 0x8a, 0x58, 0x65, 0x6c, 0x5a, + 0x7e, 0x20, 0xdb, 0xdf, 0x30, 0x8b, 0x24, 0x61, + 0xd9, 0x7c, 0x0e, 0xc0, 0x02, 0x4a, 0x27, 0x15, + 0x05, 0x52, 0x49, 0xcf, 0x3b, 0x47, 0x8d, 0xdd, + 0x47, 0x40, 0xde, 0x65, 0x4f, 0x75, 0xca, 0x68, + 0x6e, 0x0d, 0x73, 0x45, 0xc6, 0x9e, 0xd5, 0x0c, + 0xdc, 0x2a, 0x8b, 0x33, 0x2b, 0x1f, 0x88, 0x24, + 0x10, 0x8a, 0xc9, 0x37, 0xeb, 0x05, 0x05, 0x85, + 0x60, 0x8e, 0xe7, 0x34, 0x09, 0x7f, 0xc0, 0x90, + 0x54, 0xfb, 0xff, 0x89, 0xee, 0xae, 0xea, 0x79, + 0x1f, 0x4a, 0x7a, 0xb1, 0xf9, 0x86, 0x82, 0x94, + 0xa4, 0xf9, 0xe2, 0x7b, 0x42, 0xaf, 0x81, 0x00, + 0xcb, 0x9d, 0x59, 0xce, 0xf9, 0x64, 0x58, 0x03 + ]; + + SymmetricAlgorithm aes = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + + aes.EncryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); + + aes.DecryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } + + [Test] + public void Vector12Test() + { + byte[] key = [ + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, + 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, + 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27, + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, + 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, + 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 + ]; + + ulong sector = 0xffffff; + + byte[] expectedPlaintext = [ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + ]; + + byte[] expectedCiphertext = [ + 0xe3, 0x87, 0xaa, 0xa5, 0x8b, 0xa4, 0x83, 0xaf, + 0xa7, 0xe8, 0xeb, 0x46, 0x97, 0x78, 0x31, 0x7e, + 0xcf, 0x4c, 0xf5, 0x73, 0xaa, 0x9d, 0x4e, 0xac, + 0x23, 0xf2, 0xcd, 0xf9, 0x14, 0xe4, 0xe2, 0x00, + 0xa8, 0xb4, 0x90, 0xe4, 0x2e, 0xe6, 0x46, 0x80, + 0x2d, 0xc6, 0xee, 0x2b, 0x47, 0x1b, 0x27, 0x81, + 0x95, 0xd6, 0x09, 0x18, 0xec, 0xec, 0xb4, 0x4b, + 0xf7, 0x99, 0x66, 0xf8, 0x3f, 0xab, 0xa0, 0x49, + 0x92, 0x98, 0xeb, 0xc6, 0x99, 0xc0, 0xc8, 0x63, + 0x47, 0x15, 0xa3, 0x20, 0xbb, 0x4f, 0x07, 0x5d, + 0x62, 0x2e, 0x74, 0xc8, 0xc9, 0x32, 0x00, 0x4f, + 0x25, 0xb4, 0x1e, 0x36, 0x10, 0x25, 0xb5, 0xa8, + 0x78, 0x15, 0x39, 0x1f, 0x61, 0x08, 0xfc, 0x4a, + 0xfa, 0x6a, 0x05, 0xd9, 0x30, 0x3c, 0x6b, 0xa6, + 0x8a, 0x12, 0x8a, 0x55, 0x70, 0x5d, 0x41, 0x59, + 0x85, 0x83, 0x2f, 0xde, 0xaa, 0xe6, 0xc8, 0xe1, + 0x91, 0x10, 0xe8, 0x4d, 0x1b, 0x1f, 0x19, 0x9a, + 0x26, 0x92, 0x11, 0x9e, 0xdc, 0x96, 0x13, 0x26, + 0x58, 0xf0, 0x9d, 0xa7, 0xc6, 0x23, 0xef, 0xce, + 0xc7, 0x12, 0x53, 0x7a, 0x3d, 0x94, 0xc0, 0xbf, + 0x5d, 0x7e, 0x35, 0x2e, 0xc9, 0x4a, 0xe5, 0x79, + 0x7f, 0xdb, 0x37, 0x7d, 0xc1, 0x55, 0x11, 0x50, + 0x72, 0x1a, 0xdf, 0x15, 0xbd, 0x26, 0xa8, 0xef, + 0xc2, 0xfc, 0xaa, 0xd5, 0x68, 0x81, 0xfa, 0x9e, + 0x62, 0x46, 0x2c, 0x28, 0xf3, 0x0a, 0xe1, 0xce, + 0xac, 0xa9, 0x3c, 0x34, 0x5c, 0xf2, 0x43, 0xb7, + 0x3f, 0x54, 0x2e, 0x20, 0x74, 0xa7, 0x05, 0xbd, + 0x26, 0x43, 0xbb, 0x9f, 0x7c, 0xc7, 0x9b, 0xb6, + 0xe7, 0x09, 0x1e, 0xa6, 0xe2, 0x32, 0xdf, 0x0f, + 0x9a, 0xd0, 0xd6, 0xcf, 0x50, 0x23, 0x27, 0x87, + 0x6d, 0x82, 0x20, 0x7a, 0xbf, 0x21, 0x15, 0xcd, + 0xac, 0xf6, 0xd5, 0xa4, 0x8f, 0x6c, 0x18, 0x79, + 0xa6, 0x5b, 0x11, 0x5f, 0x0f, 0x8b, 0x3c, 0xb3, + 0xc5, 0x9d, 0x15, 0xdd, 0x8c, 0x76, 0x9b, 0xc0, + 0x14, 0x79, 0x5a, 0x18, 0x37, 0xf3, 0x90, 0x1b, + 0x58, 0x45, 0xeb, 0x49, 0x1a, 0xdf, 0xef, 0xe0, + 0x97, 0xb1, 0xfa, 0x30, 0xa1, 0x2f, 0xc1, 0xf6, + 0x5b, 0xa2, 0x29, 0x05, 0x03, 0x15, 0x39, 0x97, + 0x1a, 0x10, 0xf2, 0xf3, 0x6c, 0x32, 0x1b, 0xb5, + 0x13, 0x31, 0xcd, 0xef, 0xb3, 0x9e, 0x39, 0x64, + 0xc7, 0xef, 0x07, 0x99, 0x94, 0xf5, 0xb6, 0x9b, + 0x2e, 0xdd, 0x83, 0xa7, 0x1e, 0xf5, 0x49, 0x97, + 0x1e, 0xe9, 0x3f, 0x44, 0xea, 0xc3, 0x93, 0x8f, + 0xcd, 0xd6, 0x1d, 0x01, 0xfa, 0x71, 0x79, 0x9d, + 0xa3, 0xa8, 0x09, 0x1c, 0x4c, 0x48, 0xaa, 0x9e, + 0xd2, 0x63, 0xff, 0x07, 0x49, 0xdf, 0x95, 0xd4, + 0x4f, 0xef, 0x6a, 0x0b, 0xb5, 0x78, 0xec, 0x69, + 0x45, 0x6a, 0xa5, 0x40, 0x8a, 0xe3, 0x2c, 0x7a, + 0xf0, 0x8a, 0xd7, 0xba, 0x89, 0x21, 0x28, 0x7e, + 0x3b, 0xbe, 0xe3, 0x1b, 0x76, 0x7b, 0xe0, 0x6a, + 0x0e, 0x70, 0x5c, 0x86, 0x4a, 0x76, 0x91, 0x37, + 0xdf, 0x28, 0x29, 0x22, 0x83, 0xea, 0x81, 0xa2, + 0x48, 0x02, 0x41, 0xb4, 0x4d, 0x99, 0x21, 0xcd, + 0xbe, 0xc1, 0xbc, 0x28, 0xdc, 0x1f, 0xda, 0x11, + 0x4b, 0xd8, 0xe5, 0x21, 0x7a, 0xc9, 0xd8, 0xeb, + 0xaf, 0xa7, 0x20, 0xe9, 0xda, 0x4f, 0x9a, 0xce, + 0x23, 0x1c, 0xc9, 0x49, 0xe5, 0xb9, 0x6f, 0xe7, + 0x6f, 0xfc, 0x21, 0x06, 0x3f, 0xdd, 0xc8, 0x3a, + 0x6b, 0x86, 0x79, 0xc0, 0x0d, 0x35, 0xe0, 0x95, + 0x76, 0xa8, 0x75, 0x30, 0x5b, 0xed, 0x5f, 0x36, + 0xed, 0x24, 0x2c, 0x89, 0x00, 0xdd, 0x1f, 0xa9, + 0x65, 0xbc, 0x95, 0x0d, 0xfc, 0xe0, 0x9b, 0x13, + 0x22, 0x63, 0xa1, 0xee, 0xf5, 0x2d, 0xd6, 0x88, + 0x8c, 0x30, 0x9f, 0x5a, 0x7d, 0x71, 0x28, 0x26 + ]; + + SymmetricAlgorithm aes = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + + aes.EncryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); + + aes.DecryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } + + [Test] + public void Vector13Test() + { + byte[] key = [ + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, + 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, + 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27, + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, + 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, + 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 + ]; + + ulong sector = 0xffffffff; + + byte[] expectedPlaintext = [ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + ]; + + byte[] expectedCiphertext = [ + 0xbf, 0x53, 0xd2, 0xda, 0xde, 0x78, 0xe8, 0x22, + 0xa4, 0xd9, 0x49, 0xa9, 0xbc, 0x67, 0x66, 0xb0, + 0x1b, 0x06, 0xa8, 0xef, 0x70, 0xd2, 0x67, 0x48, + 0xc6, 0xa7, 0xfc, 0x36, 0xd8, 0x0a, 0xe4, 0xc5, + 0x52, 0x0f, 0x7c, 0x4a, 0xb0, 0xac, 0x85, 0x44, + 0x42, 0x4f, 0xa4, 0x05, 0x16, 0x2f, 0xef, 0x5a, + 0x6b, 0x7f, 0x22, 0x94, 0x98, 0x06, 0x36, 0x18, + 0xd3, 0x9f, 0x00, 0x03, 0xcb, 0x5f, 0xb8, 0xd1, + 0xc8, 0x6b, 0x64, 0x34, 0x97, 0xda, 0x1f, 0xf9, + 0x45, 0xc8, 0xd3, 0xbe, 0xde, 0xca, 0x4f, 0x47, + 0x97, 0x02, 0xa7, 0xa7, 0x35, 0xf0, 0x43, 0xdd, + 0xb1, 0xd6, 0xaa, 0xad, 0xe3, 0xc4, 0xa0, 0xac, + 0x7c, 0xa7, 0xf3, 0xfa, 0x52, 0x79, 0xbe, 0xf5, + 0x6f, 0x82, 0xcd, 0x7a, 0x2f, 0x38, 0x67, 0x2e, + 0x82, 0x48, 0x14, 0xe1, 0x07, 0x00, 0x30, 0x0a, + 0x05, 0x5e, 0x16, 0x30, 0xb8, 0xf1, 0xcb, 0x0e, + 0x91, 0x9f, 0x5e, 0x94, 0x20, 0x10, 0xa4, 0x16, + 0xe2, 0xbf, 0x48, 0xcb, 0x46, 0x99, 0x3d, 0x3c, + 0xb6, 0xa5, 0x1c, 0x19, 0xba, 0xcf, 0x86, 0x47, + 0x85, 0xa0, 0x0b, 0xc2, 0xec, 0xff, 0x15, 0xd3, + 0x50, 0x87, 0x5b, 0x24, 0x6e, 0xd5, 0x3e, 0x68, + 0xbe, 0x6f, 0x55, 0xbd, 0x7e, 0x05, 0xcf, 0xc2, + 0xb2, 0xed, 0x64, 0x32, 0x19, 0x8a, 0x64, 0x44, + 0xb6, 0xd8, 0xc2, 0x47, 0xfa, 0xb9, 0x41, 0xf5, + 0x69, 0x76, 0x8b, 0x5c, 0x42, 0x93, 0x66, 0xf1, + 0xd3, 0xf0, 0x0f, 0x03, 0x45, 0xb9, 0x61, 0x23, + 0xd5, 0x62, 0x04, 0xc0, 0x1c, 0x63, 0xb2, 0x2c, + 0xe7, 0x8b, 0xaf, 0x11, 0x6e, 0x52, 0x5e, 0xd9, + 0x0f, 0xde, 0xa3, 0x9f, 0xa4, 0x69, 0x49, 0x4d, + 0x38, 0x66, 0xc3, 0x1e, 0x05, 0xf2, 0x95, 0xff, + 0x21, 0xfe, 0xa8, 0xd4, 0xe6, 0xe1, 0x3d, 0x67, + 0xe4, 0x7c, 0xe7, 0x22, 0xe9, 0x69, 0x8a, 0x1c, + 0x10, 0x48, 0xd6, 0x8e, 0xbc, 0xde, 0x76, 0xb8, + 0x6f, 0xcf, 0x97, 0x6e, 0xab, 0x8a, 0xa9, 0x79, + 0x02, 0x68, 0xb7, 0x06, 0x8e, 0x01, 0x7a, 0x8b, + 0x9b, 0x74, 0x94, 0x09, 0x51, 0x4f, 0x10, 0x53, + 0x02, 0x7f, 0xd1, 0x6c, 0x37, 0x86, 0xea, 0x1b, + 0xac, 0x5f, 0x15, 0xcb, 0x79, 0x71, 0x1e, 0xe2, + 0xab, 0xe8, 0x2f, 0x5c, 0xf8, 0xb1, 0x3a, 0xe7, + 0x30, 0x30, 0xef, 0x5b, 0x9e, 0x44, 0x57, 0xe7, + 0x5d, 0x13, 0x04, 0xf9, 0x88, 0xd6, 0x2d, 0xd6, + 0xfc, 0x4b, 0x94, 0xed, 0x38, 0xba, 0x83, 0x1d, + 0xa4, 0xb7, 0x63, 0x49, 0x71, 0xb6, 0xcd, 0x8e, + 0xc3, 0x25, 0xd9, 0xc6, 0x1c, 0x00, 0xf1, 0xdf, + 0x73, 0x62, 0x7e, 0xd3, 0x74, 0x5a, 0x5e, 0x84, + 0x89, 0xf3, 0xa9, 0x5c, 0x69, 0x63, 0x9c, 0x32, + 0xcd, 0x6e, 0x1d, 0x53, 0x7a, 0x85, 0xf7, 0x5c, + 0xc8, 0x44, 0x72, 0x6e, 0x8a, 0x72, 0xfc, 0x00, + 0x77, 0xad, 0x22, 0x00, 0x0f, 0x1d, 0x50, 0x78, + 0xf6, 0xb8, 0x66, 0x31, 0x8c, 0x66, 0x8f, 0x1a, + 0xd0, 0x3d, 0x5a, 0x5f, 0xce, 0xd5, 0x21, 0x9f, + 0x2e, 0xab, 0xbd, 0x0a, 0xa5, 0xc0, 0xf4, 0x60, + 0xd1, 0x83, 0xf0, 0x44, 0x04, 0xa0, 0xd6, 0xf4, + 0x69, 0x55, 0x8e, 0x81, 0xfa, 0xb2, 0x4a, 0x16, + 0x79, 0x05, 0xab, 0x4c, 0x78, 0x78, 0x50, 0x2a, + 0xd3, 0xe3, 0x8f, 0xdb, 0xe6, 0x2a, 0x41, 0x55, + 0x6c, 0xec, 0x37, 0x32, 0x57, 0x59, 0x53, 0x3c, + 0xe8, 0xf2, 0x5f, 0x36, 0x7c, 0x87, 0xbb, 0x55, + 0x78, 0xd6, 0x67, 0xae, 0x93, 0xf9, 0xe2, 0xfd, + 0x99, 0xbc, 0xbc, 0x5f, 0x2f, 0xbb, 0xa8, 0x8c, + 0xf6, 0x51, 0x61, 0x39, 0x42, 0x0f, 0xcf, 0xf3, + 0xb7, 0x36, 0x1d, 0x86, 0x32, 0x2c, 0x4b, 0xd8, + 0x4c, 0x82, 0xf3, 0x35, 0xab, 0xb1, 0x52, 0xc4, + 0xa9, 0x34, 0x11, 0x37, 0x3a, 0xaa, 0x82, 0x20 + ]; + + SymmetricAlgorithm aes = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + + aes.EncryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); + + aes.DecryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } + + [Test] + public void Vector14Test() + { + byte[] key = [ + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, + 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, + 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27, + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, + 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, + 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 + ]; + + ulong sector = 0xffffffffff; + + byte[] expectedPlaintext = [ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + ]; + + byte[] expectedCiphertext = [ + 0x64, 0x49, 0x7e, 0x5a, 0x83, 0x1e, 0x4a, 0x93, + 0x2c, 0x09, 0xbe, 0x3e, 0x53, 0x93, 0x37, 0x6d, + 0xaa, 0x59, 0x95, 0x48, 0xb8, 0x16, 0x03, 0x1d, + 0x22, 0x4b, 0xbf, 0x50, 0xa8, 0x18, 0xed, 0x23, + 0x50, 0xea, 0xe7, 0xe9, 0x60, 0x87, 0xc8, 0xa0, + 0xdb, 0x51, 0xad, 0x29, 0x0b, 0xd0, 0x0c, 0x1a, + 0xc1, 0x62, 0x08, 0x57, 0x63, 0x5b, 0xf2, 0x46, + 0xc1, 0x76, 0xab, 0x46, 0x3b, 0xe3, 0x0b, 0x80, + 0x8d, 0xa5, 0x48, 0x08, 0x1a, 0xc8, 0x47, 0xb1, + 0x58, 0xe1, 0x26, 0x4b, 0xe2, 0x5b, 0xb0, 0x91, + 0x0b, 0xbc, 0x92, 0x64, 0x71, 0x08, 0x08, 0x94, + 0x15, 0xd4, 0x5f, 0xab, 0x1b, 0x3d, 0x26, 0x04, + 0xe8, 0xa8, 0xef, 0xf1, 0xae, 0x40, 0x20, 0xcf, + 0xa3, 0x99, 0x36, 0xb6, 0x68, 0x27, 0xb2, 0x3f, + 0x37, 0x1b, 0x92, 0x20, 0x0b, 0xe9, 0x02, 0x51, + 0xe6, 0xd7, 0x3c, 0x5f, 0x86, 0xde, 0x5f, 0xd4, + 0xa9, 0x50, 0x78, 0x19, 0x33, 0xd7, 0x9a, 0x28, + 0x27, 0x2b, 0x78, 0x2a, 0x2e, 0xc3, 0x13, 0xef, + 0xdf, 0xcc, 0x06, 0x28, 0xf4, 0x3d, 0x74, 0x4c, + 0x2d, 0xc2, 0xff, 0x3d, 0xcb, 0x66, 0x99, 0x9b, + 0x50, 0xc7, 0xca, 0x89, 0x5b, 0x0c, 0x64, 0x79, + 0x1e, 0xea, 0xa5, 0xf2, 0x94, 0x99, 0xfb, 0x1c, + 0x02, 0x6f, 0x84, 0xce, 0x5b, 0x5c, 0x72, 0xba, + 0x10, 0x83, 0xcd, 0xdb, 0x5c, 0xe4, 0x54, 0x34, + 0x63, 0x16, 0x65, 0xc3, 0x33, 0xb6, 0x0b, 0x11, + 0x59, 0x3f, 0xb2, 0x53, 0xc5, 0x17, 0x9a, 0x2c, + 0x8d, 0xb8, 0x13, 0x78, 0x2a, 0x00, 0x48, 0x56, + 0xa1, 0x65, 0x30, 0x11, 0xe9, 0x3f, 0xb6, 0xd8, + 0x76, 0xc1, 0x83, 0x66, 0xdd, 0x86, 0x83, 0xf5, + 0x34, 0x12, 0xc0, 0xc1, 0x80, 0xf9, 0xc8, 0x48, + 0x59, 0x2d, 0x59, 0x3f, 0x86, 0x09, 0xca, 0x73, + 0x63, 0x17, 0xd3, 0x56, 0xe1, 0x3e, 0x2b, 0xff, + 0x3a, 0x9f, 0x59, 0xcd, 0x9a, 0xeb, 0x19, 0xcd, + 0x48, 0x25, 0x93, 0xd8, 0xc4, 0x61, 0x28, 0xbb, + 0x32, 0x42, 0x3b, 0x37, 0xa9, 0xad, 0xfb, 0x48, + 0x2b, 0x99, 0x45, 0x3f, 0xbe, 0x25, 0xa4, 0x1b, + 0xf6, 0xfe, 0xb4, 0xaa, 0x0b, 0xef, 0x5e, 0xd2, + 0x4b, 0xf7, 0x3c, 0x76, 0x29, 0x78, 0x02, 0x54, + 0x82, 0xc1, 0x31, 0x15, 0xe4, 0x01, 0x5a, 0xac, + 0x99, 0x2e, 0x56, 0x13, 0xa3, 0xb5, 0xc2, 0xf6, + 0x85, 0xb8, 0x47, 0x95, 0xcb, 0x6e, 0x9b, 0x26, + 0x56, 0xd8, 0xc8, 0x81, 0x57, 0xe5, 0x2c, 0x42, + 0xf9, 0x78, 0xd8, 0x63, 0x4c, 0x43, 0xd0, 0x6f, + 0xea, 0x92, 0x8f, 0x28, 0x22, 0xe4, 0x65, 0xaa, + 0x65, 0x76, 0xe9, 0xbf, 0x41, 0x93, 0x84, 0x50, + 0x6c, 0xc3, 0xce, 0x3c, 0x54, 0xac, 0x1a, 0x6f, + 0x67, 0xdc, 0x66, 0xf3, 0xb3, 0x01, 0x91, 0xe6, + 0x98, 0x38, 0x0b, 0xc9, 0x99, 0xb0, 0x5a, 0xbc, + 0xe1, 0x9d, 0xc0, 0xc6, 0xdc, 0xc2, 0xdd, 0x00, + 0x1e, 0xc5, 0x35, 0xba, 0x18, 0xde, 0xb2, 0xdf, + 0x1a, 0x10, 0x10, 0x23, 0x10, 0x83, 0x18, 0xc7, + 0x5d, 0xc9, 0x86, 0x11, 0xa0, 0x9d, 0xc4, 0x8a, + 0x0a, 0xcd, 0xec, 0x67, 0x6f, 0xab, 0xdf, 0x22, + 0x2f, 0x07, 0xe0, 0x26, 0xf0, 0x59, 0xb6, 0x72, + 0xb5, 0x6e, 0x5c, 0xbc, 0x8e, 0x1d, 0x21, 0xbb, + 0xd8, 0x67, 0xdd, 0x92, 0x72, 0x12, 0x05, 0x46, + 0x81, 0xd7, 0x0e, 0xa7, 0x37, 0x13, 0x4c, 0xdf, + 0xce, 0x93, 0xb6, 0xf8, 0x2a, 0xe2, 0x24, 0x23, + 0x27, 0x4e, 0x58, 0xa0, 0x82, 0x1c, 0xc5, 0x50, + 0x2e, 0x2d, 0x0a, 0xb4, 0x58, 0x5e, 0x94, 0xde, + 0x69, 0x75, 0xbe, 0x5e, 0x0b, 0x4e, 0xfc, 0xe5, + 0x1c, 0xd3, 0xe7, 0x0c, 0x25, 0xa1, 0xfb, 0xbb, + 0xd6, 0x09, 0xd2, 0x73, 0xad, 0x5b, 0x0d, 0x59, + 0x63, 0x1c, 0x53, 0x1f, 0x6a, 0x0a, 0x57, 0xb9 + ]; + + SymmetricAlgorithm aes = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + + aes.EncryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); + + aes.DecryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } + + [Test] + public void Vector15Test() + { + byte[] key = [ + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, + 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, + 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0 + ]; + + ulong sector = 0x123456789a; + + byte[] expectedPlaintext = [ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10 + ]; + + byte[] expectedCiphertext = [ + 0x6c, 0x16, 0x25, 0xdb, 0x46, 0x71, 0x52, 0x2d, + 0x3d, 0x75, 0x99, 0x60, 0x1d, 0xe7, 0xca, 0x09, + 0xed + ]; + + SymmetricAlgorithm aes = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + + aes.EncryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); + + aes.DecryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } + + [Test] + public void Vector16Test() + { + byte[] key = [ + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, + 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, + 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0 + ]; + + ulong sector = 0x123456789a; + + byte[] expectedPlaintext = [ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11 + ]; + + byte[] expectedCiphertext = [ + 0xd0, 0x69, 0x44, 0x4b, 0x7a, 0x7e, 0x0c, 0xab, + 0x09, 0xe2, 0x44, 0x47, 0xd2, 0x4d, 0xeb, 0x1f, + 0xed, 0xbf + ]; + + SymmetricAlgorithm aes = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + + aes.EncryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); + + aes.DecryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } + + [Test] + public void Vector17Test() + { + byte[] key = [ + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, + 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, + 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0 + ]; + + ulong sector = 0x123456789a; + + byte[] expectedPlaintext = [ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12 + ]; + + byte[] expectedCiphertext = [ + 0xe5, 0xdf, 0x13, 0x51, 0xc0, 0x54, 0x4b, 0xa1, + 0x35, 0x0b, 0x33, 0x63, 0xcd, 0x8e, 0xf4, 0xbe, + 0xed, 0xbf, 0x9d + ]; + + SymmetricAlgorithm aes = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + + aes.EncryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); + + aes.DecryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } + + [Test] + public void Vector18Test() + { + byte[] key = [ + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, + 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, + 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0 + ]; + + ulong sector = 0x123456789a; + + byte[] expectedPlaintext = [ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 + ]; + + byte[] expectedCiphertext = [ + 0x9d, 0x84, 0xc8, 0x13, 0xf7, 0x19, 0xaa, 0x2c, + 0x7b, 0xe3, 0xf6, 0x61, 0x71, 0xc7, 0xc5, 0xc2, + 0xed, 0xbf, 0x9d, 0xac + ]; + + SymmetricAlgorithm aes = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + + aes.EncryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); + + aes.DecryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } + + [Test] + public void Vector19Test() + { + byte[] key = [ + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf + ]; + + ulong sector = 0xa987654321; + + byte[] expectedPlaintext = [ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + ]; + + byte[] expectedCiphertext = [ + 0x38, 0xb4, 0x58, 0x12, 0xef, 0x43, 0xa0, 0x5b, + 0xd9, 0x57, 0xe5, 0x45, 0x90, 0x7e, 0x22, 0x3b, + 0x95, 0x4a, 0xb4, 0xaa, 0xf0, 0x88, 0x30, 0x3a, + 0xd9, 0x10, 0xea, 0xdf, 0x14, 0xb4, 0x2b, 0xe6, + 0x8b, 0x24, 0x61, 0x14, 0x9d, 0x8c, 0x8b, 0xa8, + 0x5f, 0x99, 0x2b, 0xe9, 0x70, 0xbc, 0x62, 0x1f, + 0x1b, 0x06, 0x57, 0x3f, 0x63, 0xe8, 0x67, 0xbf, + 0x58, 0x75, 0xac, 0xaf, 0xa0, 0x4e, 0x42, 0xcc, + 0xbd, 0x7b, 0xd3, 0xc2, 0xa0, 0xfb, 0x1f, 0xff, + 0x79, 0x1e, 0xc5, 0xec, 0x36, 0xc6, 0x6a, 0xe4, + 0xac, 0x1e, 0x80, 0x6d, 0x81, 0xfb, 0xf7, 0x09, + 0xdb, 0xe2, 0x9e, 0x47, 0x1f, 0xad, 0x38, 0x54, + 0x9c, 0x8e, 0x66, 0xf5, 0x34, 0x5d, 0x7c, 0x1e, + 0xb9, 0x4f, 0x40, 0x5d, 0x1e, 0xc7, 0x85, 0xcc, + 0x6f, 0x6a, 0x68, 0xf6, 0x25, 0x4d, 0xd8, 0x33, + 0x9f, 0x9d, 0x84, 0x05, 0x7e, 0x01, 0xa1, 0x77, + 0x41, 0x99, 0x04, 0x82, 0x99, 0x95, 0x16, 0xb5, + 0x61, 0x1a, 0x38, 0xf4, 0x1b, 0xb6, 0x47, 0x8e, + 0x6f, 0x17, 0x3f, 0x32, 0x08, 0x05, 0xdd, 0x71, + 0xb1, 0x93, 0x2f, 0xc3, 0x33, 0xcb, 0x9e, 0xe3, + 0x99, 0x36, 0xbe, 0xea, 0x9a, 0xd9, 0x6f, 0xa1, + 0x0f, 0xb4, 0x11, 0x2b, 0x90, 0x17, 0x34, 0xdd, + 0xad, 0x40, 0xbc, 0x18, 0x78, 0x99, 0x5f, 0x8e, + 0x11, 0xae, 0xe7, 0xd1, 0x41, 0xa2, 0xf5, 0xd4, + 0x8b, 0x7a, 0x4e, 0x1e, 0x7f, 0x0b, 0x2c, 0x04, + 0x83, 0x0e, 0x69, 0xa4, 0xfd, 0x13, 0x78, 0x41, + 0x1c, 0x2f, 0x28, 0x7e, 0xdf, 0x48, 0xc6, 0xc4, + 0xe5, 0xc2, 0x47, 0xa1, 0x96, 0x80, 0xf7, 0xfe, + 0x41, 0xce, 0xfb, 0xd4, 0x9b, 0x58, 0x21, 0x06, + 0xe3, 0x61, 0x6c, 0xbb, 0xe4, 0xdf, 0xb2, 0x34, + 0x4b, 0x2a, 0xe9, 0x51, 0x93, 0x91, 0xf3, 0xe0, + 0xfb, 0x49, 0x22, 0x25, 0x4b, 0x1d, 0x6d, 0x2d, + 0x19, 0xc6, 0xd4, 0xd5, 0x37, 0xb3, 0xa2, 0x6f, + 0x3b, 0xcc, 0x51, 0x58, 0x8b, 0x32, 0xf3, 0xec, + 0xa0, 0x82, 0x9b, 0x6a, 0x5a, 0xc7, 0x25, 0x78, + 0xfb, 0x81, 0x4f, 0xb4, 0x3c, 0xf8, 0x0d, 0x64, + 0xa2, 0x33, 0xe3, 0xf9, 0x97, 0xa3, 0xf0, 0x26, + 0x83, 0x34, 0x2f, 0x2b, 0x33, 0xd2, 0x5b, 0x49, + 0x25, 0x36, 0xb9, 0x3b, 0xec, 0xb2, 0xf5, 0xe1, + 0xa8, 0xb8, 0x2f, 0x5b, 0x88, 0x33, 0x42, 0x72, + 0x9e, 0x8a, 0xe0, 0x9d, 0x16, 0x93, 0x88, 0x41, + 0xa2, 0x1a, 0x97, 0xfb, 0x54, 0x3e, 0xea, 0x3b, + 0xbf, 0xf5, 0x9f, 0x13, 0xc1, 0xa1, 0x84, 0x49, + 0xe3, 0x98, 0x70, 0x1c, 0x1a, 0xd5, 0x16, 0x48, + 0x34, 0x6c, 0xbc, 0x04, 0xc2, 0x7b, 0xb2, 0xda, + 0x3b, 0x93, 0xa1, 0x37, 0x2c, 0xca, 0xe5, 0x48, + 0xfb, 0x53, 0xbe, 0xe4, 0x76, 0xf9, 0xe9, 0xc9, + 0x17, 0x73, 0xb1, 0xbb, 0x19, 0x82, 0x83, 0x94, + 0xd5, 0x5d, 0x3e, 0x1a, 0x20, 0xed, 0x69, 0x11, + 0x3a, 0x86, 0x0b, 0x68, 0x29, 0xff, 0xa8, 0x47, + 0x22, 0x46, 0x04, 0x43, 0x50, 0x70, 0x22, 0x1b, + 0x25, 0x7e, 0x8d, 0xff, 0x78, 0x36, 0x15, 0xd2, + 0xca, 0xe4, 0x80, 0x3a, 0x93, 0xaa, 0x43, 0x34, + 0xab, 0x48, 0x2a, 0x0a, 0xfa, 0xc9, 0xc0, 0xae, + 0xda, 0x70, 0xb4, 0x5a, 0x48, 0x1d, 0xf5, 0xde, + 0xc5, 0xdf, 0x8c, 0xc0, 0xf4, 0x23, 0xc7, 0x7a, + 0x5f, 0xd4, 0x6c, 0xd3, 0x12, 0x02, 0x1d, 0x4b, + 0x43, 0x88, 0x62, 0x41, 0x9a, 0x79, 0x1b, 0xe0, + 0x3b, 0xb4, 0xd9, 0x7c, 0x0e, 0x59, 0x57, 0x85, + 0x42, 0x53, 0x1b, 0xa4, 0x66, 0xa8, 0x3b, 0xaf, + 0x92, 0xce, 0xfc, 0x15, 0x1b, 0x5c, 0xc1, 0x61, + 0x1a, 0x16, 0x78, 0x93, 0x81, 0x9b, 0x63, 0xfb, + 0x8a, 0x6b, 0x18, 0xe8, 0x6d, 0xe6, 0x02, 0x90, + 0xfa, 0x72, 0xb7, 0x97, 0xb0, 0xce, 0x59, 0xf3 + ]; + + SymmetricAlgorithm aes = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + + aes.EncryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); + + aes.DecryptXtsSector(ciphertext, key, sector); + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } + +} \ No newline at end of file diff --git a/tests/Tests.cs b/tests/Tests.cs new file mode 100644 index 0000000..5001561 --- /dev/null +++ b/tests/Tests.cs @@ -0,0 +1,118 @@ +using System.Text; + +namespace XTS.NET.Tests; + +public class Tests +{ + [SetUp] + public void Setup() + { + } + + [Test] + public void EncryptDecryptTest() + { + // Text generated with ChatGPT + byte[] expectedPlaintext = Encoding.UTF8.GetBytes("In the serene dawn of a hidden valley, golden sunlight began filtering through the mist, painting the landscape in hues of orange and pink. Each leaf sparkled with a delicate sheen of dew, reminiscent of a thousand scattered jewels upon the gentle sway of early autumn trees. A distant river whispered a soft, calming lullaby, threading its way through a bed of smooth stones. Birds, waking from their slumber, chirped a subtle yet beautiful symphony that harmonized with the flowing water, creating a tranquil yet powerful soundscape. Amidst this quiet paradise, a lone figure walked, footprints left on the soft earth, exploring with reverent curiosity.\r\n\r\nAs the figure ventured deeper into the valley, an old stone bridge appeared over the river, its stones worn by countless seasons, yet resilient, standing as a testament to the artisans of old. Crossing the bridge, they were greeted by a vibrant grove, filled with the earthy scent of damp soil and the faint fragrance of blooming wildflowers. In this magical solitude, time seemed to slow, each step a moment to breathe, to feel, and to simply exist in harmony with the world around.\r\n\r\nThis should provide around 520 bytes for a few blocks but not perfectly divisible by 520, as requested. Let me know if you'd like more text or a different style."); + byte[] key = [ + 0xE1, 0x33, 0xCB, 0xCB, 0x9B, 0xA4, 0x9E, 0xCC, + 0x27, 0x40, 0xD6, 0xF9, 0x71, 0x22, 0xA9, 0x5A, + 0x0F, 0x70, 0x77, 0xAA, 0x20, 0x2E, 0xA9, 0xAE, + 0xB6, 0x4B, 0x3B, 0xDA, 0x87, 0xED, 0xE8, 0xC7 + ]; + + Aes cipher = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + cipher.EncryptXts(ciphertext, key, 0, 520); + + // Ensures some form of data transformation happened + Assert.That(ciphertext, Is.Not.EqualTo(expectedPlaintext)); + + cipher.DecryptXts(ciphertext, key, 0, 520); + + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } + + [Test] + public void EncryptDecrypt256Test() + { + // Text generated with ChatGPT + byte[] expectedPlaintext = Encoding.UTF8.GetBytes("In the serene dawn of a hidden valley, golden sunlight began filtering through the mist, painting the landscape in hues of orange and pink. Each leaf sparkled with a delicate sheen of dew, reminiscent of a thousand scattered jewels upon the gentle sway of early autumn trees. A distant river whispered a soft, calming lullaby, threading its way through a bed of smooth stones. Birds, waking from their slumber, chirped a subtle yet beautiful symphony that harmonized with the flowing water, creating a tranquil yet powerful soundscape. Amidst this quiet paradise, a lone figure walked, footprints left on the soft earth, exploring with reverent curiosity.\r\n\r\nAs the figure ventured deeper into the valley, an old stone bridge appeared over the river, its stones worn by countless seasons, yet resilient, standing as a testament to the artisans of old. Crossing the bridge, they were greeted by a vibrant grove, filled with the earthy scent of damp soil and the faint fragrance of blooming wildflowers. In this magical solitude, time seemed to slow, each step a moment to breathe, to feel, and to simply exist in harmony with the world around.\r\n\r\nThis should provide around 520 bytes for a few blocks but not perfectly divisible by 520, as requested. Let me know if you'd like more text or a different style."); + byte[] key = [ + 0xE1, 0x33, 0xCB, 0xCB, 0x9B, 0xA4, 0x9E, 0xCC, + 0x27, 0x40, 0xD6, 0xF9, 0x71, 0x22, 0xA9, 0x5A, + 0x0F, 0x70, 0x77, 0xAA, 0x20, 0x2E, 0xA9, 0xAE, + 0xB6, 0x4B, 0x3B, 0xDA, 0x87, 0xED, 0xE8, 0xC7, + 0xE9, 0xC2, 0x5D, 0xC4, 0x14, 0xF2, 0xB4, 0xAD, + 0xC0, 0xF5, 0x80, 0x41, 0xA0, 0xCA, 0x16, 0x6F, + 0xB4, 0x11, 0x66, 0x21, 0x61, 0x8F, 0x24, 0xF5, + 0xED, 0xD3, 0x95, 0xD1, 0xB1, 0xA6, 0x19, 0x39 + + ]; + + Aes cipher = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + cipher.EncryptXts(ciphertext, key, 0, 520); + + // Ensures some form of data transformation happened + Assert.That(ciphertext, Is.Not.EqualTo(expectedPlaintext)); + + cipher.DecryptXts(ciphertext, key, 0, 520); + + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } + + [Test] + public void NoStealingTestCase() + { + // Text generated with ChatGPT + byte[] expectedPlaintext = Encoding.UTF8.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZ123456"); + byte[] key = [ + 0xE1, 0x33, 0xCB, 0xCB, 0x9B, 0xA4, 0x9E, 0xCC, + 0x27, 0x40, 0xD6, 0xF9, 0x71, 0x22, 0xA9, 0x5A, + 0x0F, 0x70, 0x77, 0xAA, 0x20, 0x2E, 0xA9, 0xAE, + 0xB6, 0x4B, 0x3B, 0xDA, 0x87, 0xED, 0xE8, 0xC7 + ]; + + Aes cipher = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + + cipher.EncryptXts(ciphertext, key, 0, 520); + + // Ensures some form of data transformation happened + Assert.That(ciphertext, Is.Not.EqualTo(expectedPlaintext)); + + cipher.DecryptXts(ciphertext, key, 0, 520); + + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } + + [Test] + public void ExactSectorTestCase() + { + // Text generated with ChatGPT + byte[] expectedPlaintext = Encoding.UTF8.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); + byte[] key = [ + 0xE1, 0x33, 0xCB, 0xCB, 0x9B, 0xA4, 0x9E, 0xCC, + 0x27, 0x40, 0xD6, 0xF9, 0x71, 0x22, 0xA9, 0x5A, + 0x0F, 0x70, 0x77, 0xAA, 0x20, 0x2E, 0xA9, 0xAE, + 0xB6, 0x4B, 0x3B, 0xDA, 0x87, 0xED, 0xE8, 0xC7 + ]; + + Aes cipher = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + + cipher.EncryptXts(ciphertext, key, 0, 100); + + // Ensures some form of data transformation happened + Assert.That(ciphertext, Is.Not.EqualTo(expectedPlaintext)); + + cipher.DecryptXts(ciphertext, key, 0, 100); + + Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); + } +} \ No newline at end of file diff --git a/tests/XTS.NET.Tests.csproj b/tests/XTS.NET.Tests.csproj new file mode 100644 index 0000000..15478fa --- /dev/null +++ b/tests/XTS.NET.Tests.csproj @@ -0,0 +1,27 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + From faa1a1e9bae7d00f71bb0fde243685a26ecca467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Dugr=C3=A9?= Date: Mon, 18 Nov 2024 15:50:10 -0500 Subject: [PATCH 02/15] Added license --- LICENSE-APACHE | 202 +++++++++++++++++++++++++++++++++++++++++++++++++ LICENSE-MIT | 7 ++ 2 files changed, 209 insertions(+) create mode 100644 LICENSE-APACHE create mode 100644 LICENSE-MIT diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 0000000..cd14bd7 --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2024 zer0x64 + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..bb53ea6 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,7 @@ +Copyright 2024 zer0x64 + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. From 42e1d488e3220b3921df21688ec6f405a56a1879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Dugr=C3=A9?= Date: Mon, 18 Nov 2024 15:54:32 -0500 Subject: [PATCH 03/15] Write README.md --- README.md | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d685a51..5965bdb 100644 --- a/README.md +++ b/README.md @@ -1 +1,26 @@ -# XTS.NET \ No newline at end of file +# XTS.NET +A pure C# implementation of the XTS encryption mode, mostly used for disk encryption. + +## How to use +```csharp +// Text generated with ChatGPT +byte[] expectedPlaintext = Encoding.UTF8.GetBytes("In the serene dawn of a hidden valley, golden sunlight began filtering through the mist, painting the landscape in hues of orange and pink. Each leaf sparkled with a delicate sheen of dew, reminiscent of a thousand scattered jewels upon the gentle sway of early autumn trees. A distant river whispered a soft, calming lullaby, threading its way through a bed of smooth stones. Birds, waking from their slumber, chirped a subtle yet beautiful symphony that harmonized with the flowing water, creating a tranquil yet powerful soundscape. Amidst this quiet paradise, a lone figure walked, footprints left on the soft earth, exploring with reverent curiosity.\r\n\r\nAs the figure ventured deeper into the valley, an old stone bridge appeared over the river, its stones worn by countless seasons, yet resilient, standing as a testament to the artisans of old. Crossing the bridge, they were greeted by a vibrant grove, filled with the earthy scent of damp soil and the faint fragrance of blooming wildflowers. In this magical solitude, time seemed to slow, each step a moment to breathe, to feel, and to simply exist in harmony with the world around.\r\n\r\nThis should provide around 520 bytes for a few blocks but not perfectly divisible by 520, as requested. Let me know if you'd like more text or a different style."); +byte[] key = [ + 0xE1, 0x33, 0xCB, 0xCB, 0x9B, 0xA4, 0x9E, 0xCC, + 0x27, 0x40, 0xD6, 0xF9, 0x71, 0x22, 0xA9, 0x5A, + 0x0F, 0x70, 0x77, 0xAA, 0x20, 0x2E, 0xA9, 0xAE, + 0xB6, 0x4B, 0x3B, 0xDA, 0x87, 0xED, 0xE8, 0xC7 +]; + +Aes cipher = Aes.Create(); + +// The method encrypts in-place, so we clone the plaintext here +byte[] ciphertext = (byte[])expectedPlaintext.Clone(); +cipher.EncryptXts(ciphertext, key, 0, 520); + +Assert.That(ciphertext, Is.Not.EqualTo(expectedPlaintext)); + +cipher.DecryptXts(ciphertext, key, 0, 520); + +Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); +``` \ No newline at end of file From abca3537f7a43d850817623cc4c611b5f3bcafb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Dugr=C3=A9?= Date: Mon, 18 Nov 2024 16:15:54 -0500 Subject: [PATCH 04/15] Added benchmarks --- XTS.NET.Benchmarks/Program.cs | 4 + XTS.NET.Benchmarks/XTS.NET.Benchmark.cs | 170 +++++++++++++++++++ XTS.NET.Benchmarks/XTS.NET.Benchmarks.csproj | 18 ++ XTS.NET.csproj | 3 + XTS.NET.sln | 6 + 5 files changed, 201 insertions(+) create mode 100644 XTS.NET.Benchmarks/Program.cs create mode 100644 XTS.NET.Benchmarks/XTS.NET.Benchmark.cs create mode 100644 XTS.NET.Benchmarks/XTS.NET.Benchmarks.csproj diff --git a/XTS.NET.Benchmarks/Program.cs b/XTS.NET.Benchmarks/Program.cs new file mode 100644 index 0000000..820cfe7 --- /dev/null +++ b/XTS.NET.Benchmarks/Program.cs @@ -0,0 +1,4 @@ +using XTS.NET.Benchmark; +using BenchmarkDotNet.Running; + +BenchmarkRunner.Run(); diff --git a/XTS.NET.Benchmarks/XTS.NET.Benchmark.cs b/XTS.NET.Benchmarks/XTS.NET.Benchmark.cs new file mode 100644 index 0000000..b046358 --- /dev/null +++ b/XTS.NET.Benchmarks/XTS.NET.Benchmark.cs @@ -0,0 +1,170 @@ +using BenchmarkDotNet.Attributes; +using System.Security.Cryptography; + +namespace XTS.NET.Benchmark; + +public class XtsNetBenchmark +{ + byte[] key = [ + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf + ]; + + ulong sector = 0xa987654321; + + byte[] expectedPlaintext = [ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + ]; + + byte[] expectedCiphertext = [ + 0x38, 0xb4, 0x58, 0x12, 0xef, 0x43, 0xa0, 0x5b, + 0xd9, 0x57, 0xe5, 0x45, 0x90, 0x7e, 0x22, 0x3b, + 0x95, 0x4a, 0xb4, 0xaa, 0xf0, 0x88, 0x30, 0x3a, + 0xd9, 0x10, 0xea, 0xdf, 0x14, 0xb4, 0x2b, 0xe6, + 0x8b, 0x24, 0x61, 0x14, 0x9d, 0x8c, 0x8b, 0xa8, + 0x5f, 0x99, 0x2b, 0xe9, 0x70, 0xbc, 0x62, 0x1f, + 0x1b, 0x06, 0x57, 0x3f, 0x63, 0xe8, 0x67, 0xbf, + 0x58, 0x75, 0xac, 0xaf, 0xa0, 0x4e, 0x42, 0xcc, + 0xbd, 0x7b, 0xd3, 0xc2, 0xa0, 0xfb, 0x1f, 0xff, + 0x79, 0x1e, 0xc5, 0xec, 0x36, 0xc6, 0x6a, 0xe4, + 0xac, 0x1e, 0x80, 0x6d, 0x81, 0xfb, 0xf7, 0x09, + 0xdb, 0xe2, 0x9e, 0x47, 0x1f, 0xad, 0x38, 0x54, + 0x9c, 0x8e, 0x66, 0xf5, 0x34, 0x5d, 0x7c, 0x1e, + 0xb9, 0x4f, 0x40, 0x5d, 0x1e, 0xc7, 0x85, 0xcc, + 0x6f, 0x6a, 0x68, 0xf6, 0x25, 0x4d, 0xd8, 0x33, + 0x9f, 0x9d, 0x84, 0x05, 0x7e, 0x01, 0xa1, 0x77, + 0x41, 0x99, 0x04, 0x82, 0x99, 0x95, 0x16, 0xb5, + 0x61, 0x1a, 0x38, 0xf4, 0x1b, 0xb6, 0x47, 0x8e, + 0x6f, 0x17, 0x3f, 0x32, 0x08, 0x05, 0xdd, 0x71, + 0xb1, 0x93, 0x2f, 0xc3, 0x33, 0xcb, 0x9e, 0xe3, + 0x99, 0x36, 0xbe, 0xea, 0x9a, 0xd9, 0x6f, 0xa1, + 0x0f, 0xb4, 0x11, 0x2b, 0x90, 0x17, 0x34, 0xdd, + 0xad, 0x40, 0xbc, 0x18, 0x78, 0x99, 0x5f, 0x8e, + 0x11, 0xae, 0xe7, 0xd1, 0x41, 0xa2, 0xf5, 0xd4, + 0x8b, 0x7a, 0x4e, 0x1e, 0x7f, 0x0b, 0x2c, 0x04, + 0x83, 0x0e, 0x69, 0xa4, 0xfd, 0x13, 0x78, 0x41, + 0x1c, 0x2f, 0x28, 0x7e, 0xdf, 0x48, 0xc6, 0xc4, + 0xe5, 0xc2, 0x47, 0xa1, 0x96, 0x80, 0xf7, 0xfe, + 0x41, 0xce, 0xfb, 0xd4, 0x9b, 0x58, 0x21, 0x06, + 0xe3, 0x61, 0x6c, 0xbb, 0xe4, 0xdf, 0xb2, 0x34, + 0x4b, 0x2a, 0xe9, 0x51, 0x93, 0x91, 0xf3, 0xe0, + 0xfb, 0x49, 0x22, 0x25, 0x4b, 0x1d, 0x6d, 0x2d, + 0x19, 0xc6, 0xd4, 0xd5, 0x37, 0xb3, 0xa2, 0x6f, + 0x3b, 0xcc, 0x51, 0x58, 0x8b, 0x32, 0xf3, 0xec, + 0xa0, 0x82, 0x9b, 0x6a, 0x5a, 0xc7, 0x25, 0x78, + 0xfb, 0x81, 0x4f, 0xb4, 0x3c, 0xf8, 0x0d, 0x64, + 0xa2, 0x33, 0xe3, 0xf9, 0x97, 0xa3, 0xf0, 0x26, + 0x83, 0x34, 0x2f, 0x2b, 0x33, 0xd2, 0x5b, 0x49, + 0x25, 0x36, 0xb9, 0x3b, 0xec, 0xb2, 0xf5, 0xe1, + 0xa8, 0xb8, 0x2f, 0x5b, 0x88, 0x33, 0x42, 0x72, + 0x9e, 0x8a, 0xe0, 0x9d, 0x16, 0x93, 0x88, 0x41, + 0xa2, 0x1a, 0x97, 0xfb, 0x54, 0x3e, 0xea, 0x3b, + 0xbf, 0xf5, 0x9f, 0x13, 0xc1, 0xa1, 0x84, 0x49, + 0xe3, 0x98, 0x70, 0x1c, 0x1a, 0xd5, 0x16, 0x48, + 0x34, 0x6c, 0xbc, 0x04, 0xc2, 0x7b, 0xb2, 0xda, + 0x3b, 0x93, 0xa1, 0x37, 0x2c, 0xca, 0xe5, 0x48, + 0xfb, 0x53, 0xbe, 0xe4, 0x76, 0xf9, 0xe9, 0xc9, + 0x17, 0x73, 0xb1, 0xbb, 0x19, 0x82, 0x83, 0x94, + 0xd5, 0x5d, 0x3e, 0x1a, 0x20, 0xed, 0x69, 0x11, + 0x3a, 0x86, 0x0b, 0x68, 0x29, 0xff, 0xa8, 0x47, + 0x22, 0x46, 0x04, 0x43, 0x50, 0x70, 0x22, 0x1b, + 0x25, 0x7e, 0x8d, 0xff, 0x78, 0x36, 0x15, 0xd2, + 0xca, 0xe4, 0x80, 0x3a, 0x93, 0xaa, 0x43, 0x34, + 0xab, 0x48, 0x2a, 0x0a, 0xfa, 0xc9, 0xc0, 0xae, + 0xda, 0x70, 0xb4, 0x5a, 0x48, 0x1d, 0xf5, 0xde, + 0xc5, 0xdf, 0x8c, 0xc0, 0xf4, 0x23, 0xc7, 0x7a, + 0x5f, 0xd4, 0x6c, 0xd3, 0x12, 0x02, 0x1d, 0x4b, + 0x43, 0x88, 0x62, 0x41, 0x9a, 0x79, 0x1b, 0xe0, + 0x3b, 0xb4, 0xd9, 0x7c, 0x0e, 0x59, 0x57, 0x85, + 0x42, 0x53, 0x1b, 0xa4, 0x66, 0xa8, 0x3b, 0xaf, + 0x92, 0xce, 0xfc, 0x15, 0x1b, 0x5c, 0xc1, 0x61, + 0x1a, 0x16, 0x78, 0x93, 0x81, 0x9b, 0x63, 0xfb, + 0x8a, 0x6b, 0x18, 0xe8, 0x6d, 0xe6, 0x02, 0x90, + 0xfa, 0x72, 0xb7, 0x97, 0xb0, 0xce, 0x59, 0xf3 + ]; + + [Benchmark] + public void Encrypt() + { + SymmetricAlgorithm aes = Aes.Create(); + + byte[] ciphertext = (byte[])expectedPlaintext.Clone(); + + aes.EncryptXtsSector(ciphertext, key, sector); + } + + [Benchmark] + public void Decrypt() + { + SymmetricAlgorithm aes = Aes.Create(); + + byte[] plaintext = (byte[])expectedCiphertext.Clone(); + + aes.DecryptXtsSector(plaintext, key, sector); + } +} diff --git a/XTS.NET.Benchmarks/XTS.NET.Benchmarks.csproj b/XTS.NET.Benchmarks/XTS.NET.Benchmarks.csproj new file mode 100644 index 0000000..b46459c --- /dev/null +++ b/XTS.NET.Benchmarks/XTS.NET.Benchmarks.csproj @@ -0,0 +1,18 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + + + diff --git a/XTS.NET.csproj b/XTS.NET.csproj index b2dfc7c..11d79e1 100644 --- a/XTS.NET.csproj +++ b/XTS.NET.csproj @@ -9,8 +9,11 @@ + + + diff --git a/XTS.NET.sln b/XTS.NET.sln index 9de33bf..715c654 100644 --- a/XTS.NET.sln +++ b/XTS.NET.sln @@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XTS.NET", "XTS.NET.csproj", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XTS.NET.Tests", "tests\XTS.NET.Tests.csproj", "{AE300E49-FCCD-45D6-A32C-6E133148DF02}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XTS.NET.Benchmarks", "XTS.NET.Benchmarks\XTS.NET.Benchmarks.csproj", "{652E2CC9-C97C-479E-82E4-F9DEF839149C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -24,5 +26,9 @@ Global {AE300E49-FCCD-45D6-A32C-6E133148DF02}.Debug|Any CPU.Build.0 = Debug|Any CPU {AE300E49-FCCD-45D6-A32C-6E133148DF02}.Release|Any CPU.ActiveCfg = Release|Any CPU {AE300E49-FCCD-45D6-A32C-6E133148DF02}.Release|Any CPU.Build.0 = Release|Any CPU + {652E2CC9-C97C-479E-82E4-F9DEF839149C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {652E2CC9-C97C-479E-82E4-F9DEF839149C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {652E2CC9-C97C-479E-82E4-F9DEF839149C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {652E2CC9-C97C-479E-82E4-F9DEF839149C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal From 2d64bf0562e8ec43af45373dbc68328af2cbc891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Dugr=C3=A9?= Date: Mon, 18 Nov 2024 16:24:14 -0500 Subject: [PATCH 05/15] Added CI --- .github/workflows/ci.yml | 37 ++++++++++++ .github/workflows/release.yml | 60 ++++++++++++++++++++ XTS.NET.Benchmarks/XTS.NET.Benchmarks.csproj | 2 +- XTS.NET.sln | 2 +- XTS.NET.csproj => src/XTS.NET.csproj | 0 src/XTS.cs | 3 +- tests/XTS.NET.Tests.csproj | 2 +- 7 files changed, 101 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/release.yml rename XTS.NET.csproj => src/XTS.NET.csproj (100%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..1b05ee9 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,37 @@ +name: Main + +on: + push: + branches: + - master + pull_request: + workflow_dispatch: +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.0.x' + + - name: Build + run: dotnet build --configuration Release + + - name: Run tests + run: dotnet test + + - name: Generate NuGet + run: | + cd src/ + dotnet pack -o package /p:Version=$(date "+%-Y.%-m.%-d") + + - uses: actions/upload-artifact@v4.3.6 + with: + name: nugets + path: src/package/*.nupkg \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..c513e9b --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,60 @@ +name: Deploy to production (Nugets) +on: + workflow_dispatch: + inputs: + publish_nuget: + description: "Publish Devolutions.XTS.NET" + required: true + type: boolean + + publish_dry_run: + description: "Dry Run Mode" + required: true + type: boolean +jobs: + deploy: + runs-on: ubuntu-latest + environment: publish + steps: + - uses: actions/checkout@v4 + + - name: Check out devolutions/actions + uses: actions/checkout@v4 + with: + path: ./.github/workflows + ref: v1 + repository: Devolutions/actions + token: ${{ secrets.DEVOLUTIONSBOT_TOKEN }} + + - name: Install toolbox + uses: ./.github/workflows/toolbox-install + with: + github_token: ${{ secrets.DEVOLUTIONSBOT_TOKEN }} + + - name: Download Nugets Artifact + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CI: true + run: | + dv github download-artifact nugets . XTS.NET + + - name: Extract Artifacts + run: | + 7z x nugets.zip -o./nugets + + - name: Publish NuGet + if: ${{ inputs.publish_nuget }} + run: | + COMMAND="dotnet nuget push ./nugets/Devolutions.XTS.NET.*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json" + + if [ '${{ inputs.publish_dry_run }}' == 'true' ]; then + echo "Dry Run : True" + else + echo "Dry Run : False" + fi + + echo "Running : $COMMAND" + + if [ "${{ inputs.publish_dry_run }}" != "true" ]; then # if not dry run, actually run the command + eval "$COMMAND" + fi diff --git a/XTS.NET.Benchmarks/XTS.NET.Benchmarks.csproj b/XTS.NET.Benchmarks/XTS.NET.Benchmarks.csproj index b46459c..9f9b705 100644 --- a/XTS.NET.Benchmarks/XTS.NET.Benchmarks.csproj +++ b/XTS.NET.Benchmarks/XTS.NET.Benchmarks.csproj @@ -12,7 +12,7 @@ - + diff --git a/XTS.NET.sln b/XTS.NET.sln index 715c654..705ca3f 100644 --- a/XTS.NET.sln +++ b/XTS.NET.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XTS.NET", "XTS.NET.csproj", "{DB2D8001-9562-4042-883D-69D4C75E647C}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XTS.NET", "src\XTS.NET.csproj", "{DB2D8001-9562-4042-883D-69D4C75E647C}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XTS.NET.Tests", "tests\XTS.NET.Tests.csproj", "{AE300E49-FCCD-45D6-A32C-6E133148DF02}" EndProject diff --git a/XTS.NET.csproj b/src/XTS.NET.csproj similarity index 100% rename from XTS.NET.csproj rename to src/XTS.NET.csproj diff --git a/src/XTS.cs b/src/XTS.cs index 7e75a05..b6d4f60 100644 --- a/src/XTS.cs +++ b/src/XTS.cs @@ -1,5 +1,4 @@ -using System; -using System.Numerics; +using System.Numerics; using System.Security.Cryptography; namespace XTS.NET; diff --git a/tests/XTS.NET.Tests.csproj b/tests/XTS.NET.Tests.csproj index 15478fa..5d6e380 100644 --- a/tests/XTS.NET.Tests.csproj +++ b/tests/XTS.NET.Tests.csproj @@ -21,7 +21,7 @@ - + From 9f334453363aa6f8dd529d2d2bcc43cb12793063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Dugr=C3=A9?= Date: Tue, 19 Nov 2024 08:44:49 -0500 Subject: [PATCH 06/15] Migrated to netstandard2.1 --- XTS.NET.sln | 12 +- src/XTS.NET.csproj | 29 ++-- src/XTS.cs | 338 +++++++++++++++++++++++---------------------- 3 files changed, 189 insertions(+), 190 deletions(-) diff --git a/XTS.NET.sln b/XTS.NET.sln index 705ca3f..8d0407d 100644 --- a/XTS.NET.sln +++ b/XTS.NET.sln @@ -3,12 +3,12 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XTS.NET", "src\XTS.NET.csproj", "{DB2D8001-9562-4042-883D-69D4C75E647C}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XTS.NET.Tests", "tests\XTS.NET.Tests.csproj", "{AE300E49-FCCD-45D6-A32C-6E133148DF02}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XTS.NET.Benchmarks", "XTS.NET.Benchmarks\XTS.NET.Benchmarks.csproj", "{652E2CC9-C97C-479E-82E4-F9DEF839149C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XTS.NET", "src\XTS.NET.csproj", "{69966EA9-5369-4673-A404-EAA548CCF722}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -18,10 +18,6 @@ Global HideSolutionNode = FALSE EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {DB2D8001-9562-4042-883D-69D4C75E647C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DB2D8001-9562-4042-883D-69D4C75E647C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DB2D8001-9562-4042-883D-69D4C75E647C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DB2D8001-9562-4042-883D-69D4C75E647C}.Release|Any CPU.Build.0 = Release|Any CPU {AE300E49-FCCD-45D6-A32C-6E133148DF02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AE300E49-FCCD-45D6-A32C-6E133148DF02}.Debug|Any CPU.Build.0 = Debug|Any CPU {AE300E49-FCCD-45D6-A32C-6E133148DF02}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -30,5 +26,9 @@ Global {652E2CC9-C97C-479E-82E4-F9DEF839149C}.Debug|Any CPU.Build.0 = Debug|Any CPU {652E2CC9-C97C-479E-82E4-F9DEF839149C}.Release|Any CPU.ActiveCfg = Release|Any CPU {652E2CC9-C97C-479E-82E4-F9DEF839149C}.Release|Any CPU.Build.0 = Release|Any CPU + {69966EA9-5369-4673-A404-EAA548CCF722}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {69966EA9-5369-4673-A404-EAA548CCF722}.Debug|Any CPU.Build.0 = Debug|Any CPU + {69966EA9-5369-4673-A404-EAA548CCF722}.Release|Any CPU.ActiveCfg = Release|Any CPU + {69966EA9-5369-4673-A404-EAA548CCF722}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/src/XTS.NET.csproj b/src/XTS.NET.csproj index 11d79e1..4f2443c 100644 --- a/src/XTS.NET.csproj +++ b/src/XTS.NET.csproj @@ -1,21 +1,18 @@  - - net8.0 - enable - enable + netstandard2.1 + MIT OR Apache-2.0 + zer0x64 (Philippe Dugre) + Devolutions + A pure C# implementation of the XTS encryption mode, mostly used for disk encryption. + https://github.com/Devolutions/XTS.NET + Devolutions.XTS.NET + README.md - - - - - - - - - - + + True + \ + - - + \ No newline at end of file diff --git a/src/XTS.cs b/src/XTS.cs index b6d4f60..2b86ab6 100644 --- a/src/XTS.cs +++ b/src/XTS.cs @@ -1,236 +1,238 @@ -using System.Numerics; +using System; +using System.Numerics; using System.Security.Cryptography; -namespace XTS.NET; - -public static class XTS +namespace XTS.NET { - public static void EncryptXts(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum, int sectorSize) + public static class XTS { - SetupRawCipher(alg); + public static void EncryptXts(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum, int sectorSize) + { + SetupRawCipher(alg); - // Set K1 and create encryptor - ICryptoTransform encryptor = alg.CreateEncryptor(key[..(key.Length / 2)].ToArray(), null); + // Set K1 and create encryptor + ICryptoTransform encryptor = alg.CreateEncryptor(key[..(key.Length / 2)].ToArray(), null); - int nSectors = (buffer.Length - 1) / sectorSize + 1; + int nSectors = (buffer.Length - 1) / sectorSize + 1; - int currentSectorSize = sectorSize; - // This for apply on each sectors - for (int i = 0; i < nSectors; i += 1) - { - // Last sector is likely shorter - if (i == nSectors - 1) + int currentSectorSize = sectorSize; + // This for apply on each sectors + for (int i = 0; i < nSectors; i += 1) { - currentSectorSize = (buffer.Length - 1) % sectorSize + 1; - } + // Last sector is likely shorter + if (i == nSectors - 1) + { + currentSectorSize = (buffer.Length - 1) % sectorSize + 1; + } - // Encrypt the tweak - byte[] tweak = EncryptTweak(alg, key, sectorNum); + // Encrypt the tweak + byte[] tweak = EncryptTweak(alg, key, sectorNum); - // Process the sector - ProcessXtsSector(encryptor, buffer, i * sectorSize, currentSectorSize, tweak, false); + // Process the sector + ProcessXtsSector(encryptor, buffer, i * sectorSize, currentSectorSize, tweak, false); - // We advance the counter for the next sector - sectorNum += 1; + // We advance the counter for the next sector + sectorNum += 1; + } } - } - public static void DecryptXts(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum, int sectorSize) - { - SetupRawCipher(alg); + public static void DecryptXts(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum, int sectorSize) + { + SetupRawCipher(alg); - // Set K1 and create decryptor - ICryptoTransform encryptor = alg.CreateDecryptor(key[..(key.Length / 2)].ToArray(), null); + // Set K1 and create decryptor + ICryptoTransform encryptor = alg.CreateDecryptor(key[..(key.Length / 2)].ToArray(), null); - int nSectors = (buffer.Length - 1) / sectorSize + 1; + int nSectors = (buffer.Length - 1) / sectorSize + 1; - int currentSectorSize = sectorSize; - // This for apply on each sectors - for (int i = 0; i < nSectors; i += 1) - { - // Last sector is likely shorter - if (i == nSectors - 1) + int currentSectorSize = sectorSize; + // This for apply on each sectors + for (int i = 0; i < nSectors; i += 1) { - currentSectorSize = (buffer.Length - 1) % sectorSize + 1; - } + // Last sector is likely shorter + if (i == nSectors - 1) + { + currentSectorSize = (buffer.Length - 1) % sectorSize + 1; + } - // Encrypt the tweak - byte[] tweak = EncryptTweak(alg, key, sectorNum); + // Encrypt the tweak + byte[] tweak = EncryptTweak(alg, key, sectorNum); - // Process the sector - ProcessXtsSector(encryptor, buffer, i * sectorSize, currentSectorSize, tweak, true); + // Process the sector + ProcessXtsSector(encryptor, buffer, i * sectorSize, currentSectorSize, tweak, true); - // We advance the counter for the next sector - sectorNum += 1; + // We advance the counter for the next sector + sectorNum += 1; + } } - } - - public static void EncryptXtsSector(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum) - { - SetupRawCipher(alg); - - // Set K1 and create encryptor - ICryptoTransform encryptor = alg.CreateEncryptor(key[..(key.Length / 2)].ToArray(), null); - // Encrypt the tweak - byte[] tweak = EncryptTweak(alg, key, sectorNum); + public static void EncryptXtsSector(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum) + { + SetupRawCipher(alg); - // Encrypt Sector - ProcessXtsSector(encryptor, buffer, 0, buffer.Length, tweak, false); - } + // Set K1 and create encryptor + ICryptoTransform encryptor = alg.CreateEncryptor(key[..(key.Length / 2)].ToArray(), null); - public static void DecryptXtsSector(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum) - { - SetupRawCipher(alg); + // Encrypt the tweak + byte[] tweak = EncryptTweak(alg, key, sectorNum); - // Set K1 and create decryptor - ICryptoTransform decryptor = alg.CreateDecryptor(key[..(key.Length / 2)].ToArray(), null); + // Encrypt Sector + ProcessXtsSector(encryptor, buffer, 0, buffer.Length, tweak, false); + } - // Encrypt the tweak - byte[] tweak = EncryptTweak(alg, key, sectorNum); + public static void DecryptXtsSector(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum) + { + SetupRawCipher(alg); - // Decrypt Sector - ProcessXtsSector(decryptor, buffer, 0, buffer.Length, tweak, true); - } + // Set K1 and create decryptor + ICryptoTransform decryptor = alg.CreateDecryptor(key[..(key.Length / 2)].ToArray(), null); - private static void ProcessXtsSector(ICryptoTransform alg, byte[] buffer, int bufferOffset, int bufferLength, Span tweak, bool decrypt) - { - int blockSize = alg.InputBlockSize; - int nFullBlocks = bufferLength / blockSize; + // Encrypt the tweak + byte[] tweak = EncryptTweak(alg, key, sectorNum); - if (bufferLength < blockSize) - { - throw new ArgumentException("You cannot encrypt less then a block in a sector using XTS"); + // Decrypt Sector + ProcessXtsSector(decryptor, buffer, 0, buffer.Length, tweak, true); } - for (int j = 0; j < nFullBlocks - 1; j += 1) + private static void ProcessXtsSector(ICryptoTransform alg, byte[] buffer, int bufferOffset, int bufferLength, Span tweak, bool decrypt) { - int blockStart = bufferOffset + j * blockSize; - TransformBlock(alg, buffer, blockStart, tweak); + int blockSize = alg.InputBlockSize; + int nFullBlocks = bufferLength / blockSize; - // Multiply tweak by two for next block - GaloisMultiplyByTwo(tweak); - } - - // If we decrypt and we need to do ciphertext stealing, we need to skip a GF multiplication here and roll back after - int remainingBytes = bufferLength - nFullBlocks * blockSize; - bool needsCiphertextStealing = remainingBytes > 0; + if (bufferLength < blockSize) + { + throw new ArgumentException("You cannot encrypt less then a block in a sector using XTS"); + } - if (decrypt && needsCiphertextStealing) - { - // We backup the tweak, re-multiply it and restore it after - byte[] oldTweak = tweak.ToArray(); - GaloisMultiplyByTwo(tweak); + for (int j = 0; j < nFullBlocks - 1; j += 1) + { + int blockStart = bufferOffset + j * blockSize; + TransformBlock(alg, buffer, blockStart, tweak); - int blockStart = bufferOffset + (nFullBlocks - 1) * blockSize; - TransformBlock(alg, buffer, blockStart, tweak); + // Multiply tweak by two for next block + GaloisMultiplyByTwo(tweak); + } - tweak = oldTweak; - } - else - { - int blockStart = bufferOffset + (nFullBlocks - 1) * blockSize; - TransformBlock(alg, buffer, blockStart, tweak); + // If we decrypt and we need to do ciphertext stealing, we need to skip a GF multiplication here and roll back after + int remainingBytes = bufferLength - nFullBlocks * blockSize; + bool needsCiphertextStealing = remainingBytes > 0; - if (needsCiphertextStealing) + if (decrypt && needsCiphertextStealing) { - // We will need another decryption after this + // We backup the tweak, re-multiply it and restore it after + byte[] oldTweak = tweak.ToArray(); GaloisMultiplyByTwo(tweak); + + int blockStart = bufferOffset + (nFullBlocks - 1) * blockSize; + TransformBlock(alg, buffer, blockStart, tweak); + + tweak = oldTweak; + } + else + { + int blockStart = bufferOffset + (nFullBlocks - 1) * blockSize; + TransformBlock(alg, buffer, blockStart, tweak); + + if (needsCiphertextStealing) + { + // We will need another decryption after this + GaloisMultiplyByTwo(tweak); + } } - } - if (needsCiphertextStealing) - { - // We need to do ciphertext stealing since the sector size does not align with the blocksize - int previousBlockStart = bufferOffset + (nFullBlocks - 1) * blockSize; - int currentBlockStart = previousBlockStart + blockSize; + if (needsCiphertextStealing) + { + // We need to do ciphertext stealing since the sector size does not align with the blocksize + int previousBlockStart = bufferOffset + (nFullBlocks - 1) * blockSize; + int currentBlockStart = previousBlockStart + blockSize; - Span bufferSpan = buffer.AsSpan(); - Span previousBlockSpan = bufferSpan[previousBlockStart..currentBlockStart]; - Span currentBlockSpan = bufferSpan[currentBlockStart..(bufferOffset + bufferLength)]; + Span bufferSpan = buffer.AsSpan(); + Span previousBlockSpan = bufferSpan[previousBlockStart..currentBlockStart]; + Span currentBlockSpan = bufferSpan[currentBlockStart..(bufferOffset + bufferLength)]; - // Buffer last bytes - byte[] remainingBytesArray = currentBlockSpan.ToArray(); + // Buffer last bytes + byte[] remainingBytesArray = currentBlockSpan.ToArray(); - // We copy part of the previous ciphertext at the end - previousBlockSpan[..remainingBytes].CopyTo(currentBlockSpan); + // We copy part of the previous ciphertext at the end + previousBlockSpan[..remainingBytes].CopyTo(currentBlockSpan); - // We compute the last block on the previous block - // We only need to copy the start of the last block, as the end of the previous block is already there - remainingBytesArray.AsSpan().CopyTo(previousBlockSpan); + // We compute the last block on the previous block + // We only need to copy the start of the last block, as the end of the previous block is already there + remainingBytesArray.AsSpan().CopyTo(previousBlockSpan); - TransformBlock(alg, buffer, previousBlockStart, tweak); + TransformBlock(alg, buffer, previousBlockStart, tweak); + } } - } - private static byte[] EncryptTweak(SymmetricAlgorithm alg, ReadOnlySpan key, BigInteger sectorNum) - { - int blockSize = alg.BlockSize / 8; + private static byte[] EncryptTweak(SymmetricAlgorithm alg, ReadOnlySpan key, BigInteger sectorNum) + { + int blockSize = alg.BlockSize / 8; - // Set K2 to create tweak encryptor - ICryptoTransform tweaker = alg.CreateEncryptor(key[(key.Length / 2)..].ToArray(), null); + // Set K2 to create tweak encryptor + ICryptoTransform tweaker = alg.CreateEncryptor(key[(key.Length / 2)..].ToArray(), null); - // Convert sector number to little endian block - byte[] tweak = sectorNum.ToByteArray(isUnsigned: true, isBigEndian: false); - Array.Resize(ref tweak, blockSize); + // Convert sector number to little endian block + byte[] tweak = sectorNum.ToByteArray(isUnsigned: true, isBigEndian: false); + Array.Resize(ref tweak, blockSize); - // Encrypt tweak - tweaker.TransformBlock(tweak, 0, blockSize, tweak, 0); + // Encrypt tweak + tweaker.TransformBlock(tweak, 0, blockSize, tweak, 0); - return tweak; - } + return tweak; + } - private static void SetupRawCipher(SymmetricAlgorithm alg) - { - // Setup for raw cipher, without mode or padding - alg.Mode = CipherMode.ECB; - alg.Padding = PaddingMode.None; - } + private static void SetupRawCipher(SymmetricAlgorithm alg) + { + // Setup for raw cipher, without mode or padding + alg.Mode = CipherMode.ECB; + alg.Padding = PaddingMode.None; + } - private static void TransformBlock(ICryptoTransform alg, byte[] buffer, int bufferOffset, ReadOnlySpan tweak) - { - // Get block size from the transform - int blockSize = alg.InputBlockSize; + private static void TransformBlock(ICryptoTransform alg, byte[] buffer, int bufferOffset, ReadOnlySpan tweak) + { + // Get block size from the transform + int blockSize = alg.InputBlockSize; - // Cast as span for easier manipulation - Span outputSpan = buffer.AsSpan()[bufferOffset..(bufferOffset + blockSize)]; + // Cast as span for easier manipulation + Span outputSpan = buffer.AsSpan()[bufferOffset..(bufferOffset + blockSize)]; - // XEX part - XorBlocksInPlace(tweak, outputSpan); - alg.TransformBlock(buffer, bufferOffset, blockSize, buffer, bufferOffset); - XorBlocksInPlace(tweak, outputSpan); - } + // XEX part + XorBlocksInPlace(tweak, outputSpan); + alg.TransformBlock(buffer, bufferOffset, blockSize, buffer, bufferOffset); + XorBlocksInPlace(tweak, outputSpan); + } - private static void XorBlocksInPlace(ReadOnlySpan input, Span output) - { - for (int i = 0; i < output.Length; i++) + private static void XorBlocksInPlace(ReadOnlySpan input, Span output) { - output[i] ^= input[i]; + for (int i = 0; i < output.Length; i++) + { + output[i] ^= input[i]; + } } - } - private static void GaloisMultiplyByTwo(Span tweak) - { - bool carry = false; - for (int i = 0; i < tweak.Length; i++) + private static void GaloisMultiplyByTwo(Span tweak) { - // Save carry from previous byte - byte oldCarry = (byte)(carry ? 1 : 0); + bool carry = false; + for (int i = 0; i < tweak.Length; i++) + { + // Save carry from previous byte + byte oldCarry = (byte)(carry ? 1 : 0); - // Check if there is a carry for this shift - carry = (tweak[i] & 0x80) > 0; + // Check if there is a carry for this shift + carry = (tweak[i] & 0x80) > 0; - // Shift left - tweak[i] <<= 1; + // Shift left + tweak[i] <<= 1; - // Carry over bit from last carry - tweak[i] |= oldCarry; - } + // Carry over bit from last carry + tweak[i] |= oldCarry; + } - if (carry) - { - // Derived from polynomial x^128 + x^7 + x^2 + x + 1 - tweak[0] ^= 135; + if (carry) + { + // Derived from polynomial x^128 + x^7 + x^2 + x + 1 + tweak[0] ^= 135; + } } } } From afc3e2192bb3eed9f83558de3c34af8d61c2d9b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Dugr=C3=A9?= Date: Tue, 19 Nov 2024 08:52:04 -0500 Subject: [PATCH 07/15] Optimized out an allocation and avoid leaving un-zeroed data in RAM --- src/XTS.cs | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/XTS.cs b/src/XTS.cs index 2b86ab6..40149e4 100644 --- a/src/XTS.cs +++ b/src/XTS.cs @@ -146,20 +146,15 @@ private static void ProcessXtsSector(ICryptoTransform alg, byte[] buffer, int bu int previousBlockStart = bufferOffset + (nFullBlocks - 1) * blockSize; int currentBlockStart = previousBlockStart + blockSize; + // Define the spans Span bufferSpan = buffer.AsSpan(); Span previousBlockSpan = bufferSpan[previousBlockStart..currentBlockStart]; Span currentBlockSpan = bufferSpan[currentBlockStart..(bufferOffset + bufferLength)]; - // Buffer last bytes - byte[] remainingBytesArray = currentBlockSpan.ToArray(); - - // We copy part of the previous ciphertext at the end - previousBlockSpan[..remainingBytes].CopyTo(currentBlockSpan); - - // We compute the last block on the previous block - // We only need to copy the start of the last block, as the end of the previous block is already there - remainingBytesArray.AsSpan().CopyTo(previousBlockSpan); + // We copy part of the previous ciphertext at the end and replace it with the plaintext of the last block + SwapSpan(previousBlockSpan[..remainingBytes], currentBlockSpan); + // We encrypt/decrypt the second to last block TransformBlock(alg, buffer, previousBlockStart, tweak); } } @@ -210,6 +205,16 @@ private static void XorBlocksInPlace(ReadOnlySpan input, Span output } } + private static void SwapSpan(Span x, Span y) + { + for (int i = 0; i < x.Length; i++) + { + byte tmp = x[i]; + x[i] = y[i]; + y[i] = tmp; + } + } + private static void GaloisMultiplyByTwo(Span tweak) { bool carry = false; From 7dc8b6790f7145de02b6778ceb8ea27ed8282d18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Dugr=C3=A9?= Date: Tue, 19 Nov 2024 09:23:19 -0500 Subject: [PATCH 08/15] Optimized out last remaining allocation --- src/XTS.cs | 56 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/src/XTS.cs b/src/XTS.cs index 40149e4..1df6ba9 100644 --- a/src/XTS.cs +++ b/src/XTS.cs @@ -6,6 +6,8 @@ namespace XTS.NET { public static class XTS { + private const byte GF_MOD = 135; + public static void EncryptXts(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum, int sectorSize) { SetupRawCipher(alg); @@ -119,14 +121,14 @@ private static void ProcessXtsSector(ICryptoTransform alg, byte[] buffer, int bu if (decrypt && needsCiphertextStealing) { - // We backup the tweak, re-multiply it and restore it after - byte[] oldTweak = tweak.ToArray(); - GaloisMultiplyByTwo(tweak); + // We fast forward the multiplication here + bool carry = GaloisMultiplyByTwo(tweak); int blockStart = bufferOffset + (nFullBlocks - 1) * blockSize; TransformBlock(alg, buffer, blockStart, tweak); - tweak = oldTweak; + // We backtrack the multiplication + GaloisUnmultiplyByTwo(tweak, carry); } else { @@ -215,7 +217,12 @@ private static void SwapSpan(Span x, Span y) } } - private static void GaloisMultiplyByTwo(Span tweak) + /// + /// Galois Field multiplication by 2 + /// + /// + /// + private static bool GaloisMultiplyByTwo(Span tweak) { bool carry = false; for (int i = 0; i < tweak.Length; i++) @@ -236,7 +243,44 @@ private static void GaloisMultiplyByTwo(Span tweak) if (carry) { // Derived from polynomial x^128 + x^7 + x^2 + x + 1 - tweak[0] ^= 135; + tweak[0] ^= GF_MOD; + } + + return carry; + } + + /// + /// Reverse the galois field multiplication. This is used once during decryption to avoid an allocation + /// + /// The tweak to reverse + /// The carry flag of the last multiplication + /// + private static void GaloisUnmultiplyByTwo(Span tweak, bool carry) + { + if (carry) + { + // Derived from polynomial x^128 + x^7 + x^2 + x + 1 + tweak[0] ^= GF_MOD; + } + + int newCarry = 0; + for (int i = tweak.Length - 1; i >= 0; i--) + { + int oldCarry = newCarry; + + // Check if there is a carry for this shift + newCarry = tweak[i] & 1; + + // Shift left + tweak[i] >>= 1; + + // Carry over bit from last carry + tweak[i] |= (byte)(oldCarry << 7); + } + + if (carry) + { + tweak[tweak.Length - 1] |= 0x80; } } } From f11ae3f0dad9cce96a63469ff61cb01ca039f78b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Dugr=C3=A9?= Date: Tue, 19 Nov 2024 09:28:56 -0500 Subject: [PATCH 09/15] Added higer-level functions that are not in-place --- XTS.NET.Benchmarks/XTS.NET.Benchmark.cs | 4 +- src/XTS.cs | 34 +++++++++-- tests/IeeeVectorsTests.cs | 76 ++++++++++++------------- tests/Tests.cs | 16 +++--- 4 files changed, 78 insertions(+), 52 deletions(-) diff --git a/XTS.NET.Benchmarks/XTS.NET.Benchmark.cs b/XTS.NET.Benchmarks/XTS.NET.Benchmark.cs index b046358..63f12e5 100644 --- a/XTS.NET.Benchmarks/XTS.NET.Benchmark.cs +++ b/XTS.NET.Benchmarks/XTS.NET.Benchmark.cs @@ -155,7 +155,7 @@ public void Encrypt() byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - aes.EncryptXtsSector(ciphertext, key, sector); + aes.EncryptXtsSectorInPlace(ciphertext, key, sector); } [Benchmark] @@ -165,6 +165,6 @@ public void Decrypt() byte[] plaintext = (byte[])expectedCiphertext.Clone(); - aes.DecryptXtsSector(plaintext, key, sector); + aes.DecryptXtsSectorInPlace(plaintext, key, sector); } } diff --git a/src/XTS.cs b/src/XTS.cs index 1df6ba9..44d5a21 100644 --- a/src/XTS.cs +++ b/src/XTS.cs @@ -7,8 +7,34 @@ namespace XTS.NET public static class XTS { private const byte GF_MOD = 135; + public static byte[] EncryptXts(this SymmetricAlgorithm alg, ReadOnlySpan input, ReadOnlySpan key, BigInteger sectorNum, int sectorSize) + { + byte[] buffer = input.ToArray(); + alg.EncryptXtsInPlace(buffer, key, sectorNum, sectorSize); + return buffer; + } + + public static byte[] DecryptXts(this SymmetricAlgorithm alg, ReadOnlySpan input, ReadOnlySpan key, BigInteger sectorNum, int sectorSize) + { + byte[] buffer = input.ToArray(); + alg.DecryptXtsInPlace(buffer, key, sectorNum, sectorSize); + return buffer; + } + public static byte[] EncryptXtsSector(this SymmetricAlgorithm alg, ReadOnlySpan input, ReadOnlySpan key, BigInteger sectorNum) + { + byte[] buffer = input.ToArray(); + alg.EncryptXtsSectorInPlace(buffer, key, sectorNum); + return buffer; + } + + public static byte[] DecryptXtsSector(this SymmetricAlgorithm alg, ReadOnlySpan input, ReadOnlySpan key, BigInteger sectorNum) + { + byte[] buffer = input.ToArray(); + alg.DecryptXtsSectorInPlace(buffer, key, sectorNum); + return buffer; + } - public static void EncryptXts(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum, int sectorSize) + public static void EncryptXtsInPlace(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum, int sectorSize) { SetupRawCipher(alg); @@ -38,7 +64,7 @@ public static void EncryptXts(this SymmetricAlgorithm alg, byte[] buffer, ReadOn } } - public static void DecryptXts(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum, int sectorSize) + public static void DecryptXtsInPlace(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum, int sectorSize) { SetupRawCipher(alg); @@ -68,7 +94,7 @@ public static void DecryptXts(this SymmetricAlgorithm alg, byte[] buffer, ReadOn } } - public static void EncryptXtsSector(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum) + public static void EncryptXtsSectorInPlace(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum) { SetupRawCipher(alg); @@ -82,7 +108,7 @@ public static void EncryptXtsSector(this SymmetricAlgorithm alg, byte[] buffer, ProcessXtsSector(encryptor, buffer, 0, buffer.Length, tweak, false); } - public static void DecryptXtsSector(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum) + public static void DecryptXtsSectorInPlace(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum) { SetupRawCipher(alg); diff --git a/tests/IeeeVectorsTests.cs b/tests/IeeeVectorsTests.cs index 51cfed4..3016f7f 100644 --- a/tests/IeeeVectorsTests.cs +++ b/tests/IeeeVectorsTests.cs @@ -32,10 +32,10 @@ public void Vector1Test() byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - aes.EncryptXtsSector(ciphertext, key, sector); + aes.EncryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); - aes.DecryptXtsSector(ciphertext, key, sector); + aes.DecryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); } @@ -69,10 +69,10 @@ public void Vector2Test() byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - aes.EncryptXtsSector(ciphertext, key, sector); + aes.EncryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); - aes.DecryptXtsSector(ciphertext, key, sector); + aes.DecryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); } @@ -106,10 +106,10 @@ public void Vector3Test() byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - aes.EncryptXtsSector(ciphertext, key, sector); + aes.EncryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); - aes.DecryptXtsSector(ciphertext, key, sector); + aes.DecryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); } @@ -263,10 +263,10 @@ public void Vector4Test() byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - aes.EncryptXtsSector(ciphertext, key, sector); + aes.EncryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); - aes.DecryptXtsSector(ciphertext, key, sector); + aes.DecryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); } @@ -420,10 +420,10 @@ public void Vector5Test() byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - aes.EncryptXtsSector(ciphertext, key, sector); + aes.EncryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); - aes.DecryptXtsSector(ciphertext, key, sector); + aes.DecryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); } @@ -577,10 +577,10 @@ public void Vector6Test() byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - aes.EncryptXtsSector(ciphertext, key, sector); + aes.EncryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); - aes.DecryptXtsSector(ciphertext, key, sector); + aes.DecryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); } @@ -734,10 +734,10 @@ public void Vector7Test() byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - aes.EncryptXtsSector(ciphertext, key, sector); + aes.EncryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); - aes.DecryptXtsSector(ciphertext, key, sector); + aes.DecryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); } @@ -891,10 +891,10 @@ public void Vector8Test() byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - aes.EncryptXtsSector(ciphertext, key, sector); + aes.EncryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); - aes.DecryptXtsSector(ciphertext, key, sector); + aes.DecryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); } @@ -1048,10 +1048,10 @@ public void Vector9Test() byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - aes.EncryptXtsSector(ciphertext, key, sector); + aes.EncryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); - aes.DecryptXtsSector(ciphertext, key, sector); + aes.DecryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); } @@ -1209,10 +1209,10 @@ public void Vector10Test() byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - aes.EncryptXtsSector(ciphertext, key, sector); + aes.EncryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); - aes.DecryptXtsSector(ciphertext, key, sector); + aes.DecryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); } @@ -1370,10 +1370,10 @@ public void Vector11Test() byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - aes.EncryptXtsSector(ciphertext, key, sector); + aes.EncryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); - aes.DecryptXtsSector(ciphertext, key, sector); + aes.DecryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); } @@ -1531,10 +1531,10 @@ public void Vector12Test() byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - aes.EncryptXtsSector(ciphertext, key, sector); + aes.EncryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); - aes.DecryptXtsSector(ciphertext, key, sector); + aes.DecryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); } @@ -1692,10 +1692,10 @@ public void Vector13Test() byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - aes.EncryptXtsSector(ciphertext, key, sector); + aes.EncryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); - aes.DecryptXtsSector(ciphertext, key, sector); + aes.DecryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); } @@ -1853,10 +1853,10 @@ public void Vector14Test() byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - aes.EncryptXtsSector(ciphertext, key, sector); + aes.EncryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); - aes.DecryptXtsSector(ciphertext, key, sector); + aes.DecryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); } @@ -1888,10 +1888,10 @@ public void Vector15Test() byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - aes.EncryptXtsSector(ciphertext, key, sector); + aes.EncryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); - aes.DecryptXtsSector(ciphertext, key, sector); + aes.DecryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); } @@ -1923,10 +1923,10 @@ public void Vector16Test() byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - aes.EncryptXtsSector(ciphertext, key, sector); + aes.EncryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); - aes.DecryptXtsSector(ciphertext, key, sector); + aes.DecryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); } @@ -1958,10 +1958,10 @@ public void Vector17Test() byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - aes.EncryptXtsSector(ciphertext, key, sector); + aes.EncryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); - aes.DecryptXtsSector(ciphertext, key, sector); + aes.DecryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); } @@ -1993,10 +1993,10 @@ public void Vector18Test() byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - aes.EncryptXtsSector(ciphertext, key, sector); + aes.EncryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); - aes.DecryptXtsSector(ciphertext, key, sector); + aes.DecryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); } @@ -2150,10 +2150,10 @@ public void Vector19Test() byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - aes.EncryptXtsSector(ciphertext, key, sector); + aes.EncryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedCiphertext)); - aes.DecryptXtsSector(ciphertext, key, sector); + aes.DecryptXtsSectorInPlace(ciphertext, key, sector); Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); } diff --git a/tests/Tests.cs b/tests/Tests.cs index 5001561..504ecc3 100644 --- a/tests/Tests.cs +++ b/tests/Tests.cs @@ -24,12 +24,12 @@ public void EncryptDecryptTest() Aes cipher = Aes.Create(); byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - cipher.EncryptXts(ciphertext, key, 0, 520); + cipher.EncryptXtsInPlace(ciphertext, key, 0, 520); // Ensures some form of data transformation happened Assert.That(ciphertext, Is.Not.EqualTo(expectedPlaintext)); - cipher.DecryptXts(ciphertext, key, 0, 520); + cipher.DecryptXtsInPlace(ciphertext, key, 0, 520); Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); } @@ -54,12 +54,12 @@ public void EncryptDecrypt256Test() Aes cipher = Aes.Create(); byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - cipher.EncryptXts(ciphertext, key, 0, 520); + cipher.EncryptXtsInPlace(ciphertext, key, 0, 520); // Ensures some form of data transformation happened Assert.That(ciphertext, Is.Not.EqualTo(expectedPlaintext)); - cipher.DecryptXts(ciphertext, key, 0, 520); + cipher.DecryptXtsInPlace(ciphertext, key, 0, 520); Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); } @@ -80,12 +80,12 @@ public void NoStealingTestCase() byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - cipher.EncryptXts(ciphertext, key, 0, 520); + cipher.EncryptXtsInPlace(ciphertext, key, 0, 520); // Ensures some form of data transformation happened Assert.That(ciphertext, Is.Not.EqualTo(expectedPlaintext)); - cipher.DecryptXts(ciphertext, key, 0, 520); + cipher.DecryptXtsInPlace(ciphertext, key, 0, 520); Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); } @@ -106,12 +106,12 @@ public void ExactSectorTestCase() byte[] ciphertext = (byte[])expectedPlaintext.Clone(); - cipher.EncryptXts(ciphertext, key, 0, 100); + cipher.EncryptXtsInPlace(ciphertext, key, 0, 100); // Ensures some form of data transformation happened Assert.That(ciphertext, Is.Not.EqualTo(expectedPlaintext)); - cipher.DecryptXts(ciphertext, key, 0, 100); + cipher.DecryptXtsInPlace(ciphertext, key, 0, 100); Assert.That(ciphertext, Is.EqualTo(expectedPlaintext)); } From bb4987a203e6e21978eb831c85c54adae4a0518e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Dugr=C3=A9?= Date: Tue, 19 Nov 2024 09:43:19 -0500 Subject: [PATCH 10/15] Added documentation --- src/XTS.cs | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 109 insertions(+), 2 deletions(-) diff --git a/src/XTS.cs b/src/XTS.cs index 44d5a21..d515f2c 100644 --- a/src/XTS.cs +++ b/src/XTS.cs @@ -6,7 +6,18 @@ namespace XTS.NET { public static class XTS { + // Derived from polynomial x^128 + x^7 + x^2 + x + 1 private const byte GF_MOD = 135; + + /// + /// Encrypt multiple sectors of data using XTS mode + /// + /// A SymmetricAlgorithm representing the underlying block cipher. In a regular scenario, you can use Aes.Create() to get this. + /// The data to encrypt + /// The key to use. Note that XTS mode uses a key twice the underlying size of the block cipher. + /// The sector number, also known as the tweak. This is the equivalent of the IV/Nonce for other modes. + /// The size of a sector. This function allows encrypting multiple sector. Use the Sector variants if you don't care about this. + /// The encrypted data public static byte[] EncryptXts(this SymmetricAlgorithm alg, ReadOnlySpan input, ReadOnlySpan key, BigInteger sectorNum, int sectorSize) { byte[] buffer = input.ToArray(); @@ -14,12 +25,30 @@ public static byte[] EncryptXts(this SymmetricAlgorithm alg, ReadOnlySpan return buffer; } + /// + /// Decrypt multiple sectors of data using XTS mode + /// + /// A SymmetricAlgorithm representing the underlying block cipher. In a regular scenario, you can use Aes.Create() to get this. + /// The data to decrypt + /// The key to use. Note that XTS mode uses a key twice the underlying size of the block cipher. + /// The sector number, also known as the tweak. This is the equivalent of the IV/Nonce for other modes. + /// The size of a sector. This function allows decrypting multiple sector. Use the Sector variants if you don't care about this. + /// The decrypted data public static byte[] DecryptXts(this SymmetricAlgorithm alg, ReadOnlySpan input, ReadOnlySpan key, BigInteger sectorNum, int sectorSize) { byte[] buffer = input.ToArray(); alg.DecryptXtsInPlace(buffer, key, sectorNum, sectorSize); return buffer; } + + /// + /// Encrypt data using XTS mode + /// + /// A SymmetricAlgorithm representing the underlying block cipher. In a regular scenario, you can use Aes.Create() to get this. + /// The data to encrypt + /// The key to use. Note that XTS mode uses a key twice the underlying size of the block cipher. + /// The sector number, also known as the tweak. This is the equivalent of the IV/Nonce for other modes. + /// The encrypted data public static byte[] EncryptXtsSector(this SymmetricAlgorithm alg, ReadOnlySpan input, ReadOnlySpan key, BigInteger sectorNum) { byte[] buffer = input.ToArray(); @@ -27,6 +56,14 @@ public static byte[] EncryptXtsSector(this SymmetricAlgorithm alg, ReadOnlySpan< return buffer; } + /// + /// Decrypt data using XTS mode + /// + /// A SymmetricAlgorithm representing the underlying block cipher. In a regular scenario, you can use Aes.Create() to get this. + /// The data to decrypt + /// The key to use. Note that XTS mode uses a key twice the underlying size of the block cipher. + /// The sector number, also known as the tweak. This is the equivalent of the IV/Nonce for other modes. + /// The decrypted data public static byte[] DecryptXtsSector(this SymmetricAlgorithm alg, ReadOnlySpan input, ReadOnlySpan key, BigInteger sectorNum) { byte[] buffer = input.ToArray(); @@ -34,6 +71,15 @@ public static byte[] DecryptXtsSector(this SymmetricAlgorithm alg, ReadOnlySpan< return buffer; } + /// + /// Encrypt multiple sectors of data using XTS mode in place + /// + /// A SymmetricAlgorithm representing the underlying block cipher. In a regular scenario, you can use Aes.Create() to get this. + /// The data to encrypt, and also the output buffer + /// The key to use. Note that XTS mode uses a key twice the underlying size of the block cipher. + /// The sector number, also known as the tweak. This is the equivalent of the IV/Nonce for other modes. + /// The size of a sector. This function allows encrypting multiple sector. Use the Sector variants if you don't care about this. + /// The encrypted data public static void EncryptXtsInPlace(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum, int sectorSize) { SetupRawCipher(alg); @@ -64,6 +110,15 @@ public static void EncryptXtsInPlace(this SymmetricAlgorithm alg, byte[] buffer, } } + /// + /// Decrypt multiple sectors of data using XTS mode in place + /// + /// A SymmetricAlgorithm representing the underlying block cipher. In a regular scenario, you can use Aes.Create() to get this. + /// The data to decrypt, and also the output buffer + /// The key to use. Note that XTS mode uses a key twice the underlying size of the block cipher. + /// The sector number, also known as the tweak. This is the equivalent of the IV/Nonce for other modes. + /// The size of a sector. This function allows encrypting multiple sector. Use the Sector variants if you don't care about this. + /// The decrypted data public static void DecryptXtsInPlace(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum, int sectorSize) { SetupRawCipher(alg); @@ -94,6 +149,14 @@ public static void DecryptXtsInPlace(this SymmetricAlgorithm alg, byte[] buffer, } } + /// + /// Encrypt data using XTS mode in place + /// + /// A SymmetricAlgorithm representing the underlying block cipher. In a regular scenario, you can use Aes.Create() to get this. + /// The data to encrypt and also the output buffer + /// The key to use. Note that XTS mode uses a key twice the underlying size of the block cipher. + /// The sector number, also known as the tweak. This is the equivalent of the IV/Nonce for other modes. + /// The encrypted data public static void EncryptXtsSectorInPlace(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum) { SetupRawCipher(alg); @@ -108,6 +171,14 @@ public static void EncryptXtsSectorInPlace(this SymmetricAlgorithm alg, byte[] b ProcessXtsSector(encryptor, buffer, 0, buffer.Length, tweak, false); } + /// + /// Decrypt data using XTS mode in place + /// + /// A SymmetricAlgorithm representing the underlying block cipher. In a regular scenario, you can use Aes.Create() to get this. + /// The data to decrypt and also the output buffer + /// The key to use. Note that XTS mode uses a key twice the underlying size of the block cipher. + /// The sector number, also known as the tweak. This is the equivalent of the IV/Nonce for other modes. + /// The decrypted data public static void DecryptXtsSectorInPlace(this SymmetricAlgorithm alg, byte[] buffer, ReadOnlySpan key, BigInteger sectorNum) { SetupRawCipher(alg); @@ -122,6 +193,16 @@ public static void DecryptXtsSectorInPlace(this SymmetricAlgorithm alg, byte[] b ProcessXtsSector(decryptor, buffer, 0, buffer.Length, tweak, true); } + /// + /// The core XTS function. This encrypts/decrypts a sector in place + /// + /// The block cipher encrypt/decrypt interface + /// The input and output buffer + /// The offset where to start processing + /// The length of the data to process + /// The initial tweak value, which is an encryption of the sector number + /// A bool telling weither or not this is a decryption. There is a single place where the function may differ based on that. + /// Throws if the sector has less data then a full block, since this case is unsupported by XTS by design. private static void ProcessXtsSector(ICryptoTransform alg, byte[] buffer, int bufferOffset, int bufferLength, Span tweak, bool decrypt) { int blockSize = alg.InputBlockSize; @@ -187,6 +268,13 @@ private static void ProcessXtsSector(ICryptoTransform alg, byte[] buffer, int bu } } + /// + /// Encrypt the sector number into a tweak using K2 + /// + /// The block cipher to use + /// The key to use + /// The sector number + /// The tweak private static byte[] EncryptTweak(SymmetricAlgorithm alg, ReadOnlySpan key, BigInteger sectorNum) { int blockSize = alg.BlockSize / 8; @@ -204,6 +292,10 @@ private static byte[] EncryptTweak(SymmetricAlgorithm alg, ReadOnlySpan ke return tweak; } + /// + /// Setup the block cipher to be ECB without padding, since we are implementing both manually + /// + /// private static void SetupRawCipher(SymmetricAlgorithm alg) { // Setup for raw cipher, without mode or padding @@ -211,6 +303,13 @@ private static void SetupRawCipher(SymmetricAlgorithm alg) alg.Padding = PaddingMode.None; } + /// + /// Execute the block cipher + /// + /// The block cipher implementation + /// The working buffer + /// The offset from which the data is being worked on in the buffer + /// The tweak private static void TransformBlock(ICryptoTransform alg, byte[] buffer, int bufferOffset, ReadOnlySpan tweak) { // Get block size from the transform @@ -225,6 +324,11 @@ private static void TransformBlock(ICryptoTransform alg, byte[] buffer, int buff XorBlocksInPlace(tweak, outputSpan); } + /// + /// XOR a span into another + /// + /// The input block, which is XORed into the output + /// The receiving buffer private static void XorBlocksInPlace(ReadOnlySpan input, Span output) { for (int i = 0; i < output.Length; i++) @@ -233,6 +337,11 @@ private static void XorBlocksInPlace(ReadOnlySpan input, Span output } } + /// + /// Swap data from one span to another. + /// + /// The first span + /// The second span private static void SwapSpan(Span x, Span y) { for (int i = 0; i < x.Length; i++) @@ -268,7 +377,6 @@ private static bool GaloisMultiplyByTwo(Span tweak) if (carry) { - // Derived from polynomial x^128 + x^7 + x^2 + x + 1 tweak[0] ^= GF_MOD; } @@ -285,7 +393,6 @@ private static void GaloisUnmultiplyByTwo(Span tweak, bool carry) { if (carry) { - // Derived from polynomial x^128 + x^7 + x^2 + x + 1 tweak[0] ^= GF_MOD; } From c035869939d200ced8b60af5f5ce8a2dca2c843d Mon Sep 17 00:00:00 2001 From: Philippe Dugre <38759268+pdugre@users.noreply.github.com> Date: Tue, 19 Nov 2024 09:43:34 -0500 Subject: [PATCH 11/15] Update .github/workflows/ci.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Danny Bédard --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1b05ee9..dd766c1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,7 @@ on: - master pull_request: workflow_dispatch: + jobs: build: From 4f53bdd779e28c68bca30315180494f46b78a258 Mon Sep 17 00:00:00 2001 From: Philippe Dugre <38759268+pdugre@users.noreply.github.com> Date: Tue, 19 Nov 2024 09:43:41 -0500 Subject: [PATCH 12/15] Update .github/workflows/ci.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Danny Bédard --- .github/workflows/ci.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dd766c1..e2b67b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,9 +28,8 @@ jobs: run: dotnet test - name: Generate NuGet - run: | - cd src/ - dotnet pack -o package /p:Version=$(date "+%-Y.%-m.%-d") + run: dotnet pack -o package /p:Version=$(date "+%-Y.%-m.%-d") + working-directory: src - uses: actions/upload-artifact@v4.3.6 with: From f7ea4e127c3d322cb463d8906a053c0ce9ff051d Mon Sep 17 00:00:00 2001 From: Philippe Dugre <38759268+pdugre@users.noreply.github.com> Date: Tue, 19 Nov 2024 09:43:48 -0500 Subject: [PATCH 13/15] Update .github/workflows/release.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Danny Bédard --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c513e9b..370a892 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,11 +6,11 @@ on: description: "Publish Devolutions.XTS.NET" required: true type: boolean - publish_dry_run: description: "Dry Run Mode" required: true type: boolean + jobs: deploy: runs-on: ubuntu-latest From 6eeb3e2f798c7fc6af706ff4f6ce837fc2ae60fb Mon Sep 17 00:00:00 2001 From: Philippe Dugre <38759268+pdugre@users.noreply.github.com> Date: Tue, 19 Nov 2024 09:43:55 -0500 Subject: [PATCH 14/15] Update .github/workflows/release.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Danny Bédard --- .github/workflows/release.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 370a892..4a8c808 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,11 +32,10 @@ jobs: github_token: ${{ secrets.DEVOLUTIONSBOT_TOKEN }} - name: Download Nugets Artifact + run: dv github download-artifact nugets . XTS.NET env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CI: true - run: | - dv github download-artifact nugets . XTS.NET - name: Extract Artifacts run: | From e78abf08f4840b826b8a3f0d029834b69978e9c1 Mon Sep 17 00:00:00 2001 From: Philippe Dugre <38759268+pdugre@users.noreply.github.com> Date: Tue, 19 Nov 2024 09:44:00 -0500 Subject: [PATCH 15/15] Update .github/workflows/release.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Danny Bédard --- .github/workflows/release.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4a8c808..870dbb7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -38,8 +38,7 @@ jobs: CI: true - name: Extract Artifacts - run: | - 7z x nugets.zip -o./nugets + run: 7z x nugets.zip -o./nugets - name: Publish NuGet if: ${{ inputs.publish_nuget }}