DID 기술을 활용한 

전자 문서 위변조 방지 및 검증 솔루션 개발기

by Engineering Team

들어가며: 왜 이 프로젝트를 시작했나요?


안녕하세요! 하이어다이버시티 Engineering 팀입니다. 👋 


오늘은 저희 팀이 최근 2주 동안 치열하게 달려왔던 DID(Decentralized Identity, 탈중앙화 신원 증명) PoC 프로젝트에 대한 이야기를 들려드리려고 합니다.


저희 회사는 "외국인 유학생 통합 솔루션"을 개발하고 있는데요. 외국인 유학생들이 한국에서 겪는 가장 큰 어려움 중 하나가 바로 각종 '증명'입니다. 


"나 이 학교 다녀요", "나 졸업했어요" 같은 사실을 증명하기 위해 수많은 종이 서류를 떼고, 공증을 받고, 제출해야 하죠.

"이 과정을 디지털로, 그것도 아주 안전하고 저렴하게 자동화할 수는 없을까?" 이 질문이 이번 프로젝트의 시작점이었습니다. 


우리는 DID 기술을 통해 전자 문서의 위변조를 방지하고 검증하는 솔루션을 만들어보기로 했습니다.

DID가 뭔가요? (순한 맛 설명 🌶️)


기술적인 내용으로 들어가기 전에, DID가 도대체 기존 방식과 뭐가 다른지 확실히 짚고 넘어갈게요. 핵심은 "내 정보의 주도권을 누가 쥐고 있는가"입니다.

CID vs DID: "맡겨둘 것인가, 소유할 것인가"


우리가 지금껏 당연하게 써왔던 아이디/비밀번호 방식, 혹은 공인인증서 방식은 모두 CID(Centralized Identity, 중앙화된 신원)에 해당합니다.


CID 세상에서 우리는 정보의 '주인'이라기보다 '이용자'에 가깝습니다.


  • 모든 정보는 '중앙' 금고에: 내 개인정보와 각종 증명서 원본이 정부 기관, 은행, 혹은 네이버나 구글 같은 거대 기업의 서버(중앙)에 깊숙이 보관되어 있습니다.

  • 주도권의 부재: 정작 내 정보인데도 내가 마음대로 옮기거나 관리할 수 없어요. 내 정보를 쓰려면 매번 그 중앙 서버에 접속해서 "저 맞아요, 문 좀 열어주세요" 하고 허락을 받아야 하죠.

  • 파편화된 검증(Silo): 더 큰 문제는 검증이에요. 대학 졸업 증명은 대학 서버가, 재직 증명은 회사 서버가 각자 제각각의 방식으로 검증해요. 서로 호환이 안 되니 증명서가 필요할 때마다 각 기관 사이트를 일일이 찾아다녀야 하는 번거로움이 있었죠.

반면 DID(Decentralized Identity)는 이 정보의 주권을 온전히 '나'에게로 가져오는 기술입니다.

  • 발급(Issue): 학교에서 졸업증명서를 받으면, 학교 서버가 아니라 내 스마트폰(전자지갑)에 저장 됩니다.

  • 보관(Hold) & 통제: 내 폰 안에 디지털 금고가 생기는 셈이죠. 누구에게 내 정보를 보여줄지, 언제까지 보여줄지 내가 직접 결정하고 통제합니다.

  • 표준화된 검증(Verify): 어떤 기관에서 발급받았든, 표준화된 방식을 통해 전 세계 어디서나 안전하게 검증할 수 있습니다.

쉽게 말해, DID는 중앙 기관에 맡겨놨던 내 디지털 인감도장과 문서를 되찾아와서, "내가 직접 관리하는 디지털 지갑”을 만드는 기술이라고 보시면 됩니다.

우리가 만든 PoC: "한국대학교에서 순양그룹까지"


이번 PoC의 목표는 "발급(Issuer) - 지갑(Wallet) - 검증(Verifier)"으로 이어지는 전체 사이클을 실제로 구현해보는 것이었습니다.

🏛️ 시나리오: W씨와 E씨의 입사 지원기


