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);
                }
        }
Esempio n. 5
0
        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);
                    }
                }
        }
Esempio n. 6
0
        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));
                }
            }
        }