public static void ResignExecutable(MachObjectFile file, string bundleIdentifier, List <X509Certificate> certificateChain, AsymmetricKeyEntry privateKey, byte[] infoFileBytes, byte[] codeResourcesBytes, EntitlementsFile entitlements)
        {
            X509Certificate signingCertificate = certificateChain[certificateChain.Count - 1];
            string          certificateCN      = CertificateHelper.GetCertificateCommonName(signingCertificate);
            string          teamID             = CertificateHelper.GetCertificateOrganizationalUnit(signingCertificate);

            SegmentCommand linkEditSegment = SegmentCommandHelper.FindLinkEditSegment(file.LoadCommands);

            if (linkEditSegment == null)
            {
                throw new InvalidDataException("LinkEdit segment was not found");
            }

            if (file.LoadCommands[file.LoadCommands.Count - 1].CommandType != LoadCommandType.CodeSignature)
            {
                throw new NotImplementedException("The last LoadCommand entry is not CodeSignature");
            }

            CodeSignatureCommand command = (CodeSignatureCommand)file.LoadCommands[file.LoadCommands.Count - 1];
            int codeLength = (int)command.DataOffset;
            CodeDirectoryBlob codeDirectory         = CreateCodeDirectoryBlob(codeLength, bundleIdentifier, teamID, HashType.SHA1);
            AttributeTable    signedAttributesTable = null;

#if ALT_CODE_DIRECTORY_SHA256
            CodeDirectoryBlob alternativeCodeDirectory1 = CreateCodeDirectoryBlob(codeLength, bundleIdentifier, teamID, HashType.SHA256);
            signedAttributesTable = GenerateSignedAttributesTable(codeDirectory.GetBytes(), alternativeCodeDirectory1.GetBytes());
#endif
            CodeRequirementsBlob codeRequirements = CreateCodeRequirementsBlob(bundleIdentifier, certificateCN);
            EntitlementsBlob     entitlementsBlob = CreateEntitlementsBlob(entitlements);
            CmsSignatureBlob     cmsSignature     = new CmsSignatureBlob();
            // We create a dummy signature to determine the length required
            cmsSignature.Data = CMSHelper.GenerateSignature(certificateChain, privateKey, codeDirectory.GetBytes(), signedAttributesTable);

            CodeSignatureSuperBlob codeSignature = new CodeSignatureSuperBlob();
            codeSignature.Entries.Add(CodeSignatureEntryType.CodeDirectory, codeDirectory);
            codeSignature.Entries.Add(CodeSignatureEntryType.Requirements, codeRequirements);
            codeSignature.Entries.Add(CodeSignatureEntryType.Entitlements, entitlementsBlob);
#if ALT_CODE_DIRECTORY_SHA256
            codeSignature.Entries.Add(CodeSignatureEntryType.AlternateCodeDirectory1, alternativeCodeDirectory1);
#endif
            codeSignature.Entries.Add(CodeSignatureEntryType.CmsSignature, cmsSignature);

            command.DataSize = (uint)codeSignature.Length;
            uint finalFileSize = command.DataOffset + command.DataSize;
            SegmentCommandHelper.SetEndOffset(linkEditSegment, finalFileSize);

            byte[] codeToHash = ByteReader.ReadBytes(file.GetBytes(), 0, codeLength);
            UpdateSpecialHashes(codeDirectory, codeToHash, infoFileBytes, codeRequirements, codeResourcesBytes, entitlementsBlob);
#if ALT_CODE_DIRECTORY_SHA256
            UpdateSpecialHashes(alternativeCodeDirectory1, codeToHash, infoFileBytes, codeRequirements, codeResourcesBytes, entitlementsBlob);
            signedAttributesTable = GenerateSignedAttributesTable(codeDirectory.GetBytes(), alternativeCodeDirectory1.GetBytes());
#endif
            cmsSignature.Data = CMSHelper.GenerateSignature(certificateChain, privateKey, codeDirectory.GetBytes(), signedAttributesTable);

            // Store updated code signature:
            byte[] codeSignatureBytes = codeSignature.GetBytes();
            Array.Resize <byte>(ref file.Data, (codeLength - file.DataOffset) + (int)command.DataSize);
            ByteWriter.WriteBytes(file.Data, (int)command.DataOffset - file.DataOffset, codeSignatureBytes);
        }
        public static bool ValidateSpecialHashes(MachObjectFile file, byte[] infoFileBytes, byte[] codeResourcesBytes)
        {
            byte[] codeSignatureBytes = file.GetCodeSignatureBytes();
            if (CodeSignatureSuperBlob.IsCodeSignatureSuperBlob(codeSignatureBytes, 0))
            {
                CodeSignatureSuperBlob codeSignature = new CodeSignatureSuperBlob(codeSignatureBytes, 0);
                CodeDirectoryBlob      codeDirectory = codeSignature.GetEntry(CodeSignatureEntryType.CodeDirectory) as CodeDirectoryBlob;

                byte[] infoFileHash = HashAlgorithmHelper.ComputeHash(codeDirectory.HashType, infoFileBytes);
                if (!ByteUtils.AreByteArraysEqual(infoFileHash, codeDirectory.SpecialHashes[codeDirectory.SpecialHashes.Count - CodeDirectoryBlob.InfoFileHashOffset]))
                {
                    return(false);
                }

                byte[] codeResourcesHash = HashAlgorithmHelper.ComputeHash(codeDirectory.HashType, codeResourcesBytes);
                if (!ByteUtils.AreByteArraysEqual(codeResourcesHash, codeDirectory.SpecialHashes[codeDirectory.SpecialHashes.Count - CodeDirectoryBlob.CodeResourcesFileHashOffset]))
                {
                    return(false);
                }

                CodeRequirementsBlob codeRequirements = codeSignature.GetEntry(CodeSignatureEntryType.Requirements) as CodeRequirementsBlob;
                byte[] codeRequirementsBytes          = codeRequirements.GetBytes();
                byte[] codeRequirementsHash           = HashAlgorithmHelper.ComputeHash(codeDirectory.HashType, codeRequirementsBytes);
                if (!ByteUtils.AreByteArraysEqual(codeRequirementsHash, codeDirectory.SpecialHashes[codeDirectory.SpecialHashes.Count - CodeDirectoryBlob.RequirementsHashOffset]))
                {
                    return(false);
                }

                if (codeDirectory.SpecialHashes.Count >= CodeDirectoryBlob.EntitlementsHashOffset)
                {
                    CodeSignatureGenericBlob entitlements = codeSignature.GetEntry(CodeSignatureEntryType.Entitlements) as CodeSignatureGenericBlob;
                    byte[] entitlementsBytes = entitlements.GetBytes();
                    byte[] entitlementsHash  = HashAlgorithmHelper.ComputeHash(codeDirectory.HashType, entitlementsBytes);
                    if (!ByteUtils.AreByteArraysEqual(entitlementsHash, codeDirectory.SpecialHashes[codeDirectory.SpecialHashes.Count - CodeDirectoryBlob.EntitlementsHashOffset]))
                    {
                        return(false);
                    }
                }
                return(true);
            }
            return(false);
        }
        public static CodeRequirementsBlob CreateCodeRequirementsBlob(string ident, string certificateCN)
        {
            CodeRequirementsBlob codeRequirements = new CodeRequirementsBlob();
            CodeRequirementBlob  codeRequirement  = new CodeRequirementBlob();

            codeRequirements.Entries.Add(SecurityRequirementType.DesignatedRequirementType, codeRequirement);

            IdentValue         identValue         = new IdentValue(ident);
            AppleGenericAnchor appleGenericAnchor = new AppleGenericAnchor();
            CertificateField   certificateField   = new CertificateField();

            certificateField.CertificateIndex = 0;
            certificateField.FieldName        = "subject.CN";
            certificateField.Match            = new MatchSuffix(MatchOperationName.Equal, certificateCN);
            CertificateGeneric certificateGeneric = new CertificateGeneric();

            certificateGeneric.CertificateIndex = 1;
            certificateGeneric.OID   = APPLE_IOS_OID;
            certificateGeneric.Match = new MatchSuffix(MatchOperationName.Exists);

            codeRequirement.Expression = new AndExpression(identValue, new AndExpression(appleGenericAnchor, new AndExpression(certificateField, certificateGeneric)));

            return(codeRequirements);
        }
        public static void UpdateSpecialHashes(CodeDirectoryBlob codeDirectory, byte[] codeToHash, byte[] infoFileBytes, CodeRequirementsBlob codeRequirements, byte[] codeResourcesBytes, EntitlementsBlob entitlements)
        {
            codeDirectory.CodeHashes = HashAlgorithmHelper.ComputeHashes(codeDirectory.HashType, codeDirectory.PageSize, codeToHash);

            codeDirectory.SpecialHashes = new List <byte[]>();
            codeDirectory.SpecialHashes.Insert(0, (HashAlgorithmHelper.ComputeHash(codeDirectory.HashType, infoFileBytes)));
            codeDirectory.SpecialHashes.Insert(0, (HashAlgorithmHelper.ComputeHash(codeDirectory.HashType, codeRequirements.GetBytes())));
            codeDirectory.SpecialHashes.Insert(0, (HashAlgorithmHelper.ComputeHash(codeDirectory.HashType, codeResourcesBytes)));
            if (SpecialHashCount >= CodeDirectoryBlob.ApplicationSpecificHashOffset)
            {
                codeDirectory.SpecialHashes.Insert(0, new byte[HashAlgorithmHelper.GetHashLength(codeDirectory.HashType)]);
                if (SpecialHashCount >= CodeDirectoryBlob.EntitlementsHashOffset)
                {
                    codeDirectory.SpecialHashes.Insert(0, (HashAlgorithmHelper.ComputeHash(codeDirectory.HashType, entitlements.GetBytes())));
                }
            }
        }