소프트웨어를 배포할 때 그 소프트웨어가 누구에 의해 만들어졌고, 배포 과정에서 변조되지 않았으며, 정당한 절차를 거쳐 승인되었는지 보증하는 것은 보안의 기본이다.
이번 글에서는 소프트웨어의 신원과 무결성을 보증하는 코드사인, 그리고 복수 인가자의 협업으로 승인을 완성하는 연대서명에 대해 알아보기로 한다.
두 개념 모두 서명의 대상인 "바이너리"에 대한 이해가 선행되어야 하므로, 바이너리가 무엇인지부터 정리하고 들어가자.
1. 바이너리와 서명의 기초 개념
1️⃣ 소프트웨어 바이너리
소프트웨어 바이너리는 컴퓨터가 직접 실행할 수 있는 기계어(machine code)로 컴파일된 파일이다. 사람이 읽고 이해할 수 있는 소스 코드(source code)와 대비되는 개념이다.
개발자가 작성한 C, C++, Java 같은 소스 코드는 그 자체로 CPU가 실행할 수 없다. 컴파일러가 이 소스 코드를 CPU가 직접 해석 가능한 이진 형태(0과 1)의 명령어 집합으로 변환하는데, 이 결과물이 바이너리다. 소스 코드는 사람이 작성하고 검토하는 대상이고, 바이너리는 컴퓨터가 실행하고 서명이 검증하는 대상이다.

운영체제마다 바이너리의 확장자와 내부 형식이 다르다. Windows는 .exe, .dll 형태의 PE(Portable Executable) 포맷을 사용하고, macOS는 .dmg, .app과 Mach-O 실행 파일을 사용하며, Linux와 Android는 ELF 실행 파일과 실행 코드를 내부에 담은 .apk를 사용한다. 코드사인이 서명하는 대상이 바로 이 바이너리이며, 소스 코드 단계가 아니라 컴파일이 완료되어 실제로 배포되고 실행되는 최종 파일에 서명을 적용한다.
2️⃣ "바이너리에 서명한다"는 것의 의미
"바이너리에 서명했다"는 표현은 파일 안에 코드를 삽입하거나 파일 전체를 암호화하는 것이 아니다. 바이너리로부터 계산한 해시값을 개발사의 개인키로 암호화한 서명 데이터를 파일에 첨부하는 작업을 의미한다. 서명 도구는 다음 세 단계를 수행한다.
🔵 해시 계산
서명 도구(Windows의 signtool, macOS의 codesign 등)가 바이너리 파일 전체에 해시 함수(SHA-256 등)를 적용한다. 결과는 파일 전체를 대표하는 고정 길이의 해시값 하나다. 파일에서 단 한 비트라도 바뀌면 이 해시값은 완전히 달라진다.
🔵 해시값을 개인키로 암호화
개발사가 CA로부터 발급받은 코드사인 인증서에는 개인키와 공개키 쌍이 연결되어 있다. 개발사만 보유한 개인키로 방금 계산한 해시값을 암호화한다. 이 암호화된 값이 전자서명이다.
🔵 서명과 인증서를 바이너리에 첨부
암호화된 서명값과 개발사 신원을 증명하는 CA 발급 인증서를 원본 바이너리 파일에 덧붙인다. 파일 형식에 따라 별도의 서명 블록이나 전용 필드에 삽입되며, 이 과정에서 원본 실행 코드 자체는 수정되지 않는다.
서명이 "변형"이 아니라 "첨부"이기 때문에, 바이너리의 실행 로직은 서명 전후로 동일하다. 서명은 파일에 봉인을 붙이는 것과 같은 개념이며, 사용자 측 OS는 이 봉인을 검사하여 파일의 신뢰성을 판정한다.

2. 코드사인 (Code Signing)
1️⃣ 개념
코드사인은 실행 파일(.exe, .apk, .dmg 등)이나 스크립트 같은 소프트웨어에 적용하는 전자서명이다. 소프트웨어 바이너리에 개발사의 디지털 서명을 부착하여, 해당 소프트웨어가 누구에 의해 배포되었으며 배포 이후 변조되지 않았음을 검증 가능하게 만든다.
2️⃣ 원리 및 역할
인증기관(CA)에서 발급받은 코드사인 인증서를 사용하여 프로그램 바이너리에 서명한다. 이 서명은 두 가지를 보증한다.
🔵 개발사 신원 보증
서명에 포함된 인증서는 CA가 검증한 소프트웨어 개발사의 신원 정보를 담고 있다. 사용자는 서명을 통해 소프트웨어의 실제 게시자가 누구인지 확인할 수 있다.
🔵 무결성 입증
서명 시점에 계산한 바이너리 해시값이 서명 안에 봉인되어 있다. 배포 과정에서 악성코드 삽입이나 파일 변조가 발생하면 해시값이 달라지므로, 검증 단계에서 서명 불일치가 감지된다.
3️⃣ 서명 및 검증 원리
코드사인은 공개키 기반 구조(PKI)를 활용한다. 서명 단계에서 개발사는 개인키로 해시값을 암호화하고, 검증 단계에서 사용자 OS는 공개키로 이를 복호화하여 두 해시값을 비교한다.

