DID(분산 신원 인증) 도입기

진병욱·2024년 7월 11일
1

개발 일지

목록 보기
3/3
post-thumbnail

작년 SSAFY에서 블록체인 프로젝트를 진행하며, 저희 팀이 DID 서비스를 프로젝트 적용하며 겪었던 어려움과 해결 과정에 대해서 이야기하려 합니다.
DID와 블록체인을 잘 알지 못하더라도 최대한 이해할 수 있도록 작성했습니다.
혹시 DID를 프로젝트에 적용하려고 하는 분들이 있다면 그 분들에게도 도움이 되길 바라며...

DID란?

먼저 DID에 대해 설명하자면, Decentralized Identity(분산 신원 증명)의 약자입니다.

현재의 신원 증명 시스템은, 국가를 통해 발급 받은 특정 문서를 통해서 신원을 증명합니다.
이후 신원 증명이 필요한 경우 특정 주체(국가, 민간)를 통해 개인 정보를 제공합니다.
따라서 개인은 해당 개인 정보에 대해 관리할 수 없습니다.

이러한 개념에 반해서 등장한 개념이 바로 DID입니다.

이미지 출처 : https://medium.com/proofer-tech/proofer-유즈케이스-신원증명-블록체인-기반-신원증명-did의-보안성과-한계-part-1-82daed18b7aa

DID는 신원 증명을 통해 VC(Verifiable Credential)를 발급 받고, 이후에 신원 인증이 필요한 경우 필요한 정보를 담아 VP(Verifiable Presentation)를 해당 주체에게 제공하는 방식입니다.

개인정보를 제공하는 주체가 단체에서 개인으로 변경된 것입니다.

관련해서 궁금한 내용은 아래 링크에서 잘 설명하고 있는 것 같아 첨부합니다.
https://www.apple-economy.com/news/articleView.html?idxno=63760

본격적인 DID 도입기

그럼 왜 DID를 사용하려 했는가?

NFT 거래 플랫폼을 구상하던 와중에, 담당 컨설턴트님께서 미래 지향적 플랫폼을 만드는 것은 어떨 것 같은지 의견을 주셨습니다.

팀원들간에 여러 이야기가 오고 갔고, DID 도입에 관해 이야기를 꺼내게 되었습니다.
블록체인을 통해 상품을 만들어 거래를 하고, 그 과정에서의 인증또한 블록체인을 통해 이루어짐으로서 모든 과정이 블록체인에서 벌어지는 것이 미래 사회의 모습이지 않을까하는 생각이 들었기 때문입니다.

물론 겁은 났습니다. DID라 함은 블록체인 내에서도 딥한 기술이기에 우리가 해낼 수 있을까?
하지만 컨설턴트님께서는 이전 기수에서도 구현했던 적이 있기 때문에 충분히 할 수 있을 것이라고 말씀해주셨고, 팀 내에서도 DID 서비스 구현을 확정지었습니다.

역시 쉽지 않군...

먼저 DID를 도입하기 위해, 자료 조사를 시작했습니다.
개념부터 구조, 사용사례 등

하지만 그 어디에서도 DID 구현에 대한 이야기를 찾을 수 없었습니다.
사실 어찌보면 당연한 이야기입니다.

신원 증명이라는 보안과 기술력을 필요로 하는 시스템으로 구 자체가 곧 자산인 시장에서 찾기는 쉽지 않았습니다.

블록체인 전문가분께 여쭤보니, 팀원들 중에서도 DID쪽을 겪어본 사람이 없다며 대신 참고할 수 있는 레퍼런스들을 주시면 최대한 도움을 주시려고 했지만 아쉽게도 큰 도움이 되지는 못했습니다.. ㅜㅜ 😂😂
(하지만 최선을 다해서 도와주셔서 감사했습니다 꾸벅)

그렇게 포기해야 하나 싶던 와중에 이전 기수에서 구현한 적이 있다는 이야기가 떠 오르게 되었습니다.
그렇게 깃허브를 뒤지게 되었고 컨설턴트님께 들었던 DID 구현 팀으로 추정되는 깃허브를 발견하게 되었습니다.

