EasyPQC.FileOperations

Types

PackedFile

Represents a packed (compressed + optionally encrypted) file along with its cryptographic signature.

  • Fields:
    • string FilePath – Full path of the resulting packed file.
    • byte[] Signature – Blake3 hash of the original file (signed or raw depending on use case).
  • Methods:
    • override string ToString() → Returns "FilePath|Signature(Base64)"
    • static PackedFile FromString(string packedFileString) – Parses a string in the above format back into a PackedFile instance.

CompressionLevel (enum)

Controls trade-off between speed and compression ratio when using LZ4.

  • Fast – Prioritizes speed (default LZ4 fast mode)
  • Balanced – Good ratio with reasonable speed
  • Max – Highest compression (uses LZ4 HC)

CompressionProgress (delegate)

public delegate void CompressionProgress(long current, long total, int percentage);

Callback used to report real-time progress during compression/decompression.


Methods

CompressFileAsync

Task<string> CompressFileAsync(
    string fileInput,
    string fileOutput,
    CompressionProgress progress = null,
    CompressionLevel level = CompressionLevel.Fast)

Asynchronously compresses a file using LZ4/LZ4HC. Returns the path to the compressed file (.lz4 extension added if not present).

DecompressFileAsync

Task<string> DecompressFileAsync(
    string fileInput,
    string fileOutput,
    CompressionProgress progress = null,
    CompressionLevel level = CompressionLevel.Fast)

Asynchronously decompresses an LZ4-compressed file. Returns the path to the decompressed output file.

HashFile

public static async Task<byte[]> HashFile(Stream fileData)

Computes the Blake3 hash of a file/stream entirely in memory. Suitable for files that fit in RAM or when streaming through a MemoryStream.

Current Implementation (Working):

public static async Task<byte[]> HashFile(Stream fileData)
{
    return await Task.Run(() =>
    {
        fileData.Seek(0, SeekOrigin.Begin);
        var hasher = Blake3.Hasher.New();           // Using Blake3.Net
        var buffer = new byte[81920];
        int bytesRead;
        while ((bytesRead = fileData.Read(buffer, 0, buffer.Length)) > 0)
            hasher.Update(buffer.AsSpan(0, bytesRead));
        return hasher.Finalize().ToArray();
    });
}

Note: The old MemoryStream copy version has been replaced with proper streaming to support large files without OOM.

VerifyHash

public static async Task<bool> VerifyHash(Stream fileData, byte[] expectedSignature)

Re-computes the Blake3 hash of the stream and compares it against the expected signature.

public static async Task<bool> VerifyHash(Stream fileData, byte[] expectedSignature)
{
    var computed = await HashFile(fileData);
    return computed.SequenceEqual(expectedSignature);
}

PackFiles (Signature + Optional Encryption)

Task<PackedFile> PackFiles(
    string fileInput,
    string outputDirectory,
    byte[] privateKey,                    // For signing hash (Ed25519/Curve25519+X)
    SecureData sessionKey = null,         // Optional AES-256-GCM session key
    CompressionProgress progress = null,
    CompressionLevel level = CompressionLevel.Balanced,
    bool encrypt = true)

Full packing pipeline:

  1. Compress file with LZ4
  2. Compute Blake3 hash of original file
  3. (Optional) Sign hash with privateKey
  4. (Optional) Encrypt compressed data + signature with sessionKey
  5. Write final packed file
  6. Return PackedFile with path and final signature

UnpackFile (Verify + Decrypt + Decompress)

Task<bool> UnpackFile(
    PackedFile packedFile,
    string outputPath,
    byte[] publicKey,                     // To verify signature
    CompressionProgress progress = null,
    CompressionLevel level = CompressionLevel.Balanced,
    SecureData sessionKey = null)

Reverse operation:

  • Decrypt if encrypted
  • Verify Blake3 ± signature using public key
  • Decompress with LZ4
  • Write original file

Returns true on success and integrity verified.