feat(ads/seo/release): v1.2.0 with live Google Ads, isolated ad profile, ads.txt, and SEO/AEO/GEO optimization
This commit is contained in:
parent
a88aafa1e5
commit
0e568f1f0a
975 changed files with 130593 additions and 16783 deletions
97
tests/Paca.Tests/Security/VirtualFido2AdversarialTests.cs
Normal file
97
tests/Paca.Tests/Security/VirtualFido2AdversarialTests.cs
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Paca.Core.Security;
|
||||
using Xunit;
|
||||
|
||||
namespace Paca.Tests.Security;
|
||||
|
||||
/// <summary>
|
||||
/// RED TEAM ATTACK SUITE: FIDO2 / Passkey 암호학적 공격 침투 테스트
|
||||
/// 1. 타인의 공개키/자격증명으로 서명 바꿔치기(Identity Spoofing) 방어
|
||||
/// 2. AuthenticatorData 플래그(User Present / User Verified) 변조 방어
|
||||
/// 3. ClientDataHash 1비트 조작 변조(Bit-Flip Tampering) 방어
|
||||
/// 4. 존재하지 않거나 유효하지 않은 CredentialId 접근 거부
|
||||
/// </summary>
|
||||
public class VirtualFido2AdversarialTests
|
||||
{
|
||||
private readonly VirtualFido2Authenticator _authenticator = VirtualFido2Authenticator.Default;
|
||||
|
||||
[Fact]
|
||||
public void RedTeam_IdentitySpoofing_WithAnotherCredential_MustFail()
|
||||
{
|
||||
// 피해자(victim)와 공격자(attacker) 자격증명 생성
|
||||
var victim = _authenticator.CreateCredential("paca.local", "victim-user", "Alice");
|
||||
var attacker = _authenticator.CreateCredential("paca.local", "attacker-user", "Mallory");
|
||||
|
||||
var challengeHash = SHA256.HashData(Encoding.UTF8.GetBytes("super-secret-challenge"));
|
||||
|
||||
// 공격자가 자신의 키로 서명 발행
|
||||
var attackerAssertion = _authenticator.SignChallenge(attacker.CredentialId, challengeHash);
|
||||
|
||||
// 공격자의 서명을 피해자의 CredentialId로 검증 시도 -> 암호학적으로 반드시 거부되어야 함
|
||||
var result = _authenticator.VerifyAssertion(
|
||||
victim.CredentialId,
|
||||
challengeHash,
|
||||
attackerAssertion.AuthenticatorData,
|
||||
attackerAssertion.Signature);
|
||||
|
||||
Assert.False(result, "[Red Team] 타인의 자격증명으로 서명 위조 시 반드시 검증 실패해야 합니다.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RedTeam_BitFlipTampering_OnClientDataHash_MustFail()
|
||||
{
|
||||
var cred = _authenticator.CreateCredential("paca.local", "user-bitflip", "Bob");
|
||||
var challengeHash = SHA256.HashData(Encoding.UTF8.GetBytes("legit-challenge"));
|
||||
var assertion = _authenticator.SignChallenge(cred.CredentialId, challengeHash);
|
||||
|
||||
// 챌린지 해시의 1비트를 고의로 조작(Bit-Flip)
|
||||
var tamperedHash = (byte[])challengeHash.Clone();
|
||||
tamperedHash[0] ^= 0x01;
|
||||
|
||||
var result = _authenticator.VerifyAssertion(
|
||||
cred.CredentialId,
|
||||
tamperedHash,
|
||||
assertion.AuthenticatorData,
|
||||
assertion.Signature);
|
||||
|
||||
Assert.False(result, "[Red Team] 챌린지 해시의 단 1비트만 변조되어도 서명 검증이 실패해야 합니다.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RedTeam_AuthenticatorData_Tampering_MustFail()
|
||||
{
|
||||
var cred = _authenticator.CreateCredential("paca.local", "user-authdata", "Charlie");
|
||||
var challengeHash = SHA256.HashData(Encoding.UTF8.GetBytes("auth-flags-challenge"));
|
||||
var assertion = _authenticator.SignChallenge(cred.CredentialId, challengeHash);
|
||||
|
||||
// AuthenticatorData 내의 플래그 바이트(Offset 32)를 고의로 변조
|
||||
var tamperedAuthData = (byte[])assertion.AuthenticatorData.Clone();
|
||||
tamperedAuthData[32] ^= 0xFF; // Flags 변조
|
||||
|
||||
var result = _authenticator.VerifyAssertion(
|
||||
cred.CredentialId,
|
||||
challengeHash,
|
||||
tamperedAuthData,
|
||||
assertion.Signature);
|
||||
|
||||
Assert.False(result, "[Red Team] AuthenticatorData의 플래그 또는 카운터가 변조되면 서명 검증이 실패해야 합니다.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RedTeam_NonExistentCredential_MustReject()
|
||||
{
|
||||
var challengeHash = SHA256.HashData(Encoding.UTF8.GetBytes("ghost-challenge"));
|
||||
var fakeSignature = new byte[64];
|
||||
var fakeAuthData = new byte[37];
|
||||
|
||||
var result = _authenticator.VerifyAssertion(
|
||||
"non-existent-credential-id-99999",
|
||||
challengeHash,
|
||||
fakeAuthData,
|
||||
fakeSignature);
|
||||
|
||||
Assert.False(result, "[Red Team] 존재하지 않는 자격증명 ID는 즉시 거부되어야 합니다.");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue