Spring Boot 프로젝트 구성부터 QR 요청 생성, VP 제출 검증, 발급기관 정책 설정까지의 연동 절차를 안내합니다.
1. 의존성 추가
Spring Boot 프로젝트에서는 starter를 추가해 KyvcVpVerifier Bean을 자동 등록합니다.
QR/VP/status DTO와 SQLite 정책 저장소를 함께 쓰려면 protocol, policy-store-sqlite 모듈도 추가합니다.
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
implementation "kr.kyvc:kyvc-verifier-spring-boot-starter:0.1.0-SNAPSHOT"
implementation "kr.kyvc:kyvc-verifier-protocol:0.1.0-SNAPSHOT"
implementation "kr.kyvc:kyvc-verifier-policy-store-sqlite:0.1.0-SNAPSHOT"
}
설명
spring-boot-starter: KyvcVpVerifier 자동 등록
verifier-protocol: QR/VP/status DTO와 인터페이스 규격
policy-store-sqlite: Issuer 정책 저장소 사용 시 필요
2. application.yml 설정
외부 Verifier 서버가 SDK를 사용할 때 작성하는 기본 설정입니다.
kyvc:
verifier:
enabled: true
xrpl:
timeout-millis: 5000
presentation:
verifier-name: Example Verifier
requester-name: Example Company
purpose: Corporate KYC Login
accepted-format: kyvc-sd-jwt-presentation-v1
accepted-vct:
- https://kyvc.example/vct/legal-entity-kyc-v1
required-claims:
- corporateName
- businessRegistrationNo
required-disclosures:
- corporateName
- businessRegistrationNo
issuer-policy:
enabled: true
allowed-issuers: []
blocked-issuers: []
policy-store:
type: sqlite
sqlite:
database-path: ./kyvc-verifier-policy.db
initialize-schema: true
busy-timeout-millis: 5000
web:
enabled: false
enabled
SDK 자동 설정 사용 여부입니다. true면 starter가 SDK Bean을 등록하고,
false면 자동 설정이 비활성화됩니다.
xrpl.timeout-millis
XRPL/DID Document 조회 timeout입니다. 예: 5000
presentation.verifier-name
QR/Wallet 화면에 표시될 검증기관 이름입니다.
presentation.requester-name
QR/Wallet 화면에 표시될 요청자 이름입니다.
presentation.purpose
Wallet 화면에 표시될 VP 제출 사유입니다. 예: Corporate KYC Login
presentation.accepted-format
현재 지원 값은 kyvc-sd-jwt-presentation-v1입니다.
presentation.accepted-vct
허용할 VC type / vct 목록입니다.
presentation.required-claims
외부 서비스가 필요한 claim 목록입니다.
presentation.required-disclosures
Wallet에게 disclosure 제출을 요구할 claim 목록입니다.
issuer-policy.enabled
true면 issuer policy 검증을 사용하고, false면 issuer policy 검증을
사용하지 않습니다.
issuer-policy.allowed-issuers
policy-store.type=memory일 때 허용할 Issuer DID 목록입니다.
issuer-policy.blocked-issuers
policy-store.type=memory일 때 차단할 Issuer DID 목록입니다.
policy-store.type
허용값은 memory, sqlite, none입니다. none은
issuer-policy.enabled=false일 때 사용합니다.
policy-store.sqlite.database-path
SQLite 정책 DB 파일 경로입니다.
policy-store.sqlite.initialize-schema
true면 시작 시 정책 테이블 schema를 초기화합니다.
policy-store.sqlite.busy-timeout-millis
SQLite lock 대기 timeout입니다. 예: 5000
web.enabled
SDK starter의 web 자동 기능 사용 여부입니다. 외부 서비스가 직접 API를 구현하면
false로 둡니다.
3. QR 요청 API 구현
서버는 QR 요청 생성 시 nonce, aud, presentationDefinition을
포함한 payload를 만들고, 같은 값을 VP 검증 시 사용하도록 저장합니다.
@RestController
@RequestMapping("/api/vp-requests")
public class VpRequestController {
private final KyvcExternalVerifierRequestHandler requestHandler;
public VpRequestController(KyvcExternalVerifierRequestHandler requestHandler) {
this.requestHandler = requestHandler;
}
@PostMapping
public KyvcExternalVpQrPayload create() {
KyvcExternalVpRequestCreateCommand command = new KyvcExternalVpRequestCreateCommand(
"Example Verifier",
"Corporate KYC Login",
"https://verifier.example.com",
List.of("corporateName", "businessRegistrationNo"),
List.of("corporateName", "businessRegistrationNo"),
List.of(new KyvcPresentationRule("format", "acceptedFormat", "kyvc-sd-jwt-presentation-v1")),
600
);
return requestHandler.createRequest(command);
}
}
QR 요청 값
nonce: VP 검증 시 expectedNonce로 사용
aud: VP 검증 시 expectedAudience로 사용
presentationDefinition: Wallet에 요구할 credential 조건
4. VP 제출 API 구현
외부 서버는 KyvcExternalVpPresentationSubmitRequest를 받아 SDK 검증 request로 변환합니다.
@RestController
@RequestMapping("/api/vp/presentations")
public class VpSubmitController {
private final VpVerificationService verificationService;
public VpSubmitController(VpVerificationService verificationService) {
this.verificationService = verificationService;
}
@PostMapping
public KyvcExternalVpPresentationSubmitResponse submit(
@RequestBody KyvcExternalVpPresentationSubmitRequest request
) {
return verificationService.verify(request);
}
}
제출 request 변환
presentation.sdJwtKb()가 SDK 검증 request의 presentation으로 들어갑니다.
didDocuments는 Wallet이 함께 보낸 DID Document map입니다.
requestId로 QR 생성 시 저장한 nonce/audience를 조회합니다.
5. VP 검증 코드
KyvcVpVerifier Bean을 주입받아 Wallet 제출값을 검증합니다.
@Service
public class VpVerificationService {
private final KyvcVpVerifier verifier;
public VpVerificationService(KyvcVpVerifier verifier) {
this.verifier = verifier;
}
public KyvcExternalVpPresentationSubmitResponse verify(KyvcExternalVpPresentationSubmitRequest submitRequest) {
Map<String, Map<String, Object>> didDocuments = normalizeDidDocuments(submitRequest.didDocuments());
KyvcVpVerificationRequest request = new KyvcVpVerificationRequest(
submitRequest.format(),
submitRequest.presentation().sdJwtKb(),
submitRequest.aud(),
submitRequest.nonce(),
KyvcVerificationOptions.defaults(),
didDocuments
);
KyvcVpVerificationResult result = verifier.verify(request);
Map<String, Object> claims = result.claimParseResult() == null
? Map.of()
: result.claimParseResult().publicClaims();
return new KyvcExternalVpPresentationSubmitResponse(
result.verified(),
result.status().name(),
submitRequest.requestId(),
result.issuerDid(),
result.holderDid(),
result.subjectDid(),
result.credentialType(),
result.credentialId(),
claims,
result.metadata(),
List.of()
);
}
private Map<String, Map<String, Object>> normalizeDidDocuments(Map<String, Object> source) {
return Map.of();
}
}
검증 결과 기준
result.verified(): 최종 성공 여부
result.errors(): 실패 원인 목록
result.metadata(): 세부 검증 플래그 확인용
6. 검증 결과 사용
검증 성공 후 외부 서비스는 issuer/holder/subject DID, credential 정보, 법인 KYC claim을 서비스
로그인/권한 판단에 사용할 수 있습니다.
if (!result.verified()) {
throw new IllegalStateException("VP verification failed");
}
String issuerDid = result.issuerDid();
String holderDid = result.holderDid();
String credentialId = result.credentialId();
KyvcLegalEntityKycClaims claims = result.claimParseResult().legalEntityKycClaims();
String corporateName = claims.corporateName();
String businessRegistrationNumber = claims.businessRegistrationNumber();
7. Issuer 정책 관리
SQLite 정책 저장소를 사용할 때 운영자는 Issuer DID를 허용 또는 차단 정책으로 관리할 수 있습니다.
SqliteKyvcIssuerPolicyStore store = KyvcPolicyStoreSqliteModule.issuerPolicyStore(
new SqlitePolicyStoreOptions("./kyvc-verifier-policy.db", true, 5000, false)
);
SqliteKyvcIssuerPolicyAdmin admin = KyvcPolicyStoreSqliteModule.issuerPolicyAdmin(store);
admin.setTrustPolicyUsed(true);
admin.trustIssuer("did:xrpl:1:rIssuer", "KYvC", "trusted issuer");
admin.blockIssuer("did:xrpl:1:rBlockedIssuer", "Blocked Issuer", "blocked issuer");
admin.deleteIssuer("did:xrpl:1:rOldIssuer");
정책 관리 메서드
setTrustPolicyUsed(true): 정책 검증 사용
trustIssuer(...): 허용 Issuer 등록
blockIssuer(...): 차단 Issuer 등록
deleteIssuer(...): Issuer 정책 삭제