// apps/desktop/tests/red/crypto-license.usecase.test.ts // Phase 11+: Ed25519 비대칭 암호화 라이센스 검증 & Reverse Trial 유스케이스 테스트 import { describe, it, expect } from 'vitest' import { generateLicenseKeyPair, issueSignedLicenseKey, verifySignedLicenseKey, } from '@d3ro/core/utils/crypto-license' import { getLicenseService } from '../../src/main/services/LicenseService' import { useRedHarness } from './harness' useRedHarness() describe('Ed25519 암호화 라이센스 & Reverse Trial 유스케이스', () => { it('Ed25519 키쌍을 생성하고 유효한 라이센스를 서명/검증할 수 있다', () => { const { publicKeyPem, privateKeyPem } = generateLicenseKeyPair() expect(publicKeyPem).toContain('BEGIN PUBLIC KEY') expect(privateKeyPem).toContain('BEGIN PRIVATE KEY') const payload = { licenseId: 'lic-1001', tier: 'pro_plus' as const, customerEmail: 'alice@enterprise.com', issuedAt: Date.now(), expiresAt: Date.now() + 365 * 24 * 60 * 60 * 1000, machineId: 'test-machine-id-1234', } const key = issueSignedLicenseKey(payload, privateKeyPem) expect(key.startsWith('D3RO-LIC-')).toBe(true) // 검증 성공 const verification = verifySignedLicenseKey(key, 'test-machine-id-1234', publicKeyPem, { environment: 'production', }) expect(verification.valid).toBe(true) expect(verification.tier).toBe('pro_plus') expect(verification.reason).toBe('valid') expect(verification.payload?.customerEmail).toBe('alice@enterprise.com') }) it('운영 환경은 레거시 접두어 키를 명시적 허용 옵션이 있어도 거부한다', () => { const verification = verifySignedLicenseKey( 'D3RO-PRO-TEST-KEY1', undefined, undefined, { allowDevelopmentKeys: true, environment: 'production' }, ) expect(verification.valid).toBe(false) expect(verification.tier).toBe('free') expect(verification.reason).toBe('corrupted_token') }) it('테스트 환경은 명시적으로 허용한 정확한 개발 fixture만 인정한다', () => { const knownFixture = verifySignedLicenseKey( 'D3RO-PRO-TEST-KEY1', undefined, undefined, { allowDevelopmentKeys: true, environment: 'test' }, ) const forgedPrefix = verifySignedLicenseKey( 'D3RO-PRO-ATTACKER-KEY', undefined, undefined, { allowDevelopmentKeys: true, environment: 'test' }, ) expect(knownFixture.valid).toBe(true) expect(knownFixture.tier).toBe('pro') expect(knownFixture.reason).toBe('dev_key') expect(forgedPrefix.valid).toBe(false) expect(forgedPrefix.tier).toBe('free') }) it('운영 공개키가 없으면 서명 형식이 맞아도 fail-closed 한다', () => { const { privateKeyPem } = generateLicenseKeyPair() const key = issueSignedLicenseKey( { licenseId: 'lic-no-production-key', tier: 'enterprise', customerEmail: 'release@example.test', issuedAt: Date.now(), expiresAt: null, machineId: null, }, privateKeyPem, ) const verification = verifySignedLicenseKey(key, undefined, undefined, { environment: 'production', }) expect(verification.valid).toBe(false) expect(verification.reason).toBe('invalid_signature') expect(verification.message).toContain('not configured') }) it('머신 ID가 일치하지 않으면 machine_mismatch 로 실패한다', () => { const { publicKeyPem, privateKeyPem } = generateLicenseKeyPair() const payload = { licenseId: 'lic-1002', tier: 'pro' as const, customerEmail: 'bob@company.com', issuedAt: Date.now(), expiresAt: null, machineId: 'machine-A', } const key = issueSignedLicenseKey(payload, privateKeyPem) const verification = verifySignedLicenseKey(key, 'machine-B', publicKeyPem) expect(verification.valid).toBe(false) expect(verification.reason).toBe('machine_mismatch') }) it('만료된 라이센스는 expired 로 실패한다', () => { const { publicKeyPem, privateKeyPem } = generateLicenseKeyPair() const payload = { licenseId: 'lic-1003', tier: 'pro' as const, customerEmail: 'charlie@past.com', issuedAt: Date.now() - 100000, expiresAt: Date.now() - 1000, // 이미 만료됨 machineId: null, } const key = issueSignedLicenseKey(payload, privateKeyPem) const verification = verifySignedLicenseKey(key, undefined, publicKeyPem) expect(verification.valid).toBe(false) expect(verification.reason).toBe('expired') }) it('서명이 위조된 라이센스는 invalid_signature 로 실패한다', () => { const { publicKeyPem } = generateLicenseKeyPair() const otherKeyPair = generateLicenseKeyPair() const payload = { licenseId: 'lic-forged', tier: 'pro_plus' as const, customerEmail: 'attacker@evil.com', issuedAt: Date.now(), expiresAt: null, machineId: null, } // 다른 키로 서명 (위조 시도) const forgedKey = issueSignedLicenseKey(payload, otherKeyPair.privateKeyPem) const verification = verifySignedLicenseKey(forgedKey, undefined, publicKeyPem) expect(verification.valid).toBe(false) expect(verification.reason).toBe('invalid_signature') }) it('LicenseService.startTrial() 호출 시 14일 Pro+ Reverse Trial 이 활성화된다', () => { const svc = getLicenseService() svc.initialize() const result = svc.startTrial('trial-tester@local') expect(result.success).toBe(true) expect(result.tier).toBe('pro_plus') expect(svc.tier).toBe('pro_plus') const info = svc.getInfo() expect(info.isTrial).toBe(true) expect(info.trialExpiresAt).toBeGreaterThan(Date.now()) // 중복 체험 시작은 방지된다 const retry = svc.startTrial('again@local') expect(retry.success).toBe(false) }) })