private bool VerifySignatureDsa()
        {
            byte[] signatureBlockBytes = JarUtils.ReadBytes(ArchivePath, SignatureBlockFilePath);
            byte[] signatureFileBytes  = JarUtils.ReadBytes(ArchivePath, SignatureFilePath);

            SHA1Managed sha = new SHA1Managed(); // lgtm [cs/weak-crypto] Hash algorithm specified by signature algorithm

            byte[] hash = sha.ComputeHash(signatureFileBytes);

            ContentInfo ci  = new ContentInfo(signatureFileBytes);
            SignedCms   cms = new SignedCms(ci, detached: true);

            cms.Decode(signatureBlockBytes);

            try
            {
                cms.CheckSignature(verifySignatureOnly: true);
            }
            catch (CryptographicException ce)
            {
                JarError.AddError(ce.Message);
                return(false);
            }

            // If there were no exceptions logged then signature verification should be good.
            return(true);
        }
        /// <summary>
        /// Verifies each individual entry's x-Digest against the computed digest of the individual section of the entry in
        /// the manifest.
        /// </summary>
        /// <param name="manifestFile">The manifest file to use when computing individual digests.</param>
        /// <returns>true if verifications was successful, false otherwise.</returns>
        public bool VerifySignatureSourceFileDigests(JarManifestFile manifestFile)
        {
            foreach (JarIndividualEntry signatureFileEntry in IndividualSection)
            {
                JarIndividualEntry manifestFileEntry = manifestFile.IndividualSection.FirstOrDefault(
                    i => String.Equals(i.Name, signatureFileEntry.Name));

                if (manifestFileEntry != null)
                {
                    string computedDigest = JarUtils.GetHashDigest(manifestFileEntry.RawText, signatureFileEntry.HashAlgorithmName);
                    if (!String.Equals(computedDigest, signatureFileEntry.DigestValue))
                    {
                        JarError.AddError(String.Format(JarResources.SignatureFileEntryDigestMismatch, signatureFileEntry.Name, SignatureFilePath, computedDigest, signatureFileEntry.DigestValue));
                        return(false);
                    }
                }
                else
                {
                    // Signature file contains an entry that's not present in the MANIFEST.MF file
                    JarError.AddError(String.Format(JarResources.MissingManifestEntry, signatureFileEntry.Name, SignatureFilePath));
                    return(false);
                }
            }

            // If we make it out of the loop we're all good
            return(true);
        }
        public JarIndividualEntry(string entryText)
        {
            Attributes = JarAttributes.From(entryText);

            // Set up some properties to simplify tasks
            string name = null;

            if (Attributes.TryGetValue("Name", out name))
            {
                Name = name;
            }

            RawText = entryText;

            // Only look for xxx-DIGEST for now.
            // There are also xxx-DIGEST-yyy attributes for language specific files we need to deal with later
            string digestAttributeKey = Attributes.Keys.FirstOrDefault(key => key.EndsWith("-Digest", StringComparison.OrdinalIgnoreCase));

            if (!String.IsNullOrEmpty(digestAttributeKey))
            {
                string manifestDigest = Attributes[digestAttributeKey];
                HashAlgorithmName = JarUtils.GetHashAlgorithmFromDigest(digestAttributeKey, "-Digest");
                DigestValue       = Attributes[digestAttributeKey];
            }
        }
 /// <summary>
 /// Verify the x-Digest-Manifest-Main-Attributes attribute if it exists, otherwise, verify the individual file attributes
 /// in the signature file and compare their digests to the digests calculated over the individual sections in the manifest
 /// file.
 /// </summary>
 /// <returns>True if the verification succeeded, false otherwise.</returns>
 public bool VerifyDigestManifestMain(JarManifestFile manifestFile)
 {
     if (HasDigestManifestMainAttributes)
     {
         string digestAttributeKey = MainAttributes.Keys.FirstOrDefault(key => key.EndsWith("-Digest-Manifest-Main-Attributes", StringComparison.OrdinalIgnoreCase));
         JarUtils.GetHashAlgorithmFromDigest(digestAttributeKey, "-Digest-Manifest-Main-Attributes");
         return(String.Equals(MainAttributes[digestAttributeKey],
                              manifestFile.GetMainAttributesDigest(JarUtils.GetHashAlgorithmFromDigest(digestAttributeKey, "-Digest-Manifest-Main-Attributes"))));
     }
     else
     {
         return(VerifySignatureSourceFileDigests(manifestFile));
     }
 }
