Skip to content

SimonCropp/DeterministicIoPackaging

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

191 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DeterministicIoPackaging

Build status NuGet Status

Modify System.IO.Packaging files to ensure they are deterministic. Helpful for testing, build reproducibility, security verification, and ensuring package integrity across different build environments.

Example file formats that leverage System.IO.Packaging

  • .nupkg
  • Microsoft Office files

See Milestones for release notes.

NuGet

How it works

  • For an input package stream
  • Duplicate each entry with Deflate compression and consistent order
  • Omit package/services/metadata/core-properties/*.psmdcp entries
  • Omit .signature.p7s entries (NuGet package signatures are invalidated by the conversion since package contents are modified)
  • For all relationship entries (.rels files)
    • Modify the Id of each Relationship to be deterministic
    • Convert absolute Target paths to relative (e.g. Target="/xl/workbook.xml" becomes Target="xl/workbook.xml")
    • Order Relationships by Type
  • For the relationships entry _rels/.rels
    • Remove the Relationship for the .psmdcp entry
  • For the relationships entry docProps/core.xml
    • Remove the creator, created, lastModifiedBy, and modified elements

Spreadsheet namespace validation

The conversion throws if any spreadsheetml XML entry (e.g. xl/workbook.xml, xl/worksheets/sheet1.xml) uses a prefixed default namespace such as <x:worksheet xmlns:x="..."> instead of the unprefixed form <worksheet xmlns="...">. This is because tools like Microsoft Spreadsheet Compare cannot open files with prefixed spreadsheetml elements. The OpenXml SDK can produce this form — ensure source xlsx files use default namespace declarations.

Binary output across .NET frameworks

Binary output may differ between .NET Framework (net48) and .NET (net10.0+) due to differences in Deflate compression implementations. The XML content within entries is identical — only the compressed bytes differ.

This applies to all package formats (xlsx, docx, nupkg, etc.). When snapshot-testing binary package output across multiple target frameworks using Verify, use UniqueForRuntime to generate framework-specific verified files:

await Verify(stream, extension: "xlsx")
    .UniqueForRuntime();

See Verify Naming docs for more details.

Usage

Convert

using var sourceStream = File.OpenRead(packagePath);
await DeterministicPackage.ConvertAsync(sourceStream, targetStream);

snippet source | anchor

ConvertAsync

using var sourceStream = File.OpenRead(packagePath);
await DeterministicPackage.ConvertAsync(sourceStream, targetStream);

snippet source | anchor

Icon

Pi designed by Zaidan from The Noun Project.

About

Modify System.IO.Packaging files to ensure they are deterministic. Helpful for testing, build reproducibility, security verification, and ensuring package integrity across different build environments.

Resources

License

Code of conduct

Stars

Watchers

Forks

Sponsor this project

 

Contributors

Languages