using System; using System.IO; using System.Security.Cryptography; using System.Text; using Paca.Mobile.Core; using Xunit; namespace Paca.Tests.Mobile; /// /// RED TEAM ATTACK SUITE: P2P QR 페어링 및 미디어 무결성 적대적 공격 테스트 /// 1. 조작된 체크섬/토큰 주입 시 디코딩 거부 /// 2. 잘못된 프로토콜 프리픽스 및 악의적 URI 주입 방어 /// 3. 헤더 매직 바이트 위조(앞 4바이트만 맞고 바디가 절단된 Truncated 공격) 방어 /// public class MobileP2pAndMediaAdversarialTests { [Fact] public void RedTeam_QrPayload_ChecksumTampering_MustReject() { var payload = new P2pQrPayload { Host = "192.168.1.100", Port = 52100, Token = "token-xyz-123", DeviceName = "Desktop-PC" }; var encoded = P2pQrPayloadCodec.Encode(payload); // 페이로드 중간의 토큰 1글자 변조 var tampered = encoded.Replace("token-xyz-123", "token-EVIL-666"); var success = P2pQrPayloadCodec.TryDecode(tampered, out var decoded); Assert.False(success, "[Red Team] 체크섬과 본문 내용이 불일치하는 변조된 QR 페이로드는 거부되어야 합니다."); Assert.Null(decoded); } [Fact] public void RedTeam_QrPayload_InvalidPrefix_Or_CorruptedUri_MustReject() { Assert.False(P2pQrPayloadCodec.TryDecode("http://attacker.com/fake-pair", out _)); Assert.False(P2pQrPayloadCodec.TryDecode("paca://invalid?h=1&p=bad&sig=000", out _)); Assert.False(P2pQrPayloadCodec.TryDecode("", out _)); Assert.False(P2pQrPayloadCodec.TryDecode(null!, out _)); } [Fact] public void RedTeam_MediaIntegrity_TruncatedPayload_MustDetectCorruption() { // MP4 매직 'ftyp'는 존재하지만 크기가 6바이트로 잘린 비정상 스트림 var truncatedMp4 = new byte[] { 0x00, 0x00, 0x00, 0x20, 0x66, 0x74 }; Assert.False(MediaIntegrityVerifier.ValidateMediaHeader(truncatedMp4, ".mp4")); // 0바이트 파일 var zeroByteResult = MediaIntegrityVerifier.InspectIntegrity(Array.Empty(), "video.mp4"); Assert.False(zeroByteResult.IsValid); Assert.Contains("0바이트", zeroByteResult.ErrorReason); // 확장자와 내용물 불일치 공격 (WebM 헤더를 가진 파일을 .mp4로 위장) var webmHeader = new byte[] { 0x1A, 0x45, 0xDF, 0xA3, 0x00, 0x00, 0x00, 0x00 }; var spoofResult = MediaIntegrityVerifier.InspectIntegrity(webmHeader, "fake_video.mp4"); Assert.False(spoofResult.IsValid, "[Red Team] 확장자(.mp4)와 실제 컨테이너(WebM) 헤더가 불일치하면 무결성 검증이 실패해야 합니다."); } [Fact] public void RedTeam_MediaIntegrity_Sha256Tampering_MustDetect() { var validMp4 = new byte[64]; validMp4[4] = 0x66; validMp4[5] = 0x74; validMp4[6] = 0x79; validMp4[7] = 0x70; // ftyp var correctHash = Convert.ToHexString(SHA256.HashData(validMp4)).ToLowerInvariant(); var forgedHash = correctHash.Substring(0, 60) + "dead"; // 끝 4자리 위조 var result = MediaIntegrityVerifier.InspectIntegrity(validMp4, "test.mp4", forgedHash); Assert.False(result.IsValid); Assert.False(result.ChecksumMatch); Assert.Contains("불일치", result.ErrorReason); } }