Exemple #5
0
        /// <summary>
        /// Creates an instance of JarAttributes using the raw section from a manifest file.
        /// </summary>
        /// <param name="rawText">A string containing the raw section (main, individual) text.</param>
        /// <returns></returns>
        public static JarAttributes From(string rawText)
        {
            var jarAttributes = new JarAttributes(rawText);

            if (String.IsNullOrEmpty(rawText))
            {
                return(jarAttributes);
            }

            // We need to deal with continuations (multi-line attributes), so convert the raw text to a stream
            // and then parse it.
            using (Stream s = JarUtils.ToStream(rawText))
                using (StreamReader reader = new StreamReader(s))
                {
                    string line = reader.ReadLine();

                    while (!reader.EndOfStream)
                    {
                        if (line.Contains(':'))
                        {
                            string[] attributeParts = line.Split(':');

                            string attributeName  = attributeParts[0];
                            string attributeValue = attributeParts[1].TrimStart(' ');

                            line = reader.ReadLine();

                            // Continuation values start with SPACE
                            while (line.StartsWith(" "))
                            {
                                line            = line.TrimStart(' ').TrimEnd(JarUtils.NewLine);
                                attributeValue += line;
                            }

                            jarAttributes[attributeName] = attributeValue;
                        }
                        else
                        {
                            line = reader.ReadLine();
                        }
                    }
                }

            return(jarAttributes);
        }
        /// <summary>
        /// Verify the signature file, e.g. x.SF using the corresponding signature block, e.g. x.RSA
        /// </summary>
        /// <returns>True if the verification is successful, false otherwise.</returns>
        private bool VerifySignatureRsa()
        {
            Timestamps.Clear();
            byte[] signatureBlockBytes = JarUtils.ReadBytes(ArchivePath, SignatureBlockFilePath);
            byte[] signatureFileBytes  = JarUtils.ReadBytes(ArchivePath, SignatureFilePath);

            SHA256Managed sha = new SHA256Managed();

            byte[] hash = sha.ComputeHash(signatureFileBytes);

            ContentInfo ci  = new ContentInfo(signatureFileBytes);
            SignedCms   cms = new SignedCms(ci, detached: true);

            cms.Decode(signatureBlockBytes);

            try
            {
                cms.CheckSignature(verifySignatureOnly: true);

                // See if we can retrieve a timestamp
                foreach (SignerInfo signerInfo in cms.SignerInfos)
                {
                    foreach (CryptographicAttributeObject unsignedAttribute in signerInfo.UnsignedAttributes)
                    {
                        if (String.Equals(unsignedAttribute.Oid.Value, WinCrypt.szOID_SIGNATURE_TIMESTAMP_ATTRIBUTE, StringComparison.OrdinalIgnoreCase))
                        {
                            Pkcs9AttributeObject timestampAttribute = new Pkcs9AttributeObject(unsignedAttribute.Values[0]);
                            SignedCms            timestampCms       = new SignedCms();
                            timestampCms.Decode(timestampAttribute.RawData);
                            TstInfo timestampToken = TstInfo.Read(timestampCms.ContentInfo.Content);

                            foreach (SignerInfo timestampSigner in timestampCms.SignerInfos)
                            {
                                foreach (CryptographicAttributeObject sa in timestampSigner.SignedAttributes)
                                {
                                    if (String.Equals(sa.Oid.Value, WinCrypt.szOID_RSA_signingTime, StringComparison.OrdinalIgnoreCase))
                                    {
                                        var signingTime = (Pkcs9SigningTime)sa.Values[0];
                                        X509Certificate2 timestampSignerCert = timestampSigner.Certificate;

                                        Timestamps.Add(new Timestamp
                                        {
                                            SignedOn           = signingTime.SigningTime.ToLocalTime(),
                                            EffectiveDate      = Convert.ToDateTime(timestampSignerCert.GetEffectiveDateString()).ToLocalTime(),
                                            ExpiryDate         = Convert.ToDateTime(timestampSignerCert.GetExpirationDateString()).ToLocalTime(),
                                            SignatureAlgorithm = timestampSignerCert.SignatureAlgorithm.FriendlyName
                                        });
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (CryptographicException ce)
            {
                JarError.AddError(ce.Message);
                return(false);
            }

            // If there were no exceptions logged then signature verification should be good.
            return(true);
        }
        /// <summary>
        /// Verify all the x-Digest-Manifest attributes.
        /// </summary>
        /// <param name="manifest">The JAR manifest (META-INF/MANIFEST.MF)</param>
        /// <returns>True if all the digests were verified, false if any verification failed or there are no x-Digest-Manifest attributes in the signature file.</returns>
        public bool VerifyDigestManifest(JarManifestFile manifest)
        {
            if (ManifestHashDigestAttributes.Count() > 0)
            {
                return(ManifestHashDigestAttributes.All(
                           a => String.Equals(MainAttributes[a], manifest.GetManifestDigest(JarUtils.GetHashAlgorithmFromDigest(a, "-Digest-Manifest")))
                           ));
            }

            return(false);
        }