하늘이 무너져도 솟아날 구멍은 있다!!

그렇게 발견한 깃허브를 담당 프론트엔드 팀원과 함께 샅샅이 파헤치기 시작했습니다.
이 팀은 왜 DID를 사용하려 했고, 어떤 구조를 통해 어떻게 사용했는지

그 결과, Javascript 라이브러리를 발견할 수 있었습니다.

did-jwt 라이브러리

https://github.com/decentralized-identity/did-jwt
https://github.com/decentralized-identity/did-jwt-vc

이름에서도 알 수 있듯이 jwt를 통해 DID 인증을 지원하고 있습니다.
먼저 issuer를 통해 did document를 발급받고 이를 통해 VC와 VP를 jwt 형태로 제공하고
사용자는 이를 사용합니다. 여기서 발급되는 jwt를 신분증이라고 생각하면 편합니다.

이슈어 생성, vc 생성, vp 생성, vp 인증과 같은 핵심 메소드를 살펴보겠습니다.
공식 라이브러리를 들어가보면 예제를 확인 할 수 있습니다.

이슈어 생성

import { EthrDID } from 'ethr-did'
import { Issuer } from 'did-jwt-vc'

const issuer = new EthrDID({
  identifier: '지갑 주소',
  privateKey: '프라이빗 키'
}) as Issuer

VC, VP 발급을 담당할 이슈어(인증기관)를 생성합니다.

VC 생성

import { JwtCredentialPayload, createVerifiableCredentialJwt } from 'did-jwt-vc'

const vcPayload: JwtCredentialPayload = {
  sub: 'did:ethr:{발급받고자 하는 사용자의 지갑 주소}',
  nbf: 1562950282, // 발급일자
  vc: {
    '@context': ['https://www.w3.org/2018/credentials/v1'],
    type: ['VerifiableCredential'],
    credentialSubject: {
      // 들어갈 데이터
      degree: {
        type: 'BachelorDegree',
        name: 'Baccalauréat en musiques numériques'
      }
    }
  }
}

const vcJwt = await createVerifiableCredentialJwt(vcPayload, issuer) // VC 발급
console.log(vcJwt)

사용자의 지갑 주소와 들어갈 데이터를 통해 vcPayload를 생성하고, 이슈어를 통해 최종적으로 vcJwt를 생성합니다.

VP 생성

import { JwtPresentationPayload, createVerifiablePresentationJwt } from 'did-jwt-vc'

const vpPayload: JwtPresentationPayload = {
  vp: {
    '@context': ['https://www.w3.org/2018/credentials/v1'],
    type: ['VerifiablePresentation'],
    verifiableCredential: [vcJwt] // 기존에 발급 받은 vcJwt
  }
}

const vpJwt = await createVerifiablePresentationJwt(vpPayload, issuer) // VP 발급

발급받았던 vcJwt를 통해 vpJwt를 발급합니다.

VC 및 VP 인증

import { verifyCredential, verifyPresentation } from 'did-jwt-vc'

const verifiedVC = await verifyCredential(vcJwt, resolver) // VC 인증
const verifiedVP = await verifyPresentation(vpJwt, resolver) // VP 인증

VC인증과 VP 인증을 resolver를 통해 받습니다.
여기서 나온 resolver는 아래에서 자세히 설명하도록 하겠습니다.

도입 과정

DID를 구현하기 위해서 딱 네가지가 필요합니다.
사용자 지갑, 이슈어 지갑, 블록체인 네트워크, DID document 배포 주소 (스마트 컨트랙트 주소)

지갑 준비


https://metamask.io/
지갑은 MetaMask라는 크롬 확장 프로그램을 통해 아주 쉽게 생성이 가능합니다.
만약 기존에 지갑을 가지고 있다면 추가도 가능합니다.

블록체인 네트워크

