using TheCr3w.Shared.Crypto; using TheCr3w.Shared.Models; using Xunit; namespace TheCr3w.Tests; public class CryptoTests { [Fact] public void GenerateKeyPair_ShouldGenerateValidHexKeys() { var (privKey, pubKey) = Ed25519Service.GenerateKeyPair(); Assert.NotNull(privKey); Assert.NotNull(pubKey); Assert.Equal(64, privKey.Length); // 32 bytes seed in hex Assert.Equal(64, pubKey.Length); // 32 bytes public key in hex } [Fact] public void ReleaseMetadata_SignAndVerify_ShouldSucceedForValidData() { var (privKey, pubKey) = Ed25519Service.GenerateKeyPair(); var metadata = new ReleaseMetadata { ReleaseId = Guid.NewGuid(), AppId = "com.thecr3w.app", Version = "1.0.0", VersionCode = 1, Platform = "android", Architecture = "arm64-v8a", Channel = "stable", Mandatory = false, MinimumSupportedVersion = "1.0.0", FileSize = 10485760, Sha256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", PublishedAt = DateTimeOffset.UtcNow, ReleaseNotes = "Wstępne wydanie" }; var canonicalBytes = Ed25519Service.GetCanonicalBytes(metadata); var signature = Ed25519Service.Sign(canonicalBytes, privKey); Assert.NotNull(signature); Assert.Equal(128, signature.Length); var isValid = Ed25519Service.Verify(canonicalBytes, signature, pubKey); Assert.True(isValid, "Podpis powinien być poprawny dla oryginalnych danych"); } [Fact] public void ReleaseMetadata_TamperingData_ShouldFailVerification() { var (privKey, pubKey) = Ed25519Service.GenerateKeyPair(); var metadata = new ReleaseMetadata { ReleaseId = Guid.NewGuid(), AppId = "com.thecr3w.app", Version = "1.0.0", VersionCode = 1, Platform = "android", Architecture = "arm64-v8a", Channel = "stable", Mandatory = false, MinimumSupportedVersion = "1.0.0", FileSize = 10485760, Sha256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", PublishedAt = DateTimeOffset.UtcNow, ReleaseNotes = "Oryginał" }; var canonicalBytes = Ed25519Service.GetCanonicalBytes(metadata); var signature = Ed25519Service.Sign(canonicalBytes, privKey); // Atak podmiany: Zmiana sumy SHA256 w pobranym pakiecie metadata.Sha256 = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; var tamperedBytes = Ed25519Service.GetCanonicalBytes(metadata); var isValid = Ed25519Service.Verify(tamperedBytes, signature, pubKey); Assert.False(isValid, "Podpis NIE może przejść weryfikacji po zmodyfikowaniu danych"); } [Fact] public void DeploymentManifest_SignAndVerify_ShouldSucceed() { var (privKey, pubKey) = Ed25519Service.GenerateKeyPair(); var manifest = new DeploymentManifest { ManifestId = Guid.NewGuid(), Project = "thecr3w-backend", Environment = "production", ServiceName = "backend", Image = "git.thecr3wnet.com/thecr3w/backend", ImmutableDigest = "sha256:7a59d8134bb8df389a9f24255198ec51787c9dc08269d7b420f1885b0d0ce0bf", ConfigHash = "b5a2c96250612366ea8c2c10df6be0ab45e561398730707cdaed864537197f4f", SecretsReferences = new() { "DB_PASSWORD", "KEYCLOAK_SECRET" }, RequiredMigrations = new() { "20261031_01_Init" }, CreatedAt = DateTimeOffset.UtcNow, CreatedBy = "ci-bot" }; var canonicalBytes = ManifestSigner.GetCanonicalBytes(manifest); var signature = Ed25519Service.Sign(canonicalBytes, privKey); manifest.SignatureEd25519 = signature; var sha256 = ManifestSigner.ComputeManifestSha256(manifest); Assert.NotNull(sha256); Assert.Equal(64, sha256.Length); var isValid = Ed25519Service.Verify(canonicalBytes, signature, pubKey); Assert.True(isValid); } }