Пример #1
0
        public static bool VerifyUnpackedFolder(string folder, UpdateInfo version = null)
        {
            try
            {
                UpdateInfo update;
                FileEntry manifest;

                var sha256 = System.Security.Cryptography.SHA256.Create();
                var md5 = System.Security.Cryptography.MD5.Create();

                using(var fs = System.IO.File.OpenRead(System.IO.Path.Combine(folder, UPDATE_MANIFEST_FILENAME)))
                {
                    using(var ss = new SignatureReadingStream(fs, SIGN_KEY))
                    using(var tr = new System.IO.StreamReader(ss))
                    using(var jr = new Newtonsoft.Json.JsonTextReader(tr))
                        update = new Newtonsoft.Json.JsonSerializer().Deserialize<UpdateInfo>(jr);

                    sha256.Initialize();
                    md5.Initialize();

                    fs.Position = 0;
                    var h1 = Convert.ToBase64String(sha256.ComputeHash(fs));
                    fs.Position = 0;
                    var h2 = Convert.ToBase64String(md5.ComputeHash(fs));

                    manifest = new FileEntry() {
                        Path = UPDATE_MANIFEST_FILENAME,
                        Ignore = false,
                        LastWriteTime = update.ReleaseTime,
                        SHA256 = h1,
                        MD5 = h2
                    };
                }

                if (version != null && (update.Displayname != version.Displayname || update.ReleaseTime != version.ReleaseTime))
                    throw new Exception("The found version was not the expected version");

                var paths = update.Files.Where(x => !x.Ignore).ToDictionary(x => x.Path.Replace('/', System.IO.Path.DirectorySeparatorChar), Library.Utility.Utility.ClientFilenameStringComparer);
                paths.Add(manifest.Path, manifest);

                var ignores = (from x in update.Files where x.Ignore select Library.Utility.Utility.AppendDirSeparator(x.Path.Replace('/', System.IO.Path.DirectorySeparatorChar))).ToList();

                folder = Library.Utility.Utility.AppendDirSeparator(folder);
                var baselen = folder.Length;

                foreach(var file in Library.Utility.Utility.EnumerateFileSystemEntries(folder))
                {
                    var relpath = file.Substring(baselen);
                    if (string.IsNullOrWhiteSpace(relpath))
                        continue;

                    FileEntry fe;
                    if (!paths.TryGetValue(relpath, out fe))
                    {
                        var ignore = false;
                        foreach(var c in ignores)
                            if (ignore = relpath.StartsWith(c))
                                break;

                        if (ignore)
                            continue;

                        throw new Exception(string.Format("Found unexpected file: {0}", file));
                    }

                    paths.Remove(relpath);

                    if (fe.Path.EndsWith("/"))
                        continue;

                    sha256.Initialize();
                    md5.Initialize();

                    using(var fs = System.IO.File.OpenRead(file))
                    {
                        if (Convert.ToBase64String(sha256.ComputeHash(fs)) != fe.SHA256)
                            throw new Exception(string.Format("Invalid sha256 hash for file: {0}", file));

                        fs.Position = 0;
                        if (Convert.ToBase64String(md5.ComputeHash(fs)) != fe.MD5)
                            throw new Exception(string.Format("Invalid md5 hash for file: {0}", file));
                    }
                }

                var filteredpaths = (from p in paths
                        where !string.IsNullOrWhiteSpace(p.Key) && !p.Key.EndsWith("/")
                        select p.Key).ToList();

                if (filteredpaths.Count == 1)
                    throw new Exception(string.Format("Folder {0} is missing: {1}", folder, filteredpaths.First()));
                else if (filteredpaths.Count > 0)
                    throw new Exception(string.Format("Folder {0} is missing {1} and {2} other file(s)", folder, filteredpaths.First(), filteredpaths.Count - 1));

                return true;
            }
            catch (Exception ex)
            {
                if (OnError != null)
                    OnError(ex);
            }

            return false;
        }
