Esempio n. 1
0
        /// <summary>
        /// Load all manifest entries from a given manifest in a JAR
        /// </summary>
        /// <param name="source">source JAR</param>
        /// <param name="manifest">manifest to load</param>
        /// <returns>manifest data</returns>
        public ManifestData Load(IJar source, string path)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (path.IsNullOrEmpty())
            {
                throw new ArgumentNullException(nameof(path));
            }

            // If this file does not exist, obviously we cannot load it
            if (!source.Contains(path))
            {
                throw new ManifestException($"Manifest {path} does not exist");
            }

            ManifestData manifest = new ManifestData
            {
                ManifestDigest = String.Empty,
                Entries        = new List <ManifestEntry>()
            };

            // The manifest digest is supposed to refer to the digest that THIS manifest
            // expects the main manifest to have. Until set otherwise, assume this digest
            // is = to our own hash (which means loading the main manifest populates this
            // value with the main manifest hash for future comparison)
            using (Hasher h = new Hasher())
            {
                manifest.ManifestDigest = source.SHA256(h, path).ToBase64();
            }

            try
            {
                using (StreamReader reader = new StreamReader(source.Open(path)))
                {
                    string[] lines = Unwrap70(reader.ReadToEnd().Split(
                                                  new char[]
                    {
                        (char)10,
                        (char)13
                    },
                                                  StringSplitOptions.RemoveEmptyEntries));

                    Populate(manifest, lines);
                }
            }
            catch (Exception ex)
            {
                throw new ManifestException($"Failed to open or parse manifest {path}", ex);
            }

            return(manifest);
        }
Esempio n. 2
0
        /// <summary>
        /// Produce a SHA256 of a file in the JAR. If the file does not exist, an exception is thrown.
        /// </summary>
        /// <param name="this"></param>
        /// <param name="hasher">hasher implementation</param>
        /// <param name="path">filename to generate a hash of</param>
        /// <returns>the byte data of the SHA-256 hash</returns>
        public static byte[] SHA256(this IJar @this, Hasher hasher, string path)
        {
            if (hasher == null)
            {
                throw new ArgumentNullException(nameof(hasher));
            }

            if (path.IsNullOrEmpty())
            {
                throw new ArgumentNullException(nameof(path));
            }

            if ([email protected](path))
            {
                throw new JarException($"File to hash {path} does not exist in JAR");
            }

            using (Stream file = @this.Open(path))
            {
                return(hasher.SHA256(file));
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Verify a PKCS7 signature block
        /// </summary>
        /// <param name="jar">JAR from which to read and verify the signature</param>
        /// <param name="sig">the signature being verified</param>
        /// <param name="certificate">the raw certificate bytes against which to verify (i.e. public key)</param>
        /// <returns>whether the PKCS signature is valid</returns>
        private bool VerifyPKCS7(IJar jar, Signature sig, byte[] certificate)
        {
            try
            {
                // Detached content to verify - in this case, the .SF file
                // (against which the signature block validates its hash)
                CmsProcessableByteArray detachedContent;

                // We cannot easily reuse a reader against the SF file
                // So instead, copy to memory in entirety and build from byte array
                using (Stream sigFile = jar.Open(sig.ManifestPath))
                    using (MemoryStream sigFileMemory = new MemoryStream())
                    {
                        sigFile.CopyTo(sigFileMemory);

                        detachedContent = new CmsProcessableByteArray(sigFileMemory.ToArray());
                    }

                // Open the signature block (e.g. .RSA or .DSA)
                using (Stream block = jar.Open(sig.Block.Path))
                {
                    X509CertificateParser certParser = new X509CertificateParser();

                    // Read the caller's certificate (assumed to have a matching public key)
                    X509Certificate cert = certParser.ReadCertificate(certificate);

                    CmsSignedData signedData = new CmsSignedData(detachedContent, block);

                    SignerInformationStore signers = signedData.GetSignerInfos();

                    int verified = 0;

                    foreach (SignerInformation signer in signers.GetSigners())
                    {
                        Log.Message($"Verifying against {cert.SubjectDN.ToString()}");

                        if (signer.Verify(cert))
                        {
                            verified++;

                            Log.Message($"Signature valid for {cert.SubjectDN.ToString()}");
                        }
                        else
                        {
                            Log.Message($"Signature INVALID for {cert.SubjectDN.ToString()}");
                        }
                    }

                    // Every signer must verify OK
                    return(verified == signers.GetSigners().Count);
                }
            }
            catch (Exception ex)
            {
                // Cert verification can trigger a number of different possible errors
                // (Ranging from cert bytes invalid -> key type mismatch)

                Log.Error(ex, "Failed to verify certifiate: assuming invalid");

                return(false);
            }
        }