이해를 돕기 위해 구체적인 시나리오를 만들었습니다.

  1. 가상의 사용자(W씨, E씨)는 스마트폰에 'HireVisa 월렛(Wallet App)'을 설치합니다.

  2. 본인의 출신 대학인 '한국대학교(가상의 발급자, Issuer)' 웹사이트에 접속해 졸업증명서를 발급받아 지갑에 저장합니다.

  3. 이 때, 발급자가 정말로 한국대학교에서 발급한 문서인지 검증 할 수 있습니다.

  4. 입사를 희망하는 '순양그룹(가상의 검증자, Verifier)' 채용 사이트에 접속합니다.

  5. "DID로 지원하기" 버튼을 누르면 지갑 앱이 열리고, 저장해 둔 졸업증명서를 순양그룹에 제출합니다.

  6. 순양그룹은 제출된 문서가 진짜 한국대학교에서 발행된 것인지 현재도 유효한 문서인지 1초도 안돼서 검증합니다.

  7. 내가 스마트폰을 잃어버리더라도 HireVisa 앱에서 본인을 증명하면 기존의 HireVisa 월렛앱에 저장된 모든 문서를 안전하게 파기할 수 있습니다.

  8. Issuer 는 발급된 문서에 대해서 무효화 시킬 수 있습니다. (가령 졸업 후에 성적 정보가 변경되었는데, 기존에 발급된 성적증명서를 무효화 시킬 수 있습니다.)

🛠️ 구현 범위 및 기술 스택

이 시나리오를 위해 저희는 총 4가지 컴포넌트를 개발했습니다.

  1. Wallet App: 사용자의 스마트폰 앱. did:key를 생성하고 생체 인증(Bio-auth)으로 보호합니다.

  2. Wallet Provider Backend: 지갑의 백업, 분실 처리, 1인 1지갑 정책을 관리합니다.

  3. Mock Issuer (한국대학교): OID4VC 표준에 따라 VC(Verifiable Credential)를 발급합니다.

  4. Mock Verifier (순양그룹): OID4VP 표준에 따라 VP(Verifiable Presentation)를 받고 검증합니다.

기술 Deep Dive: 어떻게 검증하나요? (매운 맛 🌶️🌶️)


"그냥 이미지 파일 보내는 거랑 뭐가 달라요?" 이 질문에 엔지니어답게 대답하려면, 암호화 서명(Cryptographic Signature)과 신뢰의 앵커(Trust Anchor)가 어떻게 연결되는지 파고들어야 합니다.

DID는 하나가 아니다: did:key vs did:web


DID를 구현하는 방법(Method)은 수십 가지가 넘는데, 저희는 PoC의 효율성을 위해 두 가지 방식을 혼용했습니다.

  • Holder(사용자)did:key: 별도의 서버나 블록체인 등록 없이, 로컬에서 생성된 키 쌍(Key Pair)만으로 즉시 ID를 만들 수 있습니다. 사용자의 익명성과 편의성을 위해 선택했죠. did:key이 키 쌍의 공개키(Public Key)를 기반으로 식별자(ID)가 만들어진다고 생각하면 됩니다. 덕분에 중앙 저장소 없이도 즉시 지갑을 생성하고 사용할 수 있어, 사용자의 익명성과 편의성에 최적화된 방식입니다. did:key:z6Mkh… 와 같이 did:key 다음에 공개키가 인코딩 되어서 유일한 주소를 만들어내는 방식이라 생각하면 됩니다.

  • Issuer(발급기관)did:web: 반면, '한국대학교' 같은 기관은 누구나 알 수 있는 신뢰의 앵커가 필요합니다. 그래서 기존 웹의 도메인(DNS) 주소를 ID로 활용하는 did:web 방식을 채택했습니다. 사람이 읽을 수 있는 도메인이 포함되므로 신뢰하기 쉽습니다. 즉, 발급기관에 hankook.ac.kr 도메인을 갖고 있다면 did:web:hankook.ac.kr 과 같은 형식으로 표현됩니다.

발급(Issuance): OID4VC와 PKI의 만남


