연결에 참여하는 사람과 자료를 받는 사람
도식의 네 역할은 자리를 옮기지 않습니다. 이동하는 자료와 각자 볼 수 있는 내용만 달라집니다.
잔액을 읽는 역할은 둘입니다
은행 Server는 응답을 만들고, 가입 신청자의 Prover는 그 응답을 읽습니다. 나머지 두 역할까지 잔액을 알 필요는 없습니다.
Prover(제출자)는 api.bank.example에서 받은 자료로 가입 조건을 제출합니다. Notary(공증 역할)는 TLS 세션의 공동 계산에 참여하고 Verifier(검증자)는 나중에 제출 자료를 받습니다. 여기서는 premium.example의 검증 서비스가 Verifier입니다.
본문은 세션 당시의 검사와 나중의 자료 검사를 분리하는 notarization 구성을 다룹니다. 별도 Notary 없이 애플리케이션 Verifier가 MPC-TLS에 직접 참여하는 구성도 있습니다.
네 이름은 조직의 개수가 아니라 서로 다른 역할을 가리킵니다.
두 연결을 구분해서 읽습니다
- Prover ↔ Server
- 실제 TLS 요청과 응답
- Prover ↔ Notary
- 암호 연산을 함께 수행
- Verifier
- 나중에 별도로 제출 자료 검사
Prover와 Server가 직접 TLS로 통신하고, Prover와 Notary는 별도로 공동 연산을 합니다. Notary는 응답 평문을 읽지 않습니다. Prover는 Notary 서명과 선택 공개 자료, 추가 ZKP를 Verifier에게 보냅니다. Verifier의 자료 검사와 서비스 가입 허용은 별개입니다.
역할별 책임과 공개 범위
| 역할 | 하는 일 | 이 사례의 대상 |
|---|---|---|
| Server | TLS 응답을 제공 | api.bank.example |
| Prover | 응답을 받고 제출 자료를 만듦 | 프리미엄 가입 신청자 |
| Notary | MPC-TLS에 참여하고 Session Header에 서명 | 일반 목적 공증 역할 |
| Verifier | 서명과 공개 내용을 검사하고 검증 결과를 서비스 정책 판단에 넘김 | premium.example 검증 서비스 |
Notary가 평문과 서버 이름을 보지 않는 방식
Notary는 TLS 계산에 참여하지만 commitment에 담긴 평문과 서버 식별 정보를 직접 알지 않도록 설계됩니다.
온라인 복호화에서는 Prover와 Notary가 각자의 키 지분으로 record 인증과 복호화 연산을 함께 수행합니다. 지연 복호화에서는 연결이 인증되고 닫힌 뒤 Notary가 키 지분을 공개하고, Prover가 저장한 응답 암호문을 로컬에서 복호화합니다. 연결 중에는 어느 한쪽의 키 지분만으로 전체 세션 키를 얻을 수 없습니다.
Notarization 단계에서도 Notary는 평문을 받아 읽고 서명하지 않습니다. Prover가 만든 평문 commitment와 서버 식별 자료 commitment를 담은 Session Header에 서명합니다.
| 받는 자료 | 직접 알 수 없는 내용 |
|---|---|
| MPC 키 지분, commitment | Authorization 헤더, 잔액 평문, 서버 이름 |
애플리케이션 Verifier가 세션에 직접 참여하는 방식
별도 Notary 없이 최종 Verifier가 Prover와 MPC-TLS를 수행하고 곧바로 공개 내용을 검사할 수 있습니다.
직접 방식에서는 세션 당시의 Verifier와 나중에 자료를 검사하는 Verifier가 같습니다. 일반 목적 Notary의 서명을 신뢰 목록과 대조하는 단계가 줄어듭니다.
대신 그 Verifier가 세션 시간에 온라인이어야 합니다. 제출 자료를 다른 서비스로 옮겨 쓰기도 본편의 notarization 흐름보다 어렵습니다.
- 01 Prover
- 02 직접 참여 Verifier
- 03 Server
- 04 검증
은행에 연결하기 전에 계산 범위를 정합니다
Prover와 Notary는 보낼 데이터와 받을 데이터의 한도를 맞추고 공동 계산을 준비합니다.
MPC(다자간 연산)는 각자의 비밀 입력을 공개하지 않고 함께 계산하는 방식입니다. 필요한 계산량을 미리 준비하므로 세션의 데이터 크기와 record 수 같은 한도를 정합니다.
로그인 자격 정보는 Prover에 남습니다. Notary는 은행 계정에 로그인하거나 잔액 조회를 대신하지 않습니다. Prover는 실제 연결 대상과 인증서 확인에 쓸 설정도 준비합니다.
세션 설정을 공유해도 은행 로그인 정보를 공유하는 것은 아닙니다.
은행 연결 전 준비
- 세션
trace_tlsn12_001- 함께 준비
- 데이터 한도와 공동 계산 자원
- Prover에 남음
- 은행 로그인 정보
Prover와 Server가 직접 TLS로 통신하고, Prover와 Notary는 별도로 공동 연산을 합니다. Notary는 응답 평문을 읽지 않습니다. Prover는 Notary 서명과 선택 공개 자료, 추가 ZKP를 Verifier에게 보냅니다. Verifier의 자료 검사와 서비스 가입 허용은 별개입니다.
세션 설정 예제
{
"sessionId": "trace_tlsn12_001",
"mode": "mpc",
"tlsVersion": "1.2",
"serverName": "api.bank.example",
"sentLimit": 4096,
"receivedLimit": 32768
}확인 날짜와 릴리스에 따라 달라지는 구현 정보
2026-09-09 확인: alpha.13에서 notary-server/client가 제거됐으며 tlsn-attestation은 유지보수 대상으로 남았습니다. 본문은 Notarization 개념 모델로, 현재 SDK의 실행 절차가 아닙니다. 관련 릴리스는 글 끝 기술 출처에 정리했습니다.
아래는 기존 원고의 2026-08-25 확인 기록입니다. “최신”이라는 표현도 당시 시점을 뜻합니다.
2026-08-25 공식 문서는 TLS 1.2 지원을 명시하고 TLS 1.3은 로드맵으로 둡니다. 최신 GitHub 릴리스는 사전 릴리스(pre-release)인 v0.1.0-alpha.15입니다.
앞 글이 설명한 TLS 1.3 메시지 흐름과 이 글의 TLSNotary 실행 예시는 같은 버전이 아닙니다. 그래서 세션 ID도 trace_tlsn12_001로 구분했습니다.
알파 릴리스의 자료 형식과 API는 바뀔 수 있습니다. 본문은 참여자와 데이터 흐름처럼 안정적인 개념만 다루고, 릴리스와 지원 버전은 이 심화 설명과 참고문헌에 확인 날짜를 함께 남깁니다.
| 항목 | 상태 |
|---|---|
| TLS 지원 | TLS 1.2 |
| TLS 1.3 | 로드맵 |
| GitHub 릴리스 | v0.1.0-alpha.15 (사전 릴리스) |
MPC 세션의 데이터 한도를 미리 잡는 이유
MPC 모드는 계산 자원을 미리 준비하므로 보내고 받을 데이터와 record의 최대치를 설정합니다.
한도는 애플리케이션 정책이 아니라 실행 자원 계획입니다. 응답이 예상보다 커지면 데이터가 거짓인 것이 아니라 준비한 세션 범위를 넘은 것입니다.
예제의 4 KiB 전송, 32 KiB 수신 값은 교육용 예시값입니다. 실제 배포 값은 대상 API 응답과 성능 측정을 보고 정합니다.
| 상태 | 의미 |
|---|---|
| 세션 한도 초과 | 실행 준비 범위 부족 |
| 판정 조건이 거짓 | 정해 둔 잔액 조건 불충족 |
은행 연결과 공동 계산은 별개입니다
Prover는 은행 Server와 TLS로 통신합니다. Notary와는 TLS 암호 연산을 함께 수행합니다.
연결 중에는 Prover와 Notary가 각각 키 지분을 보유합니다. 이렇게 키를 나누면 Prover가 전체 TLS 키를 혼자 확보해 서버 응답을 위조하지 못합니다. 요청은 평문을 비밀 입력으로 넣어 함께 암호화합니다. Notary가 평문을 받아 은행에 전달하는 구조가 아닙니다.
응답은 연결 중 공동 연산으로 복호화하거나 암호문을 보관했다가 세션 인증과 종료 후 Notary의 키 지분을 받아 Prover가 복호화합니다. 응답을 받는 쪽에서는 Prover만 잔액 72,840,000원을 읽습니다.
MPC-TLS는 Notary에게 평문과 서버 이름을 숨기도록 설계됩니다. 다만 세션 시간, 통신량, 왕복 횟수 같은 메타데이터까지 모두 숨기는 것은 아닙니다. 브라우저의 전송용 중계와 별도 proxy mode도 구분해야 합니다.
실제 TLS 통신은 가로선, 공동 계산은 세로선으로 구분합니다.
같은 응답, 다른 공개 범위
- Prover
- 72,840,000원
- Notary
- 평문과 서버 이름은 숨김
- 메타데이터
- 세션 시간과 통신량 등은 보일 수 있음
Prover와 Server가 직접 TLS로 통신하고, Prover와 Notary는 별도로 공동 연산을 합니다. Notary는 응답 평문을 읽지 않습니다. Prover는 Notary 서명과 선택 공개 자료, 추가 ZKP를 Verifier에게 보냅니다. Verifier의 자료 검사와 서비스 가입 허용은 별개입니다.
응답 예제와 참여자별 공개 범위
{
"AccountId": "acct_demo_7F21",
"Amount": { "Amount": "72840000.00", "Currency": "KRW", "SubType": "BCUR" },
"Type": "ITAV",
"DateTime": "2026-08-25T10:14:32+09:00"
}| 자료 | Server | Prover | Notary |
|---|---|---|---|
| 요청·응답 평문 | 자신이 처리함 | 봄 | 보지 않음 |
| MPC 내부 TLS 키 지분 | 모름 | 일부 | 일부 |
| 서버 이름 | 자신의 이름 | 앎 | 숨겨짐 |
MPC-TLS에서 메시지가 맡는 역할
세부 암호식 대신 키 지분 준비, 암호화 요청 생성, 응답 인증과 복호화의 순서를 봅니다.
Prover가 Server와 실제 소켓을 유지합니다. Notary는 그 소켓으로 들어온 TLS 메시지에 필요한 암호 연산을 Prover와 공동으로 수행합니다.
둘 중 한쪽이 가진 키 지분만으로는 전체 세션 키를 얻지 못합니다. 키 지분 분리와 공동 record 인증은 Prover가 임의 응답을 끼워 넣는 일과 Notary가 평문을 읽는 일을 각각 제한합니다.
- 01 키 지분
- 02 요청 암호화
- 03 서버 응답
- 04 인증
- 05 복호화
Proxy mode가 바꾸는 경로와 가정
Proxy mode에서는 Verifier가 암호화된 TLS 트래픽을 전달하고, 이후 ZKP로 관찰한 트래픽이 정상 TLS 세션에서 나온 것인지 검증합니다.
Verifier는 Prover와 Server 사이의 네트워크 proxy로서 암호화된 패킷을 전달하고 기록합니다. 평문을 직접 읽지는 않지만 Server로 가는 경로에 놓입니다.
MPC-TLS보다 대역폭과 검증 지연을 줄이는 대신 Verifier에서 Server까지의 네트워크 경로가 올바르다는 가정이 추가됩니다. 공식 문서도 MPC-TLS를 기본 모드로 둡니다.
| 항목 | MPC-TLS | Proxy mode |
|---|---|---|
| 온라인 역할 | 공동 TLS 암호 연산 | 암호화 트래픽 전달·기록 |
| 추가 가정 | MPC 보안 | Verifier–Server 네트워크 경로 |
| 공식 위치 | 기본·권장 | 대안 모드 |
서버 이름도 Notary에게 숨기는 이유
일반 목적 Notary가 어느 서비스에서 자료를 가져왔는지까지 알 필요가 없도록 서버 식별 정보(Server identity)도 commitment로 다룹니다.
은행 응답 본문을 숨겨도 접속한 도메인이 드러나면 민감한 서비스 이용 사실이 노출될 수 있습니다. TLSNotary의 notarization 흐름은 이 이름도 Notary에게 숨깁니다.
나중의 애플리케이션 Verifier에게는 서버 식별 정보와 이를 확인할 TLS 전용 자료(TLS-specific data)를 열어 출처를 검사하게 할 수 있습니다. 숨김 대상은 참여자마다 다릅니다.
- 01 서버 이름
- 02 commitment
- 03 Notary 서명
- 04 Verifier opening
Notary는 잔액 원문에 서명하지 않습니다
서명이 묶는 대상은 공동으로 확인한 세션과 그 통신 기록의 commitment입니다.
commitment는 값을 바로 공개하지 않고 고정해 두는 암호학적 결과입니다. Prover는 TLS 통신 기록과 서버 식별 자료를 commitment로 묶고 Notary는 이를 담은 자료에 서명합니다. 공식 개념 문서는 이 자료를 Session Header라고 부릅니다.
Notary는 서명할 때도 잔액 평문을 읽지 않습니다. 이 서명은 은행이 발급한 잔액 증명서나 가입 승인 서명이 아닙니다. 나중에 공개한 자료가 당시 세션에 묶여 있었는지 검사할 근거가 됩니다.
은행 응답, Notary 서명, 서비스 가입 허용은 서로 다른 결과입니다.
Session Header
- 고정한 자료
- 통신 기록 + 서버 식별 자료
- 서명자
- Notary
- 상태
- 서명 받음
Prover와 Server가 직접 TLS로 통신하고, Prover와 Notary는 별도로 공동 연산을 합니다. Notary는 응답 평문을 읽지 않습니다. Prover는 Notary 서명과 선택 공개 자료, 추가 ZKP를 Verifier에게 보냅니다. Verifier의 자료 검사와 서비스 가입 허용은 별개입니다.
Session Header에 무엇이 묶이는가
평문 commitment와 TLS-specific data commitment, Notary 서명이 이후 presentation의 기준점이 됩니다.
Session Header는 HTTP header가 아니라 TLSNotary가 정의한 자료 구조 이름입니다. Prover가 저장했다가 나중에 애플리케이션 Verifier에게 presentation의 일부로 보냅니다.
Verifier는 허용한 Notary인지 확인하는 정책 검사와 Session Header 서명 검증을 따로 수행합니다. 이어서 opening과 TLS-specific data가 Session Header 안의 commitment에 맞는지 검사합니다.
| 자료 | 역할 |
|---|---|
| commitment | 세션 당시 값을 숨긴 채 고정 |
| Notary signature | Notary가 Session Header에 서명했는지 확인 |
| opening | 나중에 선택한 범위가 commitment에 맞는지 확인할 자료 |
바이트 공개와 조건 증명을 나눕니다
Prover는 presentation(제출 자료)에 서명과 공개 범위, opening(확인 자료)을 묶습니다.
selective disclosure(선택 공개)는 통신 기록에서 고른 바이트만 보여 주는 기능입니다. 예를 들어 HTTP 맥락은 공개하고 Authorization 헤더와 계좌번호는 가릴 수 있습니다. 공개한 값이 commitment에 맞는지는 opening으로 확인합니다.
잔액까지 가린다고 “5,000만 원 이상”이라는 결과가 자동으로 생기지는 않습니다. 이 예제의 premiumEligible: true에는 같은 비공개 응답과 비교 조건을 묶는 별도의 영지식 증명(ZKP)이 필요합니다. ZKP에 사용한 값이 같은 비공개 응답에서 나왔다는 연결까지 확인해야 합니다.
선택 공개는 바이트를 고르는 기능이고, 숨긴 값의 조건 판정은 추가 작업입니다.
Verifier에게 보낼 내용
- 선택 공개
- HTTP 맥락 + 서명 + opening
- 추가 ZKP
premiumEligible: true- 잔액 원문
- 공개하지 않음
Prover와 Server가 직접 TLS로 통신하고, Prover와 Notary는 별도로 공동 연산을 합니다. Notary는 응답 평문을 읽지 않습니다. Prover는 Notary 서명과 선택 공개 자료, 추가 ZKP를 Verifier에게 보냅니다. Verifier의 자료 검사와 서비스 가입 허용은 별개입니다.
선택 공개와 추가 ZKP의 차이
| 기능 | Verifier가 얻는 것 | 이 사례에서의 역할 |
|---|---|---|
| TLSNotary 선택 공개 | 선택한 TLS 통신 기록 바이트와 출처 확인 자료 | 필요한 HTTP 맥락 공개 |
| 추가 ZKP | 숨긴 값에 대한 조건 결과 | premiumEligible: true |
premiumEligible를 만들 때 추가되는 ZKP
정확한 잔액을 열지 않고 비교 결과만 보이려면 TLS 통신 기록의 출처와 판정 조건 계산을 연결하는 별도 회로나 검증 절차가 필요합니다.
ZKP의 비공개 입력에는 원문 응답의 잔액과 이를 출처 commitment에 연결하는 증인값(witness)이 들어갈 수 있습니다. 공개 입력에는 기준 금액, 통화, 잔액 유형(balance type), challenge 같은 맥락을 둘 수 있습니다.
이 글은 실제 회로나 증명을 실행하지 않습니다. UI에서 premiumEligible가 만들어지는 장면은 어떤 관계를 추가로 증명해야 하는지 설명하는 교육용 모델입니다.
| 구분 | 예시 |
|---|---|
| 비공개 | 72,840,000.00, 응답 바이트 |
| 공개 | 50,000,000.00, KRW, ITAV, challenge_demo_001 |
| 결과 | premiumEligible: true |
Verifier는 받은 자료의 연결 관계를 검사합니다
서명이 맞는지뿐 아니라, 누가 서명했고 어느 서버의 어떤 자료에 관한 서명인지 확인합니다.
Verifier는 서비스가 허용한 Notary인지 확인하고 서명을 검증합니다. opening과 서버 식별 자료를 각각 commitment에 대조한 뒤, 확인된 서버 이름이 api.bank.example인지 검사합니다.
공개한 바이트는 HTTP·JSON 해석 규칙으로 읽습니다. 추가 ZKP도 같은 응답과 가입 조건에 묶였는지 확인해야 합니다. 자료가 여기까지 통과하면 verified 상태입니다. 서비스는 현재 시간과 가입 기준을 적용해 가입 허용 여부를 따로 판단합니다.
자료 검사에 성공했어도 서비스가 가입을 허용하지 않을 수 있습니다.
Verifier의 제출 자료 검사
- 허용한 Notary통과
- Notary 서명통과
- commitment와 opening통과
- 서버 식별 자료와 이름통과
- 응답 해석과 추가 ZKP통과
Prover와 Server가 직접 TLS로 통신하고, Prover와 Notary는 별도로 공동 연산을 합니다. Notary는 응답 평문을 읽지 않습니다. Prover는 Notary 서명과 선택 공개 자료, 추가 ZKP를 Verifier에게 보냅니다. Verifier의 자료 검사와 서비스 가입 허용은 별개입니다.
검사 순서와 가입 판단
- Notary가 서비스의 허용 목록에 있는지 확인
- Session Header의 Notary 서명을 검증
- opening이 commitment에 맞는지 검사
- 서버 식별 자료가 commitment와 맞는지 검사
- 서버 이름을 식별 자료와 대조
- 공개 HTTP·JSON과 추가 판정 조건 증명을 애플리케이션 규칙으로 검사
presentation을 어떤 순서로 검사하는가
허용한 Notary 정책, 서명, opening, 서버 식별 정보, JSON 해석, 판정 조건을 각각 다른 실패 원인으로 처리합니다.
Notary가 허용 목록에 있어도 서명이 틀리면 Session Header를 받아들이지 않습니다. 서명이 맞아도 opening이 commitment와 다르면 공개된 값은 세션에 묶이지 않습니다. opening이 맞아도 서버 식별 정보가 기대한 api.bank.example과 다르면 기대한 출처의 자료라고 확인할 수 없습니다.
암호 검사를 모두 통과한 뒤에야 HTTP와 JSON을 해석하고 premiumEligible를 서비스 정책에 넣습니다. 이 순서대로 결과를 기록하면 어느 검사에서 멈췄는지 알 수 있어, 오류를 한 덩어리의 “검증 실패”로 다루지 않아도 됩니다.
- 01 허용한 Notary
- 02 서명
- 03 opening
- 04 서버 식별 정보
- 05 JSON 해석
- 06 판정 조건
세 실패는 서로 다른 검사에서 멈춥니다
검사 결과를 원인별로 남기면, 허용 목록 정책과 암호학적 오류, 출처 조건의 문제를 구분할 수 있습니다.
허용 목록 밖의 Notary라면 서명 계산은 맞아도 서비스가 받아들이지 않습니다. commitment와 opening이 다르면 암호학적 검사 자체가 실패합니다. 다른 서버의 진짜 응답이라면 그 서버 자료로는 유효하더라도 api.bank.example이라는 출처 조건을 충족하지 못합니다.
Notary를 별도로 두는 구성에서는 Verifier가 그 Notary의 세션 검사와 운영을 받아들인다는 가정도 남습니다. 서명이 있다는 사실만으로 이 가정이 사라지지는 않습니다.
실패한 검사와 적용한 정책을 구분해 거절 이유를 남깁니다.
독립적인 실패 사례
- 허용 목록 밖의 Notary 서명은 맞아도 서비스가 받아들이지 않습니다.
- opening 불일치 공개 자료가 commitment와 맞지 않습니다.
- 다른 서버의 응답 진짜 응답이어도 요구한 은행의 자료가 아닙니다.
Prover와 Server가 직접 TLS로 통신하고, Prover와 Notary는 별도로 공동 연산을 합니다. Notary는 응답 평문을 읽지 않습니다. Prover는 Notary 서명과 선택 공개 자료, 추가 ZKP를 Verifier에게 보냅니다. Verifier의 자료 검사와 서비스 가입 허용은 별개입니다.
전체 공개 범위와 실패 비교
| 역할 | 보는 것 | 만드는 것 | 검사하는 것 |
|---|---|---|---|
| Server | 요청과 자신의 응답 | TLS 응답 | 일반 TLS 요청 |
| Prover | 전체 평문과 자신의 비밀 | commitment, presentation, 추가 ZKP | Notary가 올바르게 참여했는지 |
| Notary | MPC 내부 TLS 키 지분과 commitment | 서명된 Session Header | TLS 세션의 공동 계산 |
| Verifier | 선택 공개 내용과 premiumEligible | 검증 결과 | 서명, opening, 서버 이름, 조건 |
| 실패 | 제출 자료 검사 | 정책 판단 | 결과 |
|---|---|---|---|
| 신뢰 목록 밖의 Notary | 서명 계산은 맞을 수 있음 | 운영상 신뢰하지 않음 | 정책 거절 |
| commitment와 opening 불일치 | 검사 실패 | 진입하지 않음 | 암호 검사 거절 |
| 서버 이름이 api.bank.example이 아님 | api.bank.example의 자료라고 확인할 수 없음 | 출처 조건 불충족 | 서버 출처 검사 거절 |
세 가지 실패를 참여자별 표에서 다시 보기
서명 계산, commitment 결합, 서버 식별 정보, 서비스 신뢰 목록이 서로 다른 검사임을 짧게 비교합니다.
Notary가 허용 목록 밖에 있어도 서명 계산 자체는 맞을 수 있습니다. 서명 검증과 별개로 premium.example이 그 운영자를 세션 검증자로 받아들이지 않는다는 정책 결정입니다.
commitment 불일치와 잘못된 서버 식별 정보는 제출 자료가 해당 세션·출처에 결합됐음을 확인할 수 없게 합니다. 같은 거절 화면을 보여 주더라도 내부 원인은 구분해서 기록해야 합니다.
| 원인 | 먼저 판단하는 주체 | 분류 |
|---|---|---|
| Notary가 허용 목록 밖 | 서비스 정책 | 정책 거절 |
| opening 불일치 | 암호 검증기 | 암호 검사 거절 |
| 서버 식별 정보 불일치 | 출처 검사 | 서버 출처 검사 거절 |