프로토콜 데모 P-256 ECDH → SHA-256 → AES-128-CBC 4부작 중 2부 · 클라이언트 응답

DID Auth: 클라이언트

ECDH 기반 챌린지-응답의 클라이언트 쪽. 서버의 nonce에 답하는 MAC을 계산한다.

프로토콜 설명용 예제이며 실서비스에서 사용하지 마십시오. 표시된 키는 공개 데모 키입니다.

앱에서 열기 .ncw 내려받기

DID Auth: 클라이언트

개요 및 암호학적 배경

이 워크플로우는 4부작 DID Auth 학습 모음의 2부입니다(키쌍 → 클라이언트 → 서버 → 종단 간 데모). ECDH 챌린지-응답 인증 프로토콜의 클라이언트 쪽을 모델링합니다. 서버가 자신의 P-256 공개키와 32바이트 챌린지 Nonce를 보내면, 클라이언트는 개인키를 전송하지 않고도 DID 문서의 공개키에 해당하는 개인키를 가지고 있음을 증명해야 합니다.

클라이언트는 P-256 ECDH 공유 비밀 Z(raw_x, 32 B)를 계산하고, D = SHA-256(Z)(32 B)를 구합니다. D를 16바이트 AES-128 키(D[0..16])와 16바이트 IV(D[16..32])로 나누고, 32바이트 챌린지 nonce를 AES-128-CBC(Padding = None)로 암호화합니다. 마지막 16바이트 암호문 블록의 앞 8바이트(offset = -16, length = 8)를 8바이트 응답 MAC으로 꺼냅니다.

파이프라인 배선 구조와 단계별 흐름

ECDH (P-256) ──► SHA-256 (32B) ──► Byte Slicer (Key 16B / IV 16B) ──► AES-128-CBC (Nonce 32B) ──► Byte Slicer (MAC 8B)
  1. 공유 비밀 합의(ECDH Key Agreement): Client Private Key(32 B)와 Server Public Key(65 B)를 곡선 p256에서 결합해 32바이트 X 좌표를 출력합니다.
  2. 키와 IV 분할(Cryptographic Hash + Byte Slicer × 2): 공유 비밀을 SHA-256으로 해시하고, 바이트 0..16을 Key로, 바이트 16..32를 IV로 자릅니다.
  3. 챌린지 암호화와 절단(AES Encrypt + Byte Slicer): 32바이트 Nonce를 CBC 모드(Padding = None)로 암호화하고, 마지막 암호문 블록의 시작에서 8바이트(offset = -16, length = 8)를 잘라 Client Public Key와 함께 MAC으로 내보냅니다.

노드 구성 및 설정

노드역할과 주요 매개변수개수
Workflow InputClient Private Key, Client Public Key, Server Public Key, Nonce 공급1
ECDH Key Agreementcurve = "p256", format = "raw_x"(32바이트 공유 비밀)1
Cryptographic Hashalgorithm = "SHA-256"1
Byte Slicer세 인스턴스: Key(0, 16), IV(16, 16), MAC(-16, 8)3
AES Encrypt이름 AES-128-CBC. mode = "CBC", padding = "None"으로 설정1
Workflow OutputClient Public Key(65 B)와 MAC(8 B) 출력1

노드 레퍼런스 →

입출력 명세 및 시험 벡터 검증

검증 출처: independent implementation: Node crypto (reference/did-auth/did-auth.mjs), no published vector

공개된 시험 벡터가 없어, Node crypto로 작성한 독립 구현(reference/did-auth/did-auth.mjs)과 결과를 대조했습니다.

입력

이름타입값 (Hex)
Client Private Keybytes (32 B)2ad39d172118c0802359e6806b8939881b6a3fbcc9e89e307499a862acd4e3c9
Client Public Keybytes (65 B)0415dc193b8e2a688d603303e85ec8fcc15dcba44ef2156a128c386b66b4f5e1d2188e7ca9d0385c02e72c6899f2771e86bb017a2d2903d89a2892c2199aec8f4d
Server Public Keybytes (65 B)0447edf45c2c402ae4cfe8460fb208fbc0d6af18efa4b3d78d44c73fcb0c250ec08222f152af03468af65a74fbf89ecc763f19b0dadec5fd8df5cf76d7da097ae5
Noncebytes (32 B)000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f

기대 출력

이름타입값 (Hex)
Client Public Keybytes (65 B)0415dc193b8e2a688d603303e85ec8fcc15dcba44ef2156a128c386b66b4f5e1d2188e7ca9d0385c02e72c6899f2771e86bb017a2d2903d89a2892c2199aec8f4d
MACbytes (8 B)39b415c1dfeb8f52