public void ReadSignedArchiveMetadata_WhenReaderNull_Throws() { var exception = Assert.Throws <ArgumentNullException>( () => SignedPackageArchiveIOUtility.ReadSignedArchiveMetadata(reader: null)); Assert.Equal("reader", exception.ParamName); }
public void ReadSignedArchiveMetadata_WithUnsignedPackage_Throws() { using (var stream = new MemoryStream(GetNonEmptyZip())) using (var reader = new BinaryReader(stream)) { var exception = Assert.Throws <SignatureException>( () => SignedPackageArchiveIOUtility.ReadSignedArchiveMetadata(reader)); Assert.Equal(NuGetLogCode.NU3005, exception.Code); Assert.Equal("The package does not contain a valid package signature file.", exception.Message); } }
private static Task ShiftSignatureMetadata(SigningSpecifications spec, BinaryReader reader, BinaryWriter writer, int centralDirectoryIndex, int fileHeaderIndex) { // Read metadata var metadata = SignedPackageArchiveIOUtility.ReadSignedArchiveMetadata(reader); // Update central directory records by excluding the signature entry SignedPackageArchiveIOUtility.UpdateSignedPackageArchiveMetadata(reader, metadata); // Calculate new central directory record metadata with the the signature record and entry shifted var shiftedCdr = ShiftMetadata(spec, metadata, newSignatureFileEntryIndex: fileHeaderIndex, newSignatureCentralDirectoryRecordIndex: centralDirectoryIndex); // Order records by shifted ofset (new offset = old offset + change in offset). // This is the order they will appear in the new shifted package, but not necesarily the same order they were in the old package shiftedCdr.Sort((x, y) => (x.OffsetToFileHeader + x.ChangeInOffset).CompareTo(y.OffsetToFileHeader + y.ChangeInOffset)); // Write data from start of file to first file entry reader.BaseStream.Seek(offset: 0, origin: SeekOrigin.Begin); SignedPackageArchiveIOUtility.ReadAndWriteUntilPosition(reader, writer, metadata.StartOfFileHeaders); // Write all file entries in the new order foreach (var entry in shiftedCdr) { // We need to read each entry from their position in the old package and write them sequencially to the new package // The order in which they will appear in the new shited package is defined by the sorting done before starting to write reader.BaseStream.Seek(offset: entry.OffsetToFileHeader, origin: SeekOrigin.Begin); SignedPackageArchiveIOUtility.ReadAndWriteUntilPosition(reader, writer, entry.OffsetToFileHeader + entry.FileEntryTotalSize); } // Write all central directory records with updated offsets // We first need to sort them in the order they will appear in the new shifted package shiftedCdr.Sort((x, y) => x.IndexInHeaders.CompareTo(y.IndexInHeaders)); foreach (var entry in shiftedCdr) { reader.BaseStream.Seek(offset: entry.Position, origin: SeekOrigin.Begin); // Read and write from the start of the central directory record until the relative offset of local file header (42 from the start of central directory record, incluing signature length) SignedPackageArchiveIOUtility.ReadAndWriteUntilPosition(reader, writer, reader.BaseStream.Position + 42); var relativeOffsetOfLocalFileHeader = (uint)(reader.ReadUInt32() + entry.ChangeInOffset); writer.Write(relativeOffsetOfLocalFileHeader); // We already read and hash the whole header, skip only filenameLength + extraFieldLength + fileCommentLength (46 is the size of the header without those lengths) SignedPackageArchiveIOUtility.ReadAndWriteUntilPosition(reader, writer, reader.BaseStream.Position + entry.HeaderSize - CentralDirectoryFileHeaderSizeWithoutSignature); } // Write everything after central directory records reader.BaseStream.Seek(offset: metadata.EndOfCentralDirectory, origin: SeekOrigin.Begin); SignedPackageArchiveIOUtility.ReadAndWriteUntilPosition(reader, writer, reader.BaseStream.Length); return(Task.FromResult(0)); }
public void ReadSignedArchiveMetadata_WithOnlyPackageSignatureEntry_ReturnsMetadata() { using (var stream = new MemoryStream(GetResource("SignatureFileEntry.zip"))) using (var reader = new BinaryReader(stream)) { var metadata = SignedPackageArchiveIOUtility.ReadSignedArchiveMetadata(reader); Assert.Equal(1, metadata.CentralDirectoryHeaders.Count); Assert.Equal(0, metadata.SignatureCentralDirectoryHeaderIndex); var header = metadata.CentralDirectoryHeaders[0]; Assert.True(header.IsPackageSignatureFile); } }
public void ReadSignedArchiveMetadata_WithSignedPackage_ReturnsMetadata() { using (var stream = new MemoryStream(GetResource("SignedPackage.1.0.0.nupkg"))) using (var reader = new BinaryReader(stream)) { var metadata = SignedPackageArchiveIOUtility.ReadSignedArchiveMetadata(reader); Assert.Equal(0, metadata.StartOfLocalFileHeaders); Assert.Equal(0xbcc, metadata.EndOfLocalFileHeaders); Assert.Equal(6, metadata.CentralDirectoryHeaders.Count); Assert.Equal(0xd7c, metadata.EndOfCentralDirectory); Assert.Equal(5, metadata.SignatureCentralDirectoryHeaderIndex); var expectedHeaders = new[] { new { ChangeInOffset = 0L, FileEntryTotalSize = 0x136, HeaderSize = 0x39, IndexInHeaders = 0, IsPackageSignatureFile = false, OffsetToFileHeader = 0, Position = 0xbcc }, new { ChangeInOffset = 0L, FileEntryTotalSize = 0x110, HeaderSize = 0x42, IndexInHeaders = 1, IsPackageSignatureFile = false, OffsetToFileHeader = 0x136, Position = 0xc05 }, new { ChangeInOffset = 0L, FileEntryTotalSize = 0x29, HeaderSize = 0x39, IndexInHeaders = 2, IsPackageSignatureFile = false, OffsetToFileHeader = 0x246, Position = 0xc47 }, new { ChangeInOffset = 0L, FileEntryTotalSize = 0xff, HeaderSize = 0x41, IndexInHeaders = 3, IsPackageSignatureFile = false, OffsetToFileHeader = 0x26f, Position = 0xc80 }, new { ChangeInOffset = 0L, FileEntryTotalSize = 0x1dd, HeaderSize = 0x7f, IndexInHeaders = 4, IsPackageSignatureFile = false, OffsetToFileHeader = 0x36e, Position = 0xcc1 }, new { ChangeInOffset = 0L, FileEntryTotalSize = 0x681, HeaderSize = 0x3c, IndexInHeaders = 5, IsPackageSignatureFile = true, OffsetToFileHeader = 0x54b, Position = 0xd40 }, }; Assert.Equal(expectedHeaders.Length, metadata.CentralDirectoryHeaders.Count); for (var i = 0; i < expectedHeaders.Length; ++i) { var expectedHeader = expectedHeaders[i]; var actualHeader = metadata.CentralDirectoryHeaders[i]; Assert.Equal(expectedHeader.Position, actualHeader.Position); Assert.Equal(expectedHeader.OffsetToFileHeader, actualHeader.OffsetToLocalFileHeader); Assert.Equal(expectedHeader.FileEntryTotalSize, actualHeader.FileEntryTotalSize); Assert.Equal(expectedHeader.IsPackageSignatureFile, actualHeader.IsPackageSignatureFile); Assert.Equal(expectedHeader.HeaderSize, actualHeader.HeaderSize); Assert.Equal(expectedHeader.ChangeInOffset, actualHeader.ChangeInOffset); Assert.Equal(expectedHeader.IndexInHeaders, actualHeader.IndexInHeaders); } } }
public void ReadSignedArchiveMetadata_WithNonEmptyZip_ReturnsMetadata() { using (var stream = new MemoryStream(GetResource("3Entries.zip"))) using (var reader = new BinaryReader(stream)) { var metadata = SignedPackageArchiveIOUtility.ReadSignedArchiveMetadata(reader); Assert.Equal(0, metadata.StartOfFileHeaders); Assert.Equal(0x84, metadata.EndOfFileHeaders); Assert.Equal(3, metadata.CentralDirectoryHeaders.Count); Assert.Equal(0x11d, metadata.EndOfCentralDirectory); Assert.Equal(0x11d, metadata.EndOfCentralDirectoryRecordPosition); Assert.Equal(0, metadata.SignatureCentralDirectoryHeaderIndex); var header = metadata.CentralDirectoryHeaders[0]; Assert.Equal(0x84, header.Position); Assert.Equal(0, header.OffsetToFileHeader); Assert.Equal(0x2a, header.FileEntryTotalSize); Assert.Equal("1.txt", header.Filename); Assert.Equal(0x33, header.HeaderSize); Assert.Equal(0, header.ChangeInOffset); Assert.Equal(0, header.IndexInHeaders); header = metadata.CentralDirectoryHeaders[1]; Assert.Equal(0xb7, header.Position); Assert.Equal(0x2a, header.OffsetToFileHeader); Assert.Equal(0x2f, header.FileEntryTotalSize); Assert.Equal("2.txt", header.Filename); Assert.Equal(0x33, header.HeaderSize); Assert.Equal(0, header.ChangeInOffset); Assert.Equal(1, header.IndexInHeaders); header = metadata.CentralDirectoryHeaders[2]; Assert.Equal(0xea, header.Position); Assert.Equal(0x59, header.OffsetToFileHeader); Assert.Equal(0x2b, header.FileEntryTotalSize); Assert.Equal("3.txt", header.Filename); Assert.Equal(0x33, header.HeaderSize); Assert.Equal(0, header.ChangeInOffset); Assert.Equal(2, header.IndexInHeaders); } }
public void ReadSignedArchiveMetadata_WithEmptyZip_Throws() { using (var stream = new MemoryStream()) { using (var zip = new ZipArchive(stream, ZipArchiveMode.Create, leaveOpen: true)) { } stream.Seek(offset: 0, loc: SeekOrigin.Begin); using (var reader = new BinaryReader(stream)) { Assert.Throws <InvalidDataException>( () => SignedPackageArchiveIOUtility.ReadSignedArchiveMetadata(reader)); } } }