/// <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); }
/// <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); }