사용자가 졸업증명서를 발급받아 내 폰에 저장하고 검증하기까지, 내부에서는 이런 일이 벌어집니다.

  • OID4VC 프로토콜을 통한 발급 요청: 먼저 Wallet은 OID4VC(OpenID for Verifiable Credential) 표준 프로토콜을 이용해 Issuer에게 VC(Verifiable Credential) 발급을 요청합니다. 이때 사용자는 본인 인증을 거칩니다. VC 는 다음과 같은 형식의 json 텍스트 입니다.

  • Issuer의 개인키(Private Key) 서명: 한국대학교(Issuer) 서버는 졸업증명서 데이터(JSON)를 만든 뒤, 자신이 관리하는 비공개 개인키(Private Key)로 이 데이터에 전자 서명을 합니다. 이 서명은 한국대학교 외에는 누구도 만들 수 없습니다.

  • 공개키(Public Key) 디스커버리 (did.json): 이제 검증의 시간입니다. 도대체 이 서명이 진짜 한국대학교 것인지 어떻게 알까요? 여기서 did:web의 마법이 일어납니다. 검증 로직은 한국대학교의 DID 식별자(did:web:hankook.ac.kr)를 보고, 약속된 경로인 https://hankook.ac.kr/.well-known/did.json으로 접속해 공개키(Public Key)를 가져옵니다. did.json 파일은 다음과 같은 구조를 갖고 있습니다.


  • PKI 위에서 완성되는 신뢰: 이 지점이 핵심입니다. 저 did.json 파일 자체가 해커가 심어둔 가짜면 어떡하냐?"라는 의문이 들 수 있죠. 하지만 우리는 이미 웹 브라우저를 통해 HTTPS(TLS/SSL) 인증서 체인을 신뢰하고 있습니다. 즉, 기존 Web2의 PKI(공개키 기반 구조) 신뢰망을 통해 "이 도메인은 진짜 한국대학교 소유임"을 보장받고, 그 위에 Web3의 DID 서명 검증을 얹는 구조입니다.

  • 최종 검증 (Verify): 마지막으로 암호화 검증 알고리즘을 수행합니다. 단순히 복호화해서 비교하는 것이 아니라, 서명 검증 함수를 통해 수학적 증명을 거칩니다.

"이 문서의 서명값(Signature)이, 방금 did.json에서 가져온 공개키와 쌍(Pair)을 이루는 비밀키로 생성된 것이 맞는가?"

검증 알고리즘이 이 질문에 대해 True를 반환한다면, 해당 문서는 hankook.ac.kr 도메인 소유주(Issuer)만이 서명할 수 있는 진짜 문서임이 증명되는 것입니다.

참고로 ODI4VC 프로토콜을 이용해서 어떻게 Issuer 와 Wallet App 이 통신하는지의 모습을 살짝 들여다보면 아래와 같은 약속을 이용해서 정보를 주고 받게 됩니다.

검증(Verification): OID4VP와 무결성 체크


순양그룹(Verifier)이 문서를 검증할 때도, 단순히 눈으로 보는 것이 아니라 OID4VP(OpenID for Verifiable Presentation) 표준에 따라 빡빡한 검증 로직이 돌아갑니다.


  • VP(Verifiable Presentation) 제출: 사용자의 지갑은 단순히 VC만 던지는 게 아니라, "이 VC 내 거야!"라는 것을 증명하기 위해 VC를 감싸서 지갑의 개인키로 한 번 더 서명한 VP를 제출합니다. VP 는 VC 를 포함하고 이를 다시 서명한 문서 입니다. VC 와 마찬가지로 Json 텍스트 형식을 갖습니다.


  • Holder 검증: Verifier는 먼저 VP의 서명을 확인하여, 제출자가 지갑의 실제 소유자인지 확인합니다.

  • Issuer 서명 검증 (Chain of Trust): 그 안의 VC를 꺼내, 앞서 설명한 did:web 리졸빙(Resolving) 과정을 통해 한국대학교의 공개키를 가져와 서명을 검증합니다. 단 1비트라도 데이터가 변조되었다면 이 과정에서 즉시 Fail이 뜹니다.

  • 상태(Status) 검증: 서명이 맞아도, 이미 취소된 졸업장일 수 있습니다. Verifier는 Issuer가 게시한 Revocation Registry(폐기 목록)의 비트스트링(Bitstring)을 조회하여 현재 유효한 문서인지 최종 확인합니다.


이 모든 과정이 사용자가 "제출" 버튼을 누르는 순간, 1초 내에 백그라운드에서 완료됩니다.

[보너스 트랙] 이미 발급된 문서를 폐기하고 싶다면? (Revocation)


잠깐, 여기서 예리한 분들은 의문이 드실 겁니다.

"만약 W씨가 한국대학교를 다니다가 자퇴를 했거나, 

부정행위로 입학이 취소됐다면요? 

이미 W씨 폰에 저장된 졸업증명서를 한국대학교가 원격으로 지울 수는 없잖아요?"

