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