네트워크의 경우 사용중인 블록체인 네트워크가 있다면 사용하면 되고
그렇지 않으면 테스트넷을 사용하면 됩니다.

블록체인의 네트워크는 메인넷과 테스트넷으로 구분됩니다.
메인넷의 경우 말 그대로 블록체인 내의 메인 네트워크로 기본 활동들이 이루어지는 곳입니다.
테스트넷은 테스트를 위해 사용되는 네트워크로써 테스트넷 내에서의 활동은 메인넷에 영향을 미치지 않습니다.

그리고 블록체인의 종류를 골라야합니다.

https://www.kakaocorp.com/page/detail/537
클레이튼은 카카오에서 만든 퍼블릭 블록체인입니다.
이더리움과는 전혀 다른 블록체인이지만 클레이튼은 이더리움을 기반으로 만들어졌고 많은 부분에서 호환됩니다.

장점으로는 한글로된 공식문서를 제공하지만, 이더리움에 비해 주류에 속하지 않기에
저희는 블록체인을 처음 경험하기 때문에 기초가 되는 이더리움을 선택하였습니다.

이더리움 내에 여러 테스트넷이 존재하지만 저희는 Sepolia를 선택하였습니다.
대부분의 사용법이 비슷하기에 팀에 따라서 선택하면 될 것 같습니다.

MetaMask 연결하기

설정 > 네트워크에서 Sepolia 테스트 네트워크 선택

만약 없다면, 수동으로 아래 내용을 추가하면 됩니다.

https://www.infura.io/
이후 infura 공식 홈페이지에 접속해서 API를 발급받아 v3뒤에 넣어주면 됩니다.

스마트 컨트랙트

블록체인 내에서의 계약을 의미, 법적으로 구속력을 가집니다. 이를 통해 블록체인으로 여러 활동이 가능합니다.

DID에서 스마트 컨트랙트가 등장한 이유는, DID Document를 통해 VC와 VP의 소유권을 증명하기 때문입니다.

Issuer(인증 기관)는 DID Document를 블록체인 네트워크에 발행합니다. 이후에 사용자의 DID(VC or VP)가 해당 인증 기관에서 발급된 것이 맞는지의 진위 여부를 판단하게 됩니다.

쉽게 말하면, 인감 도장을 만들어두고 그 도장으로 여러 활동을 하고 나중에 그 활동에서 사용된 도장이 원본 인감 도장과 일치하는지 확인하는 것으로 생각하면 편합니다.

따라서 DID를 발급하기 위해서 DID Document를 발행해야 합니다.

Solidity

블록체인 네트워크에서의 스마트 컨트랙트를 관리하는데 사용되는 프로그래밍 언어

Remix IDE를 사용하면 프로그램을 설치하지 않고, 바로 Solidity를 사용할 수 있습니다.
많이 사용하는 VS Code를 통해서도 가능합니다.

DID Document

공식 홈페이지 : https://www.w3.org/TR/did-core/

공식 홈페이지를 통해 DID Document에 대한 자세한 내용을 확인할 수 있습니다.

위에서의 did-jwt-vc 깃허브를 보면, 이더리움 네트워크에서 사용 가능한 DID Document도 제공하고 있습니다.

https://github.com/uport-project/ethr-did-registry
해당 리포지토리에서 스마트 컨트랙트 관련 코드를 확인할 수 있습니다.

배포

https://remix.ethereum.org/

위에서의 스마트 컨트랙트 코드를 Remix IDE에서 배포할 수 있습니다.
접속해서 lang 뒤를 en에서 ko로 변경하면 한국어로 사용할 수 있습니다.

https://remix.ethereum.org/#lang=en => https://remix.ethereum.org/#lang=ko

  1. 접속해서 .sol 확장자를 가진 파일을 생성합니다.

  2. ethr-did-registry의 스마트 컨트랙트 코드를 복사 붙여넣기 합니다.

  3. 저장하면 자동으로 컴파일(기본 설정)을 실행하면서 왼쪽에서 컴파일에 성공했다는 메시지가 나옵니다.
    (만약 자동으로 컴파일을 하지 않았다면, 수동으로 컴파일을 클릭해줍니다)

  4. 왼쪽의 이더리움 문약을 클릭하면, 배포 탭으로 이동할 수 있습니다