검증 단계에서 사용자 OS는 수신한 바이너리에서 해시값을 다시 계산(A)하고, 첨부된 전자서명을 인증서의 공개키로 복호화하여 서명 시점의 해시값(B)을 복원한다. 두 값이 일치하면 파일이 변조되지 않은 것이며, 인증서 체인이 신뢰할 수 있는 CA로 연결되면 게시자 신원이 확인된다. 여기서 개인키로 암호화한 것을 공개키로만 복호화할 수 있다는 비대칭 암호의 성질이, 서명이 실제로 그 개발사에 의해 생성되었음을 보장한다.
4️⃣ 효과
서명된 소프트웨어는 운영체제 보안 시스템에서 신뢰 대상으로 처리된다. Windows SmartScreen이나 macOS Gatekeeper는 서명되지 않았거나 신뢰할 수 없는 서명을 가진 소프트웨어에 "알 수 없는 게시자" 경고를 표시한다. 유효한 코드사인이 적용된 소프트웨어는 이러한 경고 없이 사용자가 신뢰하고 설치할 수 있다.
3. 연대서명 (Joint Signature / Co-signing / Multi-sig)
1️⃣ 개념
연대서명은 단일 주체의 승인만으로 시스템이 작동하지 않도록, 정해진 복수의 인가자가 각자의 전자서명을 완료해야만 배포나 트랜잭션이 최종 승인되는 다중 검증 체계다. 예를 들어 관리자 3명 중 2명 이상의 서명이 있어야 승인이 성립하는 방식(임계값 서명, threshold signature)으로 구성된다.
단일 서명 방식은 하나의 개인키가 탈취되면 전체 시스템이 위협받지만, 연대서명은 승인 권한을 복수 주체에 분산시켜 단일 실패 지점(single point of failure)을 제거한다.
2️⃣ 승인 흐름
관리자 3명 중 2명 이상의 서명이 필요한 2-of-3 구조에서, 승인 시스템은 각 인가자에게 서명을 요청하고 수집된 서명 수가 임계값에 도달하는 순간 승인을 확정한다.

관리자 A와 B의 서명이 수집되어 임계값 2를 충족하면, 관리자 C의 서명 없이도 배포가 승인된다. 임계값을 충족하지 못하면 요청은 대기 또는 거부 상태로 유지된다.
3️⃣ 검증 구조
각 인가자의 서명은 개별적으로 유효성이 검증된다. 위조되거나 권한 없는 주체의 서명은 유효 서명 수에서 제외되며, 유효 서명 수가 임계값 이상일 때만 승인이 확정된다.

4️⃣ 활용
연대서명은 단일 주체의 판단 오류나 개인키 탈취가 치명적 결과로 이어지는 고위험 환경에서 사용된다.
🔵 고보안 소프트웨어 배포 파이프라인
프로덕션 환경에 배포되는 코드나 인프라 변경 사항에 복수 승인자의 서명을 요구하여, 단독 배포로 인한 사고나 내부자 위협을 방지한다.
🔵 금융권 결제 승인 시스템
고액 이체나 중요 거래에 복수 담당자의 승인을 강제하여, 단일 계정 탈취만으로 부정 거래가 성립하지 않도록 한다.
🔵 블록체인 멀티시그 지갑
자산 이동에 다수의 개인키 서명을 요구하여, 하나의 키가 유출되어도 자산이 즉시 탈취되지 않도록 보호한다.
4. 코드사인과 연대서명의 관계
코드사인은 "누가 배포했는가"와 "변조되지 않았는가"를 보증하는 무결성·신원 검증 기술이며, 연대서명은 "누구의 승인으로 배포되는가"를 통제하는 권한 분산 체계다. 두 기술은 배타적이지 않고 결합하여 사용된다.
실제 고보안 배포 파이프라인에서는 연대서명으로 복수 인가자의 승인을 확보한 뒤, 최종 산출물에 코드사인을 적용하여 배포한다. 연대서명이 배포 결정의 정당성을 확보하고, 코드사인이 배포된 산출물의 신뢰성을 사용자 측에서 검증 가능하게 만드는 상호 보완 관계다.
'Journey to Security > 엔드포인트' 카테고리의 다른 글
| Active Directory 인증 공격의 이해 — Pass-the-Hash와 Golden Ticket, 그리고 방어 체계 (0) | 2026.08.08 |
|---|---|
| Active Directory와 Domain Controller의 구조, 그리고 이기종 OS 연동 (0) | 2026.08.08 |
| 엔드포인트 보안 이벤트와 Syslog: 로그 기반 위협 탐지의 출발점 (0) | 2026.07.17 |