/// <summary>
        /// Checks the hashes and signatures for this PKG.
        /// </summary>
        /// <returns>Returns a list of failed hashes. If the list is empty then the PKG is valid.</returns>
        public List <string> Validate(Stream pkgStream)
        {
            var             errors  = new List <string>();
            Action <string> onError = e => { errors.Add(e); errorHandler?.Invoke(e); };

            // Check general digests
            var generalDigests = pkg_.CalcGeneralDigests();

            foreach (var d in generalDigests)
            {
                if (!d.Value.SequenceEqual(pkg_.GeneralDigests.Digests[d.Key]))
                {
                    onError(d.Key.ToString());
                }
            }

            // Check PFS Signed digest
            var pfsSignedDigest = Crypto.Sha256(pkgStream, (long)pkg_.Header.pfs_image_offset, 0x10000);

            if (!pfsSignedDigest.SequenceEqual(pkg_.Header.pfs_signed_digest))
            {
                onError(nameof(pkg_.Header.pfs_signed_digest));
            }

            // Check PFS Image digest
            var pfsImageDigest = Crypto.Sha256(pkgStream, (long)pkg_.Header.pfs_image_offset, (long)pkg_.Header.pfs_image_size);

            if (!pfsImageDigest.SequenceEqual(pkg_.Header.pfs_image_digest))
            {
                onError(nameof(pkg_.Header.pfs_image_digest));
            }

            return(errors);
        }
Пример #2
0
        /// <summary>
        /// Computes the final digests and writes them to the PKG
        /// </summary>
        /// <param name="pkgStream">PKG file stream</param>
        private void FinishPkg(Stream pkgStream)
        {
            Logger("Calculating SHA256 of finished outer PFS...");
            // Set PFS Image 1st block and full SHA256 hashes (mount image)
            pkg.Header.pfs_signed_digest = Crypto.Sha256(pkgStream, (long)pkg.Header.pfs_image_offset, 0x10000);
            pkg.Header.pfs_image_digest  = Crypto.Sha256(pkgStream, (long)pkg.Header.pfs_image_offset, (long)pkg.Header.pfs_image_size);

            foreach (var a in pkg.CalcGeneralDigests())
            {
                pkg.GeneralDigests.Set(a.Key, a.Value);
            }

            // Write body now because it will make calculating hashes easier.
            var writer = new PkgWriter(pkgStream);

            writer.WriteBody(pkg, project.ContentId, project.Passcode);

            CalcBodyDigests(pkg, pkgStream);

            // Now write header
            pkgStream.Position = 0;
            writer.WriteHeader(pkg.Header);

            // Final Pkg digest and signature
            pkg.HeaderDigest   = Crypto.Sha256(pkgStream, 0, 0xFE0);
            pkgStream.Position = 0xFE0;
            pkgStream.Write(pkg.HeaderDigest, 0, pkg.HeaderDigest.Length);
            byte[] header_sha256 = Crypto.Sha256(pkgStream, 0, 0x1000);
            pkgStream.Position = 0x1000;
            pkgStream.Write(pkg.HeaderSignature = Crypto.RSA2048EncryptKey(Keys.PkgSignKey, header_sha256), 0, 256);
        }