배포 전에 주의 사항이 있습니다. 현재 환경을 보면 Remix VM으로 선택되어 있습니다.
Remix에서 제공하는 가상환경을 의미합니다.
꼭! 본인이 배포하고자 하는 환경을 선택해야 합니다.
밑에 있는 계정도 현재 본인이 배포하고자 하는 계정이 맞는지 꼭 확인해야 합니다.
이후 해당 계정이 인증기관의 역할을 하기에 매우 중요합니다.

목록을 확인해 보면 Injected Provider - MetaMaskTestnet - Sepolia가 있습니다.
전자의 경우 MetaMask와 현재 연결된 네트워크를 사용한다는 의미이고, 후자는 테스트넷인 세폴리아를 의미합니다.

만약 현재 본인의 지갑이 테스트넷에 연결되어 있는 상태라면 아래와 같이 확인할 수 있습니다.

저는 MetaMask를 사용했습니다. (세폴리아와 연결되어 있기에)
마지막으로 계정을 확인해주고, 배포를 누르면 배포가 진행됩니다.
참고로 컨트랙트 배포시마다 일정 비용의 세폴리아 이더가 필요합니다.

작년 까지만 해도 무료로 세폴리아 이더를 받을 수 있었던 곳이 많았었던 것 같은데
현재는 많이 없네요.

(2024.07.08 기준)
https://faucets.chain.link/ 를 통해서 0.1 세폴리아 이더를 받을 수 있습니다.
Github 로그인 연동 필수

  1. 배포 클릭 => MetaMask와 연결 => 컨펌

  1. 트랜잭션 완료 시에 알림 창이 뜹니다. (배포 완료)

  1. 배포된 컨트랙트 확인

배포된 컨트랙에서의 여러 메소드 확인이 가능하지만, 저희는 지금 주소만 필요하기에 주소를 복사해둡니다.

Resolver

DID Document를 반환받는 객체

Resolver는 블록체인에 배포한 DID Document를 반환 받는 객체입니다.
스마트 컨트랙트의 주소를 통해 배포한 DID Document를 찾아서, VC와 VP의 유효성 검증을 위해 사용됩니다.

원래는 끝이지만..

앞서 말했듯, DID 구현을 위한 준비는 여기서 끝이 나는게 맞습니다.
하지만 저희의 기획 의도는 온라인 상의 신원 인증을 대체하고자 함이었습니다.

따라서 DID Document 를 통해 만들어진 VC에 들어갈 데이터의 정확성이 매우 중요했습니다.
만약 DID안에 들어갈 데이터가 정확하지 않고, 누구나 만들 수 있는 데이터라면 DID를 통해 신원 인증을 하는 것이 의미가 없었습니다.

그래서 저희는 정확한 데이터를 얻을 수 있는 방법에 대해서 고민하기 시작했습니다.
이메일 인증, 문자 인증과 같은 방법은 단순히 해당 이메일과 문자에 대한 존재 여부만 판단할 뿐
실제로 해당 유저가 가지고 있는지, 맞는지를 판단하기는 어렵습니다.

이미지 출처 - https://ktpass.kt.com/

이후 PASS 인증을 떠올리게 되었습니다. 하지만 PASS의 경우 사업자 등록증을 소유하고 있는, 실제로 사업을 하는 경우에만 API 발급이 가능하였기에 이 방법도 사용할 수 없었습니다.

그렇게 실제 본인 인증을 통해 서비스를 구현하는 것에는 한계가 있다는 것을 인정하고
이미 인증된 시스템을 사용하기로 하였습니다.

그것은 바로 신분증입니다.
신분증의 경우 이미 공식적으로 신원을 인증하여 발급해준 증명서입니다.
따라서 해당 신분증을 소유하고 있는 경우, 본인임을 입증할 수 있다고 생각하였고
신분증을 통해 데이터를 획득한 뒤 이를 가공하여 DID를 발급하기로 결정하였습니다.