맞습니다. DID는 중앙 서버가 없기에 사용자 폰에 있는 데이터를 강제로 삭제할 수는 없습니다. 대신, "이 문서는 더 이상 유효하지 않음"이라고 공표하는 방식(Revocation)을 사용합니다.


  • 전광판 (Bitstring Status List): Issuer(한국대학교)는 서버에 아주 긴~ 0과 1로 된 문자열(Bitstring)을 게시해 둡니다. 이를 Status List라고 합니다.(위에 VC 의 내용에 있는 credentialStatus 항목이 바로 이 내용입니다) VC를 발급할 때, W씨의 졸업증명서에는 "너는 이 전광판의 50번째 칸을 확인해봐"라는 정보(credentialStatus)가 심어져 있습니다.
    • 평소 상태: 000000...0... (모두 유효함)


  • 킬 스위치 작동 (Revoke): 만약 W씨의 증명서를 정지시켜야 한다면, 한국대학교는 50번째 비트를 0에서 1로 바꿉니다.
    • 폐기 후 상태: 000000...1... (50번째 문서 폐기됨!)

  • 검증 시점의 확인: 나중에 순양그룹(Verifier)이 W씨의 문서를 검증할 때, 앞서 설명한 서명 검증이 다 통과되더라도 마지막으로 이 Status List를 다운로드합니다. 그리고 50번째 칸을 딱 확인하죠.


"어? 50번째 비트가 1이네? 서명은 맞지만 이 문서는 폐기되었군."


이 방식의 장점은 프라이버시입니다. 순양그룹은 "50번째 문서가 폐기됐다"는 사실만 알 뿐, 그게 W씨인지 E씨인지, 왜 폐기됐는지는 리스트만 봐선 알 수 없거든요. 아주 효율적이고 스마트한 방식이죠?

DID로 할 수 '없는' 것들 (현실적인 한계)

기술 블로그인 만큼 솔직한 이야기도 담아야겠죠? DID는 만능열쇠가 아닙니다. PoC를 통해 알게 된 명확한 한계점들도 있습니다.


  • 도메인 소유 증명: hankook.ac.kr이라는 도메인이 실제로 '한국대학교' 소유인지 DID가 증명해주진 않아요. 이건 기존의 DNS와 공인인증(CA)의 영역입니다.

  • 자연인 특정: 지갑의 주인(Key 소유자)이 현실 세계의 '홍길동'인지는 DID 기술만으로 알 수 없어요. 이건 Wallet Provider(HireVisa Wallet App 이라면 Hirediversity 가 되겠죠)가 KYC(신원확인)를 통해 보증해줘야 하는 역할입니다.

  • 내용의 진실성(Oracle Problem): DID는 "누가 서명했는가"는 완벽히 증명하지만, "그 내용이 사실인가"는 판단하지 못해요. 학교가 실수로 학점을 잘못 입력해서 발급했다면, DID는 그 잘못된 정보를 '안전하게' 전달할 뿐입니다. 이는 CID 생태계에서도 마찬가지로 발생할 수 있는 문제 입니다.

결국 DID 기술 도입만으로 모든 신뢰 문제가 해결되는 것은 아닙니다. 저희 하이어다이버시티는 이러한 DID의 기술적 공백을 메우기 위해, 기존 레거시 시스템의 검증 절차를 Wallet 서비스에 어떻게 효과적으로 녹여낼지 다양한 기술적 시도를 하고 있습니다.

마치며: AI와 함께한 2주간의 여정

놀랍게도 이 모든 과정—기술 검토, 시나리오 기획, 아키텍처 설계, 앱/서버 개발까지—을 DID 배경지식이 전혀 없던 모바일 엔지니어 2명이서 단 2주 만에 해냈습니다.

비결이 뭐냐구요? 바로 하이어다이버시티의 AI 친화적인 개발 문화 덕분입니다. 저희는 ChatGPT, Claude, Cursor 같은 AI 도구를 적극적으로 활용했어요. 난해한 OID4VC/VP 표준 문서를 AI에게 학습시켜 요약받고, 복잡한 암호화 로직의 보일러플레이트 코드를 생성하며 학습 속도를 비약적으로 단축시켰죠.

물론 100% AI가 다 해준 건 아닙니다. 하지만 AI 덕분에 초기 기술 습득 시간을 대폭 줄이고, 핵심 로직과 비즈니스 가치에 집중할 수 있었던 소중한 경험이었습니다.

앞으로 이 기술을 바탕으로 외국인 유학생들이 집을 구하거나(부동산), 알바를 구할 때(취업) 겪는 신원 증명의 불편함을 하나씩 해결해 나가려 합니다. 저희의 여정을 지켜봐 주세요! 🚀