using System.Security.Cryptography; using ScadaLink.Commons.Types.Transport; namespace ScadaLink.Transport.Serialization; /// /// Outcome of validating a against the supplied /// raw content bytes. Distinct values let the importer surface a precise /// rejection reason to the operator. /// public enum ManifestValidationResult { Ok, UnsupportedFormatVersion, ContentHashMismatch, MalformedManifest } /// /// Inspects a deserialized manifest plus the raw content bytes recovered from /// the bundle ZIP and reports the first integrity failure (or ). /// public sealed class ManifestValidator { public ManifestValidationResult Validate(BundleManifest manifest, byte[] contentBytes) { if (manifest is null || contentBytes is null) { return ManifestValidationResult.MalformedManifest; } if (string.IsNullOrEmpty(manifest.SourceEnvironment) || manifest.Contents is null) { return ManifestValidationResult.MalformedManifest; } if (manifest.BundleFormatVersion != ManifestBuilder.CurrentBundleFormatVersion) { return ManifestValidationResult.UnsupportedFormatVersion; } var expected = "sha256:" + Convert.ToHexString(SHA256.HashData(contentBytes)).ToLowerInvariant(); if (!string.Equals(expected, manifest.ContentHash, StringComparison.Ordinal)) { return ManifestValidationResult.ContentHashMismatch; } return ManifestValidationResult.Ok; } }