OCR을 사용할 수 있는 여러 방법이 존재합니다.

Tesseract.js, OCR API, Naver API, Kakao API

이 중 Tesseract는 한글 인식률이 매우 떨어지고, OCR API는 API 사용법만 알면 되지만 유료입니다.
그러면 남은 선택지가 Naver와 Kakao가 남게 됩니다.
이 중 저희는 특정 템플릿 전용 OCR을 지원하는 Naver Clova OCR을 선택하였습니다.

이미지 출처 - https://www.ncloud.com/product/aiService/ocr

저희의 목적은 신분증에서 정확한 데이터를 뽑아 오는 것이기에 특화 모델이 적합했습니다.
물론 300회를 넘어가면 과금이 되는 구조이지만,
프로젝트 특성상 개발 테스트시에만 대부분의 API를 사용할 것이기에 큰 문제는 되지 않았습니다.

Node.js 게이트웨이 사용

보통의 프로젝트의 경우 MSA 구조를 채택하지 않는 한 게이트웨이를 사용하지 않는 것이 일반적이라고 생각합니다. 저희 프로젝트도 초반에 프론트엔드 React, 백엔드 Spring Boot를 채택하여 아키텍처를 구성하였었습니다.

하지만, 자바스크립트 기반의 DID 라이브러리와 CLOVA OCR을 프론트엔드에서 처리하는 것은 보안과 성능상 옳지 않다고 판단하였습니다.
DID의 경우 사용자의 지갑 주소와 프라이빗 키를 다루고, OCR도 신분증 데이터를 다루기 때문입니다.

따라서 자바스크립트로 게이트웨이를 구현하기 위해 Express.js를 사용하여 React와 Spring Boot를 연결하였고, DID와 OCR 기능을 구현하였습나다.

프로젝트 아키텍처

이러한 기술과 배경을 바탕으로 아키텍처를 구성했습니다.

인증기관을 담당하는 DITINFT 플랫폼인 Uniqon 이렇게 두 개의 서비스로 구성되어 있습니다.

DITI에서 OCR을 통해 VC(Verifiable Credential)와 VP(Verifiable Presentation)를 발급받아 DITI DB에 저장합니다. 이후 Uniqon에서 사용자의 VP를 DITI에서 불러와 유효성 검증을 마친 뒤 회원 가입을 끝냅니다.

현재는 회원가입 시의 본인 인증에만 사용하지만, 비즈니스 요구사항에 따라 다양하게 사용할 수 있습니다.
ex) 구매 및 판매시의 본인 인증

마무리

이번 프로젝트를 통해 블록체인 기반의 DID(Decentralized Identity) 시스템을 도입하면서, 새로운 신원 인증 시스템을 개발하게 되었습니다.

프로젝트를 진행하면서 DID 개념, 인증 시스템 구축에 많은 어려움이 있었지만, 팀원들과 이야기하며 어려움을 직접 해결해 나가며 DID의 개념을 이해하고 이를 실제 서비스에 구현하는 과정이 즐겁고 값진 경험이었습니다.

프로젝트에 대한 더 많은 정보는 아래의 깃허브에서 확인할 수 있습니다.
https://github.com/cutepassions/uniqon

profile
새로운 기술을 접하는 것에 망설임이 없고, 부족한 것이 있다면 항상 배우고자 하는 열정을 가지고 있습니다!

3개의 댓글

comment-user-thumbnail
2025년 2월 9일

안녕하세요.
좋은 글 감사합니다. 저도 성인인증이 필요한데 사업자 등록증이 없어서 헤매고 있던 중 이 글을 발견했습니다.
개발 기한을 산정하고 싶은데 cutepassions님께서는 DID를 도입하시는데 대략 몇 일 정도가 걸렸는지 알 수 있을까요?

1개의 답글

관련 채용 정보