"소프트웨어의 완성은 컴파일이 끝나는 순간이 아니라, 사용자의 컴퓨터에서 한 치의 보안 경고 없이 안전하게 실행되는 순간 완성됩니다. 외부 상용 CA에 의존할 수 없는 국방·공공 폐쇄망에서 암호학적 신뢰 체인을 스스로 증명하고 배포 무결성을 수호하는 것—그것이 ZeliCert가 추구하는 엔지니어링의 본질입니다."
1. 전산실 40대 PC와 국방 폐쇄망의 배포 중단 위기: SmartScreen 경고와 인증서 만료의 덫
초·중·고등학교 컴퓨터실, 국가 디지털 교과서(AIDT) 실습 PC, 군부대 작전 교육망 등 공공·국방 소프트웨어 인프라에서 새로운 애플리케이션(MSIX, EXE, DLL)을 배포할 때 가장 빈번하게 발생하는 재앙은 디지털 서명(Digital Signature) 실패입니다.
Windows 10 및 Windows 11 운영체제는 커널 수준의 보안 정책(SmartScreen, HVCI)을 통해 디지털 서명이 누락되었거나 신뢰할 수 없는 게시자가 제작한 실행 파일을 "위험한 프로그램"으로 간주하고 실행을 원천 차단합니다. 이로 인해 다음과 같은 세 가지 치명적인 문제가 반복됩니다:
- 상용 공인인증서(CA)의 폐쇄망 한계: DigiCert, Sectigo 등의 상용 코드 서명 인증서는 매년 수백만 원의 비용이 발생할 뿐 아니라, 외부 인터넷 연결을 통해 CRL(인증서 폐기 목록) 및 OCSP 서버와 통신해야 하므로 물리적 망분리(Air-Gap) 국방망에서는 서명 검증 타임아웃으로 배포가 중단됩니다.
- 인증서 만료에 따른 일괄 실행 마비: 테스트용 자체 서명 인증서의 유효기간(보통 1년)이 만료되는 순간, 컴퓨터실 40대 PC 전역에서 솔루션 구동이 일제히 정지되어 수업 파행이 발생합니다.
- 프로젝트 파일과 서명 키의 불일치: Visual Studio에서 MSIX 패키지를 빌드할 때,
.csproj파일에 선언된PackageCertificateThumbprint와 실제 로컬 인증서 저장소의 지문(Thumbprint)이 일치하지 않아 원인을 알 수 없는 빌드 실패가 지속됩니다.
| 비교 항목 | 상용 외부 CA (DigiCert 등) | 수동 PowerShell 콘솔 작업 | ZeliCert 온디바이스 거버넌스 |
|---|---|---|---|
| 폐쇄망(Air-Gap) 호환성 | CRL/OCSP 조회 실패로 지연·오류 | 스크립트 오류 및 경로 파편화 | 로컬 Root CA 자동 등록으로 0초 검증 |
| 도입 및 유지 비용 | 연간 80만 ~ 300만 원 (고비용) | 무료 (하지만 높은 관리 공수) | 완전 무료 (자체 서명 인프라 내장) |
| SignTool 자동 연동 | 수동 CLI 명령어 조합 필수 | 경로 수동 탐색 및 구문 오류 빈발 | Windows SDK 최신 SignTool 자동 감지 |
| .csproj 프로젝트 동기화 | XML 수동 복사·붙여넣기 | 휴먼 에러로 빌드 실패 빈발 | 웹 대시보드 원클릭 Thumbprint 자동 교체 |
| 외부 통신량 | 인증서 검증 패킷 지속 발생 | 0바이트 | 완전 0바이트 (Localhost 전용 격리) |
ZeliCert는 이러한 배포 장애를 영구적으로 제거하기 위해 개발된 인트라넷 전용 X.509 인증서 관리 및 MSIX 무결성 바이너리 서명 대시보드입니다.
2. X.509 자체 서명 인증서 및 EKU(코드 서명 전용 확장) 자동 발급 파이프라인
Windows에서 MSIX 패키지를 정상적으로 인식하기 위해서는 단순 SSL 인증서가 아닌, 코드 서명 확장(Enhanced Key Usage, OID: 1.3.6.1.5.5.7.3.3)이 부여된 X.509 인증서가 필수적입니다. ZeliCert는 PowerShell PKI 모듈을 추상화하여, 원하는 유효기간(기본 3년~10년)을 가진 정밀한 코드 서명 인증서를 0초 만에 발급합니다.
// ═══════════════════════════════════════════════════════
// ZeliCert X.509 코드 서명 인증서 자동 생성 파이프라인
// ═══════════════════════════════════════════════════════
app.post('/api/certs/create', requireAuth, (req, res) => {
try {
const { subject, friendlyName, years, keyUsage } = req.body;
const cn = (subject || 'CN=hajunho').replace(/'/g, "''").replace(/"/g, '');
const fn = (friendlyName || 'hajunho').replace(/'/g, "''").replace(/"/g, '');
const yrs = parseInt(years) || 3;
// EKU(Extended Key Usage) OID 주입: 코드 서명(1.3.6.1.5.5.7.3.3)
let ekuOid = '1.3.6.1.5.5.7.3.3';
if (keyUsage === 'ssl') ekuOid = '1.3.6.1.5.5.7.3.1'; // Server Auth
if (keyUsage === 'both') ekuOid = '1.3.6.1.5.5.7.3.3,1.3.6.1.5.5.7.3.1';
// [핵심] 인증서 생성 즉시 신뢰할 수 있는 루트 기관(Root, CurrentUser)에 등록
const ps = [
`$cert = New-SelfSignedCertificate -Type Custom -Subject '${cn}' ` +
`-KeyUsage DigitalSignature -FriendlyName '${fn}' ` +
`-CertStoreLocation 'Cert:\\CurrentUser\\My' -NotAfter (Get-Date).AddYears(${yrs}) ` +
`-TextExtension @('2.5.29.37={text}${ekuOid}', '2.5.29.19={text}')`,
`$store = New-Object System.Security.Cryptography.X509Certificates.X509Store('Root','CurrentUser')`,
`$store.Open('ReadWrite')`,
`$store.Add($cert)`,
`$store.Close()`,
`$cert.Thumbprint`
].join('; ');
const thumbprint = runPS(ps).trim();
res.json({
success: true,
thumbprint,
message: `인증서가 생성되고 신뢰할 수 있는 루트 기관에 자동 등록되었습니다: ${thumbprint}`
});
} catch (e) {
res.status(500).json({ error: e.message });
}
});
특히 생성과 동시에 X509Store('Root', 'CurrentUser')에 인증서를 주입함으로써, 별도의 복잡한 mmc 콘솔 작업 없이도 "이 게시자를 신뢰할 수 없습니다"라는 시스템 경고를 사전에 완벽히 무력화합니다.
3. Windows SDK SignTool 자동 탐색 및 SHA-256 바이너리 서명 엔진
개발 머신마다 설치된 Windows SDK의 버전(10.0.19041.0, 10.0.22621.0 등)과 아키텍처(x64, arm64)가 달라, 빌드 자동화 스크립트에서 signtool.exe를 찾지 못해 실패하는 경우가 흔합니다.
ZeliCert는 파일 시스템 순회 알고리즘을 통해 시스템에 설치된 최신 SignTool을 자동으로 찾아내고, 업로드된 바이너리에 고강도 암호학적 서명을 부여합니다.
// ── Windows SDK 최신 SignTool 자동 탐색 ──
function findSignTool() {
const searchPaths = [
'C:\\Program Files (x86)\\Windows Kits\\10\\bin',
'C:\\Program Files\\Windows Kits\\10\\bin'
];
for (const base of searchPaths) {
if (!fs.existsSync(base)) continue;
const versions = fs.readdirSync(base)
.filter(d => d.match(/^10\.\d+/))
.sort().reverse();
for (const ver of versions) {
for (const arch of ['x64', 'x86', 'arm64']) {
const p = path.join(base, ver, arch, 'signtool.exe');
if (fs.existsSync(p)) return p;
}
}
}
return null;
}
// ── SHA-256 무결성 바이너리 서명 & RFC 3161 타임스탬프 주입 ──
app.post('/api/sign', requireAuth, upload.single('binaryFile'), async (req, res) => {
const toolPath = findSignTool();
const tp = (req.body.thumbprint || '').replace(/[^a-fA-F0-9]/g, '');
const targetPath = path.join(os.tmpdir(), 'zelicert_sign', req.file.originalname);
// SHA256 다이제스트 알고리즘 및 공인 타임스탬프 결합
const cmd = `& '${toolPath}' sign /sha1 ${tp} /fd SHA256 /t http://timestamp.digicert.com '${targetPath}'`;
await runPSAsync(cmd);
res.download(targetPath, `signed_${req.file.originalname}`);
});
서명된 바이너리는 SHA-256 해시 다이제스트와 RFC 3161 규격의 타임스탬프를 포함하므로, 훗날 인증서의 원래 유효기간이 지나더라도 "서명 당시 유효했던 인증서"로 영구 인정되어 애플리케이션의 지속적인 실행을 보장합니다.
4. Visual Studio & ZeliDesk.csproj 원클릭 프로젝트 동기화 거버넌스
MSIX 패키징 빌드 시 발생하는 가장 큰 번거로움은 새 인증서를 만들 때마다 프로젝트 파일의 XML 태그를 수동으로 찾아 고쳐야 한다는 점입니다. ZeliCert는 웹 대시보드에서 클릭 한 번으로 프로젝트 파일의 Thumbprint를 원자적으로 교체하는 Project Integration 파이프라인을 내장했습니다.
const CSPROJ_PATH = path.resolve(__dirname, '..', 'ZeliDesk.csproj');
// 원클릭 .csproj 패키징 인증서 지문(Thumbprint) 일괄 치환
app.post('/api/project-update', requireAuth, (req, res) => {
const tp = req.body.thumbprint.replace(/[^a-fA-F0-9]/g, '');
let content = fs.readFileSync(CSPROJ_PATH, 'utf-8');
content = content.replace(
/<PackageCertificateThumbprint>[^<]+<\/PackageCertificateThumbprint>/,
`<PackageCertificateThumbprint>${tp}<\/PackageCertificateThumbprint>`
);
content = content.replace(
/<AppxPackageSigningThumbprint>[^<]+<\/AppxPackageSigningThumbprint>/,
`<AppxPackageSigningThumbprint>${tp}<\/AppxPackageSigningThumbprint>`
);
fs.writeFileSync(CSPROJ_PATH, content, 'utf-8');
res.json({ success: true, message: `ZeliDesk.csproj가 업데이트되었습니다. Thumbprint: ${tp}` });
});
이를 통해 개발자나 전산 담당자는 인증서 갱신 후 즉시 Visual Studio에서 F5 또는 게시(Publish)를 눌러 무결성이 검증된 MSIX 패키지를 0초 지연으로 빌드할 수 있습니다.
5. 0바이트 외부 통신 & 로컬 인트라넷 보안 (Air-Gap Zero-Data-Leak)
인증서의 개인키(.pfx, Private Key)는 소프트웨어 서명 권한의 정점이므로 절대 외부로 유출되어서는 안 됩니다. ZeliCert는 다음과 같은 다중 보안 설계를 엄격히 준수합니다:
- Localhost 완전 격리 (0.0.0.0 바인딩 차단): 외부 인터넷 통신 0바이트를 유지하며, 로컬 관리자 세션(8시간 만료 쿠키)을 통해서만 제어 가능.
- 정규식 기반 16진수 살균(Sanitization): 모든 지문 입력값을
replace(/[^a-fA-F0-9]/g, '')로 정제하여 PowerShell 명령 주입(Command Injection) 위협을 원천 차단. - 원클릭 PFX 암호화 내보내기/가져오기:
Export-PfxCertificate를 통해 관리자 암호로 강력히 암호화된 PFX 형태로만 키를 이동하여, 전산실 40대 PC에 동일 서명 환경을 안전하게 배포.
6. 결론: 신뢰할 수 있는 국가 공공 소프트웨어 배포 인프라의 미래
ZeliCert는 보안과 편의성이 대립하지 않고, 견고한 자동화 아키텍처를 통해 완벽히 조화될 수 있음을 보여줍니다.
- MSIX Desktop Bridge(#986)와의 결합: 관리자 권한 없는 학교 PC 원클릭 배포 패키지에 ZeliCert의 무결성 서명을 주입하여 100% 무인 자동 설치 파이프라인 완성.
- Windows 11 HVCI 메모리 무결성(#998)과의 연계: 커널 격리 환경에서도 악성코드로 오인되지 않는 완벽한 서명 바이너리 공급망 확보.
- 차세대 HSM(하드웨어 보안 모듈) 및 YubiKey FIPS 확장: 국방 C4I 최고 등급 보안 규격을 충족하기 위해 FIPS 140-2 Level 3 하드웨어 토큰 기반 서명 모듈 연계 추진.
보안 경고 없는 무결점 배포, 외부 클라우드 의존 없는 자체 암호학적 신뢰 구축—ZeliDesk가 교육과 국방 전산망을 위해 완성해 나가는 독립적 엔지니어링 표준입니다.