Пример #2
0
        public static bool VerifyUnpackedFolder(string folder, UpdateInfo version = null)
        {
            try
            {
                UpdateInfo update;
                FileEntry  manifest;

                var sha256 = System.Security.Cryptography.SHA256.Create();
                var md5    = System.Security.Cryptography.MD5.Create();

                using (var fs = System.IO.File.OpenRead(System.IO.Path.Combine(folder, UPDATE_MANIFEST_FILENAME)))
                {
                    using (var ss = new SignatureReadingStream(fs, SIGN_KEY))
                        using (var tr = new System.IO.StreamReader(ss))
                            using (var jr = new Newtonsoft.Json.JsonTextReader(tr))
                                update = new Newtonsoft.Json.JsonSerializer().Deserialize <UpdateInfo>(jr);

                    sha256.Initialize();
                    md5.Initialize();

                    fs.Position = 0;
                    var h1 = Convert.ToBase64String(sha256.ComputeHash(fs));
                    fs.Position = 0;
                    var h2 = Convert.ToBase64String(md5.ComputeHash(fs));

                    manifest = new FileEntry()
                    {
                        Path          = UPDATE_MANIFEST_FILENAME,
                        Ignore        = false,
                        LastWriteTime = update.ReleaseTime,
                        SHA256        = h1,
                        MD5           = h2
                    };
                }

                if (version != null && (update.Displayname != version.Displayname || update.ReleaseTime != version.ReleaseTime))
                {
                    throw new Exception("The found version was not the expected version");
                }

                var paths = update.Files.Where(x => !x.Ignore).ToDictionary(x => x.Path.Replace('/', System.IO.Path.DirectorySeparatorChar), Library.Utility.Utility.ClientFilenameStringComparer);
                paths.Add(manifest.Path, manifest);

                var ignores = (from x in update.Files where x.Ignore select Library.Utility.Utility.AppendDirSeparator(x.Path.Replace('/', System.IO.Path.DirectorySeparatorChar))).ToList();

                folder = Library.Utility.Utility.AppendDirSeparator(folder);
                var baselen = folder.Length;

                foreach (var file in Library.Utility.Utility.EnumerateFileSystemEntries(folder))
                {
                    var relpath = file.Substring(baselen);
                    if (string.IsNullOrWhiteSpace(relpath))
                    {
                        continue;
                    }

                    FileEntry fe;
                    if (!paths.TryGetValue(relpath, out fe))
                    {
                        var ignore = false;
                        foreach (var c in ignores)
                        {
                            if (ignore = relpath.StartsWith(c))
                            {
                                break;
                            }
                        }

                        if (ignore)
                        {
                            continue;
                        }

                        throw new Exception(string.Format("Found unexpected file: {0}", file));
                    }

                    paths.Remove(relpath);

                    if (fe.Path.EndsWith("/"))
                    {
                        continue;
                    }

                    sha256.Initialize();
                    md5.Initialize();

                    using (var fs = System.IO.File.OpenRead(file))
                    {
                        if (Convert.ToBase64String(sha256.ComputeHash(fs)) != fe.SHA256)
                        {
                            throw new Exception(string.Format("Invalid sha256 hash for file: {0}", file));
                        }

                        fs.Position = 0;
                        if (Convert.ToBase64String(md5.ComputeHash(fs)) != fe.MD5)
                        {
                            throw new Exception(string.Format("Invalid md5 hash for file: {0}", file));
                        }
                    }
                }

                var filteredpaths = (from p in paths
                                     where !string.IsNullOrWhiteSpace(p.Key) && !p.Key.EndsWith("/")
                                     select p.Key).ToList();


                if (filteredpaths.Count == 1)
                {
                    throw new Exception(string.Format("Folder {0} is missing: {1}", folder, filteredpaths.First()));
                }
                else if (filteredpaths.Count > 0)
                {
                    throw new Exception(string.Format("Folder {0} is missing {1} and {2} other file(s)", folder, filteredpaths.First(), filteredpaths.Count - 1));
                }

                return(true);
            }
            catch (Exception ex)
            {
                if (OnError != null)
                {
                    OnError(ex);
                }
            }

            return(false);
        }