(bugfix): add remove padding, code review
This commit is contained in:
parent
225debf8f2
commit
fcbf7e17b5
@ -244,27 +244,7 @@ public class Application {
|
||||
});
|
||||
}
|
||||
|
||||
private static byte[] AddPadding(byte[] data, int blockSize) {
|
||||
// Calculate the padding size
|
||||
int paddingSize = blockSize - (data.Length % blockSize);
|
||||
if (paddingSize == blockSize) {
|
||||
paddingSize = 0;
|
||||
}
|
||||
|
||||
// Create a new array with the original data plus padding
|
||||
byte[] paddedData = new byte[data.Length + paddingSize + 1];
|
||||
Array.Copy(data, paddedData, data.Length);
|
||||
|
||||
// Fill the padding with a specific value (e.g., 0x00)
|
||||
for (int i = data.Length; i < paddedData.Length - 1; i++) {
|
||||
paddedData[i] = 0x00;
|
||||
}
|
||||
|
||||
// Append the padding size at the end
|
||||
paddedData[paddedData.Length - 1] = (byte)paddingSize;
|
||||
|
||||
return paddedData;
|
||||
}
|
||||
|
||||
private void WriteFilesToTape(WorkingFolder workingFolder, string descriptorFilePath, uint blockSize) {
|
||||
PathAccessWrapper(workingFolder, (directoryPath) => {
|
||||
@ -334,7 +314,7 @@ public class Application {
|
||||
var encryptedDescriptorData = AESGCMUtility.EncryptData(descriptorData, _secret);
|
||||
|
||||
// add padding to the encrypted descriptor data
|
||||
var paddedDescriptorData = AddPadding(encryptedDescriptorData, (int)blockSize);
|
||||
var paddedDescriptorData = PaddingUtility.AddPadding(encryptedDescriptorData, (int)blockSize);
|
||||
|
||||
// calculate the number of blocks needed
|
||||
var descriptorBlocks = (paddedDescriptorData.Length + blockSize - 1) / blockSize;
|
||||
@ -381,55 +361,53 @@ public class Application {
|
||||
handler.SetPosition(TapeDeviceHandler.TAPE_SPACE_FILEMARKS, 0, 1);
|
||||
Thread.Sleep(2000);
|
||||
|
||||
var position = handler.GetPosition(TapeDeviceHandler.TAPE_ABSOLUTE_BLOCK);
|
||||
if (position.Error != null)
|
||||
var endOfBackupMarkerPosition = handler.GetPosition(TapeDeviceHandler.TAPE_ABSOLUTE_BLOCK);
|
||||
if (endOfBackupMarkerPosition.Error != null || endOfBackupMarkerPosition.OffsetLow == null)
|
||||
return null;
|
||||
|
||||
var desctiptorBlocks = position.OffsetLow;
|
||||
_logger.LogInformation($"End of backup marker position: {endOfBackupMarkerPosition.OffsetLow}");
|
||||
|
||||
var descriptorBlocks = endOfBackupMarkerPosition.OffsetLow;
|
||||
|
||||
handler.SetPosition(TapeDeviceHandler.TAPE_SPACE_FILEMARKS, 0, 2);
|
||||
Thread.Sleep(2000);
|
||||
|
||||
position = handler.GetPosition(TapeDeviceHandler.TAPE_ABSOLUTE_BLOCK);
|
||||
if (position.Error != null)
|
||||
var endOfDescriptorMarkerPosition = handler.GetPosition(TapeDeviceHandler.TAPE_ABSOLUTE_BLOCK);
|
||||
if (endOfDescriptorMarkerPosition.Error != null || endOfDescriptorMarkerPosition.OffsetLow == null)
|
||||
return null;
|
||||
|
||||
desctiptorBlocks = position.OffsetLow - desctiptorBlocks;
|
||||
_logger.LogInformation($"End of descriptor marker position: {endOfDescriptorMarkerPosition.OffsetLow}");
|
||||
|
||||
descriptorBlocks = endOfDescriptorMarkerPosition.OffsetLow - descriptorBlocks;
|
||||
|
||||
var padding = handler.ReadData(blockSize);
|
||||
if (descriptorBlocks == null)
|
||||
return null;
|
||||
|
||||
handler.SetPosition(TapeDeviceHandler.TAPE_SPACE_FILEMARKS, 0, 1);
|
||||
_logger.LogInformation($"Descriptor blocks to read: {descriptorBlocks}");
|
||||
|
||||
handler.SetPosition(TapeDeviceHandler.TAPE_ABSOLUTE_BLOCK, 0, (long)(endOfDescriptorMarkerPosition.OffsetLow - descriptorBlocks));
|
||||
Thread.Sleep(2000);
|
||||
|
||||
// read data from descriptorBlocks
|
||||
var buffer = new List<byte>();
|
||||
for (var i = 0; i < desctiptorBlocks; i++) {
|
||||
var data = handler.ReadData(blockSize);
|
||||
buffer.AddRange(data);
|
||||
descriptorBlocks -= 2;
|
||||
|
||||
var paddedData = new byte[(descriptorBlocks.Value) * blockSize];
|
||||
var buffer = new byte[blockSize];
|
||||
|
||||
for (var i = 0; i < descriptorBlocks; i++) {
|
||||
var bytesRead = handler.ReadData(buffer, 0, buffer.Length);
|
||||
|
||||
// Copy the read data into the encryptedData array
|
||||
Array.Copy(buffer, 0, paddedData, i * blockSize, buffer.Length);
|
||||
}
|
||||
|
||||
// Convert buffer to array
|
||||
var paddedData = buffer.ToArray();
|
||||
// i need to remove padding from the data
|
||||
var encryptedData = PaddingUtility.RemovePadding(paddedData, (int)blockSize);
|
||||
|
||||
// Retrieve the padding size from the last byte
|
||||
int paddingSize = paddedData[^1];
|
||||
|
||||
// Calculate the length of the original data
|
||||
int originalDataLength = paddedData.Length - paddingSize - 1;
|
||||
|
||||
// Ensure the padding size is valid
|
||||
if (paddingSize < 0 || paddingSize >= paddedData.Length || originalDataLength < 0)
|
||||
return null;
|
||||
|
||||
// Create a new array for the original data
|
||||
var descriptorData = new byte[originalDataLength];
|
||||
Array.Copy(paddedData, descriptorData, originalDataLength);
|
||||
|
||||
descriptorData = AESGCMUtility.DecryptData(descriptorData, _secret);
|
||||
// decrypt the data
|
||||
var decryptedData = AESGCMUtility.DecryptData(encryptedData, _secret);
|
||||
|
||||
// Convert byte array to string and trim ending zeros
|
||||
var json = Encoding.UTF8.GetString(descriptorData);
|
||||
var json = Encoding.UTF8.GetString(decryptedData);
|
||||
|
||||
try {
|
||||
var descriptor = JsonSerializer.Deserialize<BackupDescriptor>(json);
|
||||
@ -514,7 +492,7 @@ public class Application {
|
||||
|
||||
var encryptedDescriptorData = AESGCMUtility.EncryptData(File.ReadAllBytes(_descriptorFilePath), _secret);
|
||||
|
||||
var paddedDescriptorData = AddPadding(encryptedDescriptorData, (int)descriptor.BlockSize);
|
||||
var paddedDescriptorData = PaddingUtility.AddPadding(encryptedDescriptorData, (int)descriptor.BlockSize);
|
||||
|
||||
const ulong fileMarkBlocks = 2;
|
||||
|
||||
|
||||
87
src/MaksIT.LTO.Core/Crc32.cs
Normal file
87
src/MaksIT.LTO.Core/Crc32.cs
Normal file
@ -0,0 +1,87 @@
|
||||
using System.Security.Cryptography;
|
||||
|
||||
|
||||
namespace MaksIT.LTO.Core;
|
||||
|
||||
public class Crc32 : HashAlgorithm {
|
||||
public const uint DefaultPolynomial = 0xedb88320;
|
||||
public const uint DefaultSeed = 0xffffffff;
|
||||
|
||||
private static uint[]? defaultTable;
|
||||
|
||||
private readonly uint seed;
|
||||
private readonly uint[] table;
|
||||
private uint hash;
|
||||
|
||||
public Crc32()
|
||||
: this(DefaultPolynomial, DefaultSeed) {
|
||||
}
|
||||
|
||||
public Crc32(uint polynomial, uint seed) {
|
||||
table = InitializeTable(polynomial);
|
||||
this.seed = hash = seed;
|
||||
}
|
||||
|
||||
public override void Initialize() {
|
||||
hash = seed;
|
||||
}
|
||||
|
||||
protected override void HashCore(byte[] buffer, int start, int length) {
|
||||
hash = CalculateHash(table, hash, buffer, start, length);
|
||||
}
|
||||
|
||||
protected override byte[] HashFinal() {
|
||||
var hashBuffer = UInt32ToBigEndianBytes(~hash);
|
||||
HashValue = hashBuffer;
|
||||
return hashBuffer;
|
||||
}
|
||||
|
||||
public override int HashSize => 32;
|
||||
|
||||
public static uint Compute(byte[] buffer) {
|
||||
return Compute(DefaultPolynomial, DefaultSeed, buffer);
|
||||
}
|
||||
|
||||
public static uint Compute(uint seed, byte[] buffer) {
|
||||
return Compute(DefaultPolynomial, seed, buffer);
|
||||
}
|
||||
|
||||
public static uint Compute(uint polynomial, uint seed, byte[] buffer) {
|
||||
return ~CalculateHash(InitializeTable(polynomial), seed, buffer, 0, buffer.Length);
|
||||
}
|
||||
|
||||
private static uint[] InitializeTable(uint polynomial) {
|
||||
if (polynomial == DefaultPolynomial && defaultTable != null)
|
||||
return defaultTable;
|
||||
|
||||
var createTable = new uint[256];
|
||||
for (var i = 0; i < 256; i++) {
|
||||
var entry = (uint)i;
|
||||
for (var j = 0; j < 8; j++)
|
||||
if ((entry & 1) == 1)
|
||||
entry = (entry >> 1) ^ polynomial;
|
||||
else
|
||||
entry >>= 1;
|
||||
createTable[i] = entry;
|
||||
}
|
||||
|
||||
if (polynomial == DefaultPolynomial)
|
||||
defaultTable = createTable;
|
||||
|
||||
return createTable;
|
||||
}
|
||||
|
||||
private static uint CalculateHash(uint[] table, uint seed, byte[] buffer, int start, int size) {
|
||||
var crc = seed;
|
||||
for (var i = start; i < size - start; i++)
|
||||
crc = (crc >> 8) ^ table[buffer[i] ^ crc & 0xff];
|
||||
return crc;
|
||||
}
|
||||
|
||||
private static byte[] UInt32ToBigEndianBytes(uint x) => [
|
||||
(byte)((x >> 24) & 0xff),
|
||||
(byte)((x >> 16) & 0xff),
|
||||
(byte)((x >> 8) & 0xff),
|
||||
(byte)(x & 0xff)
|
||||
];
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
|
||||
namespace MaksIT.LTO.Core;
|
||||
public class DriverManager {
|
||||
public static void RestartDriver(string deviceName) {
|
||||
string script = $@"
|
||||
$device = Get-PnpDevice -FriendlyName '{deviceName}'
|
||||
Disable-PnpDevice -InstanceId $device.InstanceId -Confirm:$false
|
||||
Start-Sleep -Seconds 5
|
||||
Enable-PnpDevice -InstanceId $device.InstanceId -Confirm:$false
|
||||
";
|
||||
|
||||
ProcessStartInfo psi = new ProcessStartInfo {
|
||||
FileName = "powershell.exe",
|
||||
Arguments = $"-NoProfile -ExecutionPolicy Bypass -Command \"{script}\"",
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true
|
||||
};
|
||||
|
||||
using (Process process = Process.Start(psi)) {
|
||||
string output = process.StandardOutput.ReadToEnd();
|
||||
string error = process.StandardError.ReadToEnd();
|
||||
process.WaitForExit();
|
||||
|
||||
Console.WriteLine(output);
|
||||
if (!string.IsNullOrEmpty(error)) {
|
||||
Console.WriteLine($"Error: {error}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,19 +1,16 @@
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace MaksIT.LTO.Core.Helpers;
|
||||
namespace MaksIT.LTO.Core.Helpers;
|
||||
|
||||
public static class ChecksumUtility {
|
||||
public static string CalculateCRC32Checksum(byte[] data) {
|
||||
using var crc32 = new Crc32();
|
||||
byte[] hashBytes = crc32.ComputeHash(data);
|
||||
var hashBytes = crc32.ComputeHash(data);
|
||||
return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
|
||||
}
|
||||
|
||||
public static string CalculateCRC32ChecksumFromFile(string filePath) {
|
||||
using var crc32 = new Crc32();
|
||||
using var stream = File.OpenRead(filePath);
|
||||
byte[] hashBytes = crc32.ComputeHash(stream);
|
||||
var hashBytes = crc32.ComputeHash(stream);
|
||||
return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
|
||||
}
|
||||
|
||||
@ -26,105 +23,23 @@ public static class ChecksumUtility {
|
||||
crc32.TransformBlock(buffer, 0, bytesRead, null, 0);
|
||||
}
|
||||
crc32.TransformFinalBlock(buffer, 0, 0);
|
||||
byte[] hashBytes = crc32.Hash;
|
||||
return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
|
||||
var hashBytes = crc32.Hash;
|
||||
return BitConverter.ToString(hashBytes ?? Array.Empty<byte>()).Replace("-", "").ToLower();
|
||||
}
|
||||
|
||||
public static bool VerifyCRC32Checksum(byte[] data, string expectedChecksum) {
|
||||
string calculatedChecksum = CalculateCRC32Checksum(data);
|
||||
var calculatedChecksum = CalculateCRC32Checksum(data);
|
||||
return string.Equals(calculatedChecksum, expectedChecksum, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public static bool VerifyCRC32ChecksumFromFile(string filePath, string expectedChecksum) {
|
||||
string calculatedChecksum = CalculateCRC32ChecksumFromFile(filePath);
|
||||
var calculatedChecksum = CalculateCRC32ChecksumFromFile(filePath);
|
||||
return string.Equals(calculatedChecksum, expectedChecksum, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public static bool VerifyCRC32ChecksumFromFileInChunks(string filePath, string expectedChecksum, int chunkSize = 8192) {
|
||||
string calculatedChecksum = CalculateCRC32ChecksumFromFileInChunks(filePath, chunkSize);
|
||||
var calculatedChecksum = CalculateCRC32ChecksumFromFileInChunks(filePath, chunkSize);
|
||||
return string.Equals(calculatedChecksum, expectedChecksum, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
public class Crc32 : HashAlgorithm {
|
||||
public const uint DefaultPolynomial = 0xedb88320;
|
||||
public const uint DefaultSeed = 0xffffffff;
|
||||
|
||||
private static uint[]? defaultTable;
|
||||
|
||||
private readonly uint seed;
|
||||
private readonly uint[] table;
|
||||
private uint hash;
|
||||
|
||||
public Crc32()
|
||||
: this(DefaultPolynomial, DefaultSeed) {
|
||||
}
|
||||
|
||||
public Crc32(uint polynomial, uint seed) {
|
||||
table = InitializeTable(polynomial);
|
||||
this.seed = hash = seed;
|
||||
}
|
||||
|
||||
public override void Initialize() {
|
||||
hash = seed;
|
||||
}
|
||||
|
||||
protected override void HashCore(byte[] buffer, int start, int length) {
|
||||
hash = CalculateHash(table, hash, buffer, start, length);
|
||||
}
|
||||
|
||||
protected override byte[] HashFinal() {
|
||||
var hashBuffer = UInt32ToBigEndianBytes(~hash);
|
||||
HashValue = hashBuffer;
|
||||
return hashBuffer;
|
||||
}
|
||||
|
||||
public override int HashSize => 32;
|
||||
|
||||
public static uint Compute(byte[] buffer) {
|
||||
return Compute(DefaultPolynomial, DefaultSeed, buffer);
|
||||
}
|
||||
|
||||
public static uint Compute(uint seed, byte[] buffer) {
|
||||
return Compute(DefaultPolynomial, seed, buffer);
|
||||
}
|
||||
|
||||
public static uint Compute(uint polynomial, uint seed, byte[] buffer) {
|
||||
return ~CalculateHash(InitializeTable(polynomial), seed, buffer, 0, buffer.Length);
|
||||
}
|
||||
|
||||
private static uint[] InitializeTable(uint polynomial) {
|
||||
if (polynomial == DefaultPolynomial && defaultTable != null)
|
||||
return defaultTable;
|
||||
|
||||
var createTable = new uint[256];
|
||||
for (var i = 0; i < 256; i++) {
|
||||
var entry = (uint)i;
|
||||
for (var j = 0; j < 8; j++)
|
||||
if ((entry & 1) == 1)
|
||||
entry = (entry >> 1) ^ polynomial;
|
||||
else
|
||||
entry >>= 1;
|
||||
createTable[i] = entry;
|
||||
}
|
||||
|
||||
if (polynomial == DefaultPolynomial)
|
||||
defaultTable = createTable;
|
||||
|
||||
return createTable;
|
||||
}
|
||||
|
||||
private static uint CalculateHash(uint[] table, uint seed, byte[] buffer, int start, int size) {
|
||||
var crc = seed;
|
||||
for (var i = start; i < size - start; i++)
|
||||
crc = (crc >> 8) ^ table[buffer[i] ^ crc & 0xff];
|
||||
return crc;
|
||||
}
|
||||
|
||||
private static byte[] UInt32ToBigEndianBytes(uint x) => [
|
||||
(byte)((x >> 24) & 0xff),
|
||||
(byte)((x >> 16) & 0xff),
|
||||
(byte)((x >> 8) & 0xff),
|
||||
(byte)(x & 0xff)
|
||||
];
|
||||
}
|
||||
|
||||
38
src/MaksIT.LTO.Core/Utilities/PaddingUtility.cs
Normal file
38
src/MaksIT.LTO.Core/Utilities/PaddingUtility.cs
Normal file
@ -0,0 +1,38 @@
|
||||
namespace MaksIT.LTO.Core.Utilities;
|
||||
|
||||
public static class PaddingUtility {
|
||||
|
||||
private const byte _specialByte = 0x80;
|
||||
|
||||
public static byte[] AddPadding(byte[] data, int blockSize) {
|
||||
var paddingSize = blockSize - (data.Length % blockSize);
|
||||
if (paddingSize == blockSize) {
|
||||
paddingSize = 0; // no padding needed if already aligned
|
||||
}
|
||||
|
||||
var paddedData = new byte[data.Length + paddingSize];
|
||||
Array.Copy(data, paddedData, data.Length);
|
||||
|
||||
// fill the padding bytes with specialBytes
|
||||
for (var i = data.Length; i < paddedData.Length; i++) {
|
||||
paddedData[i] = _specialByte;
|
||||
}
|
||||
|
||||
return paddedData;
|
||||
}
|
||||
|
||||
public static byte[] RemovePadding(byte[] paddedData, int blockSize) {
|
||||
var originalLength = paddedData.Length;
|
||||
|
||||
// find the original length by checking for the padding byte 0x80
|
||||
while (originalLength > 0 && paddedData[originalLength - 1] == _specialByte) {
|
||||
originalLength--;
|
||||
}
|
||||
|
||||
// create a new array to hold the unpadded data
|
||||
var unpaddedData = new byte[originalLength];
|
||||
Array.Copy(paddedData, unpaddedData, originalLength);
|
||||
|
||||
return unpaddedData;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user