BYOK(키 주입) 개요

Prev Next

VPC 환경에서 이용 가능합니다.

Hardware Security Module(HSM) 서비스는 Thales Luna HSM을 기반으로 하며, 이미 보유하고 계신 키를 HSM 파티션 안으로 주입(BYOK, Bring Your Own Key)해서 사용할 수 있습니다. 주입한 키는 파티션 내부의 일반 키와 동일하게 조회, 암호화·복호화, 서명·검증에 사용할 수 있습니다. 단 공개키는 label로 조회되지 않습니다. 이 문서는 BYOK가 어떤 원리로 동작하고 어떤 키·연산이 지원되는지를 정리하는 개요 문서이며, 실제 실행 절차는 BYOK(키 주입) Java 예제에서 안내합니다.

참고

BYOK란

BYOK는 고객이 이미 보유하고 있는 키를 HSM 파티션 안으로 옮겨 넣고, 이후의 암호 연산을 HSM 안에서 수행하도록 하는 방식입니다. 키가 HSM 안으로 들어오고 나면 다음과 같이 동작합니다.

  • 대칭키와 개인키는 파티션 밖으로 반출되지 않습니다(CKA_EXTRACTABLE=false).
  • 암호화·복호화·서명 연산은 모두 HSM 내부에서 수행되고, 애플리케이션은 결과값만 전달받습니다.
  • 주입한 개인키·대칭키는 파티션 내부에서 직접 생성한 키와 동일하게 label로 조회하고 재사용할 수 있습니다. (공개키는 예외 — 아래 제약 및 주의 사항 참고)

지원 환경

BYOK를 사용하려면 아래 환경이 준비되어 있어야 합니다.

HSM 클라이언트 서버에 SafeNet Luna Client를 설치해 주십시오. 설치 방법은 SafeNet Luna Client 사용을 참고해 주십시오.

Java 예제를 사용하는 경우 JDK 17 이상이 필요합니다. 키를 감싸는(wrap) 단계에서 사용하는 AES/KWP/NoPadding 변환이 JDK 17부터 표준 제공되기 때문입니다. 예제 동작은 OpenJDK 17에서 확인했습니다.

지원 키·연산 매트릭스

다음 표는 주입할 수 있는 키 유형과 주입 방식, 주입 후 사용 가능한 연산을 설명합니다.

주입 대상 키 주입 방식 주입 후 사용 가능한 연산
RSA 공개키 평문 그대로 주입 (공개 정보) RSA 서명 검증, RSA-OAEP 암호화
RSA 개인키 AES-KWP + RSA-OAEP 이중 wrap 후 주입 RSA 서명 생성, RSA-OAEP 복호화
EC 공개키 (P-256 등) 평문 그대로 주입 (공개 정보) ECDSA 서명 검증
EC 개인키 (P-256 등) AES-KWP + RSA-OAEP 이중 wrap 후 주입 ECDSA 서명 생성
AES-256 대칭키 RSA-OAEP wrap 후 주입 암호화·복호화

공개키는 주입 후에도 label로 조회되지 않는다는 제약이 있습니다. 제약 및 주의 사항을 확인해 주십시오.

참고

위 키 유형은 각각 여러 개를 주입할 수 있습니다. 예를 들어 용도가 다른 공개키 두 개와 대칭키 두 개를 한 파티션에 함께 주입할 수 있습니다. 주입할 때 지정한 label이 파티션 안에서 키를 구분하는 이름이 되므로, 키마다 서로 다른 label을 지정해 주십시오.

주입 원리

BYOK의 핵심 원칙은 키 평문을 HSM에 직접 넣지 않는다는 것입니다. 대신 HSM 안에서 만든 wrapping key로 감싼(wrap) 상태로 전달하고, HSM 내부에서 풀어서(unwrap) 키 객체를 만듭니다.

  1. HSM 파티션 안에서 RSA wrapping 키쌍을 생성합니다.
  2. 그중 공개키만 PEM으로 반출해서 키를 보유한 쪽에 전달합니다.
  3. 키를 보유한 쪽에서 그 공개키로 자기 키를 감쌉니다 (wrapped blob 생성).
  4. wrapped blob만 전달받습니다 (평문은 전달되지 않습니다).
  5. HSM 파티션 안에서 wrapping 개인키로 unwrap 합니다.
  6. HSM 파티션 안에 키 객체가 만들어집니다.

이 구조에서 wrapping 개인키는 HSM 밖으로 나가지 않으므로, 전달 과정에서 wrapped blob이 노출되더라도 키 평문이 복원되지 않습니다.

주의

3번 단계는 키 평문을 다루는 유일한 지점입니다. 이 작업은 키를 보유한 쪽의 시스템에서 수행해야 하며, 평문 키 파일을 HSM 클라이언트 서버로 옮겨서 작업하지 말아 주십시오. 작업이 끝난 뒤에는 평문 키 파일과 임시 KEK(Key Encryption Key) 파일을 삭제해 주십시오.

공개키 주입 vs 개인키·대칭키 주입

공개키는 공개해도 되는 정보이므로 감쌀 필요가 없습니다. 반면 개인키와 대칭키는 반드시 감싸서 주입해야 하며, 개인키는 한 단계가 더 필요합니다.

다음 표는 키 종류별 주입 흐름과 unwrap 횟수를 설명합니다.

구분 주입 흐름 unwrap 횟수
공개키 (RSA·EC) 공개키 PEM을 그대로 전달 → HSM 안에서 공개키 객체 생성 0회 (wrap 없음)
AES 대칭키 AES 키를 HSM 공개키로 RSA-OAEP wrap → HSM 안에서 unwrap 1회
RSA/EC 개인키 개인키를 임시 AES KEK로 AES-KWP wrap하고, 그 KEK를 HSM 공개키로 RSA-OAEP wrap → HSM 안에서 KEK를 먼저 unwrap하고, 그 KEK로 개인키를 unwrap 2회

개인키에 임시 KEK를 한 단계 더 두는 이유는 RSA-OAEP로 직접 감쌀 수 있는 데이터 크기가 제한되기 때문입니다. RSA-2048/OAEP-SHA256으로 감쌀 수 있는 데이터는 190바이트까지인데, PKCS#8로 인코딩된 RSA-2048 개인키는 1,200바이트 안팎입니다. 그래서 개인키는 크기 제한이 없는 AES-KWP로 감싸고, 32바이트짜리 AES KEK만 RSA-OAEP로 감쌉니다.

암호 파라미터

주입에 사용하는 파라미터는 아래 값으로 고정합니다. 키를 보유한 쪽과 HSM 쪽이 같은 값을 사용해야 unwrap이 성공합니다.

용도 알고리즘 / 변환 파라미터
AES 키·AES KEK 전달 RSA/ECB/OAEPWithSHA256AndMGF1Padding 해시 SHA-256, MGF1 해시 SHA-256, label 없음
RSA/EC 개인키 전달 AES/KWP/NoPadding 입력은 PKCS#8 DER, KEK는 AES-256
wrapping 키쌍 RSA 2048비트 이상, 공개 지수 65537
주의

RSA-OAEP는 해시와 MGF1 해시를 각각 지정할 수 있고 기본값이 구현마다 다릅니다. OpenSSL의 rsa_oaep_md/rsa_mgf1_md 기본값은 SHA-1이므로, 두 값을 모두 sha256으로 명시하지 않으면 HSM에서 unwrap이 실패합니다.

사전 준비

키를 주입하기 전에 아래 두 가지가 준비되어 있어야 합니다.

HSM 파티션 준비

  • HSM 클라이언트 서버에 SafeNet Luna Client 설치 — SafeNet Luna Client 사용
  • HSM 클라이언트 서버 인스턴스와 HSM 파티션 간 연결 생성 완료
  • HSM 파티션 초기 설정 완료 및 Crypto User(CU) 비밀번호 확보 (정책을 변경해야 한다면 초기화 시 설정한 Partition Security Officer(PO) 비밀번호도 필요합니다)
  • 주입에 필요한 파티션 정책이 켜져 있는지 확인

wrapping 키쌍 생성 및 공개키 반출

파티션 안에서 RSA wrapping 키쌍을 만들고, 공개키만 PEM 파일로 반출합니다. 이 공개키를 키 보유 측에 전달하면 됩니다. 구체적인 명령은 Java 예제 가이드에서 안내합니다.

참고

wrapping 키쌍은 주입 대상 키와 별개의 관리용 키입니다. 주입이 끝난 뒤에도 남겨두면 이후 추가 주입에 재사용할 수 있습니다. 용도별로 나누어 관리하려면 주입 건마다 새로 만들어도 됩니다.

파티션 정책 요구사항

키 주입은 파티션 정책(partition policy)의 영향을 받습니다. 아래 정책이 켜져 있어야 합니다. 네 정책 모두 기본값이 켬이지만, 파티션 생성 시 정책 템플릿을 적용했거나 이후 값을 바꾼 경우에는 다를 수 있으므로 현재 정책 확인으로 직접 점검해 주십시오.

정책 이름 필요한 경우 기본값 끔 → 켬 변경이 파괴적인가
28 Allow Key Management Functions 모든 주입 시나리오 (wrapping 키쌍 생성 포함)
6 Allow secret key unwrapping AES 대칭키 주입, 개인키 주입용 임시 KEK 주입 아니오
2 Allow private key unwrapping RSA/EC 개인키 주입 아니오
17 Allow signing with non-local keys 주입한 RSA/EC 개인키로 서명할 때 아니오
주의

정책 17(Allow signing with non-local keys)은 파티션 밖에서 만들어진 키로 서명하는 것을 허용하는 정책입니다. 이 정책이 꺼져 있으면 개인키 주입 자체는 성공하지만, 그 키로 서명하려 할 때 CKR_KEY_FUNCTION_NOT_PERMITTED로 실패합니다. 주입한 개인키로 서명해야 한다면 주입 전에 정책 상태를 확인해 주십시오.

현재 정책 확인

SafeNet Luna Client CLI로 확인합니다. -verbose를 붙이면 현재 값과 함께, 값을 바꿀 때 파티션이 초기화되는지가 방향별로 표시됩니다.

lunacm:> slot set -slot <슬롯번호>
lunacm:> partition showPolicies -verbose

출력 예시입니다. 이 문서가 요구하는 네 정책만 발췌했습니다.

    Partition Policies
                                                                  Destructive
     Code Description                                   Value Off-To-On On-To-Off
    _____________________________________________________________________________

      2   Allow private key unwrapping                   On      No        No
      6   Allow secret key unwrapping                    On      No        No
      17  Allow signing with non-local keys              On      No        No
      28  Allow Key Management Functions                 On      Yes       No
  • Off-To-On — 정책을 끔에서 켬으로 바꿀 때 파괴적인지
  • On-To-Off — 켬에서 끔으로 바꿀 때 파괴적인지
  • Yes인 방향으로 값을 바꾸면 파티션이 초기화되어 저장된 키 객체가 모두 삭제됩니다.

Thales 공식 문서 기준으로 네 정책은 모두 기본값이 1(켬)이고, 대응하는 capability도 항상 1입니다. 다만 파티션 생성 시 정책 템플릿을 적용했거나 이후 값을 바꾼 경우에는 다를 수 있으므로, 주입을 시작하기 전에 사용하실 파티션에서 직접 확인해 주십시오.

네 정책이 모두 On이면 별도 설정 없이 주입을 진행할 수 있습니다. 하나라도 Off라면 정책 변경을 먼저 수행해야 하며, 특히 정책 28이 Off인 경우에는 아래 경고를 반드시 확인해 주십시오.

참고

partition showPolicies 출력에는 Partition Capabilities도 함께 나옵니다. Capability는 HSM Security Officer가 정한 상한이며, 값이 0인 항목은 정책으로도 켤 수 없습니다. 고객이 변경할 수 있는 것은 Policies 쪽입니다.

정책 변경

Hardware Security Module 서비스의 콘솔이나 API에서는 파티션 정책 변경을 제공하지 않습니다. SafeNet Luna Client CLI에서 PO로 로그인해 변경합니다. Crypto Officer(CO)나 Crypto User(CU) 권한으로는 변경할 수 없습니다. 이 문서의 다른 절차는 CU로 수행하지만, 정책 변경만은 PO 권한이 필요합니다.

PO 비밀번호는 HSM 파티션을 초기화할 때 직접 설정한 값입니다.

lunacm:> slot set -slot <슬롯번호>
lunacm:> role login -name po
lunacm:> partition changePolicy -policy <정책번호> -value <0|1>
lunacm:> role logout
주의

정책 변경으로 파티션이 초기화될 수 있습니다

  • partition showPolicies -verbose에서 바꾸려는 방향이 Yes로 표시된 정책은 파괴적(destructive)입니다. 값을 바꾸는 순간 파티션이 초기화되어 저장된 모든 키 객체가 삭제되며, 되돌릴 수 없습니다.
  • 특히 정책 28(Allow Key Management Functions)은 끔 → 켬 변경이 파괴적입니다. 이 정책이 꺼진 파티션에서 BYOK를 시작하려면 정책부터 켜야 하는데, 그 시점에 파티션에 들어 있던 키가 모두 사라집니다. 반면 정책 2·6·17은 양방향 모두 비파괴적이라 안전하게 켤 수 있습니다.
  • partition changePolicy는 파괴적 변경을 실행하기 전에 확인을 요구합니다. -force 옵션은 이 확인을 건너뛰므로 사용하지 마십시오.
  • BYOK로 주입한 키는 CKA_EXTRACTABLE=false라 파티션 밖으로 백업할 수 없습니다. 파티션이 초기화되면 원본 키를 다시 주입하는 것 외에 복구 방법이 없습니다. 키를 주입하기 전에 필요한 정책을 모두 확인하고 설정해 주십시오. 이미 운영 중인 파티션이라면 정책 변경 전에 영향 범위를 반드시 확인해 주십시오.

주입한 키로 연산 수행

주입한 개인키·대칭키는 label로 조회해서 파티션 내부에서 생성한 키와 동일하게 사용합니다. 공개키만 label 조회가 되지 않아 PEM에서 로드해 사용합니다. Hardware Security Module 서비스의 API가 아니라 SafeNet Luna Client를 통해 직접 연동하는 방식입니다.

다음 표는 연산별로 사용하는 키와 Java 호출 방법을 설명합니다.

연산 사용하는 키 Java(LunaProvider) 기준
키 조회 (개인키·대칭키) LunaKey.LocateKeyByAlias(label, slot)
키 조회 (공개키) label 조회 불가 — handle로 조회
AES 암호화·복호화 주입한 AES 키 Cipher.getInstance("AES/CBC/PKCS5Padding", "LunaProvider")
RSA-OAEP 암호화 RSA 공개키 (PEM에서 로드) Cipher.getInstance("RSA/ECB/OAEPWithSHA256AndMGF1Padding", "LunaProvider")
RSA-OAEP 복호화 주입한 RSA 개인키 위와 동일 변환, DECRYPT_MODE
RSA 서명 생성 주입한 RSA 개인키 Signature.getInstance("SHA256withRSA", "LunaProvider")
ECDSA 서명 생성 주입한 EC 개인키 Signature.getInstance("SHA256withECDSA", "LunaProvider")
RSA 서명 검증 RSA 공개키 (PEM에서 로드) Signature.getInstance("SHA256withRSA", "LunaProvider")
ECDSA 서명 검증 EC 공개키 (PEM에서 로드) Signature.getInstance("SHA256withECDSA", "LunaProvider")

실제 코드는 BYOK(키 주입) 가이드 - Java 예제를 참고해 주십시오.

제약 및 주의 사항

제약 및 주의 사항을 설명합니다.

키 평문 직접 주입 불가

AES 키 평문을 CKA_VALUE 속성에 넣어 객체를 직접 생성하는 방식은 지원되지 않습니다. Hardware Security Module 서비스 파티션에서 확인한 결과 CKR_TEMPLATE_INCONSISTENT 오류로 실패합니다. 평문 AES 키를 보유하고 계시더라도 이 문서에서 안내하는 wrapping 방식으로 주입해야 합니다.

HA 파티션의 가상 슬롯 사용

HA(고가용성) 그룹으로 구성된 경우, 주입 작업의 슬롯 번호로 개별 파티션 슬롯이 아니라 HA 가상 슬롯 ID를 지정해야 합니다. 개별 슬롯에 주입하면 그 파티션에만 키가 생기고 HA 멤버 간에 동기화되지 않습니다.

주입한 키의 반출 불가

주입한 대칭키·개인키는 CKA_EXTRACTABLE=false로 생성되므로 다시 꺼낼 수 없습니다. 주입 후에도 원본 키 백업이 필요하다면 주입 전에 별도로 보관해 주십시오.

키 메타데이터 관리

HSM 객체에는 label과 몇 가지 속성만 저장됩니다. 어떤 키를 언제 어떤 파라미터로 주입했는지는 HSM 바깥에서 별도로 기록해 두어야 합니다. 운영 환경에서 함께 남겨두면 좋은 항목은 Java 예제 가이드의 운영 적용 시 조정 항목에서 안내합니다.

공개키의 label 조회 불가

공개키는 파티션에 정상 보관되지만, LunaProvider의 label 기반 탐색 API는 개인키·대칭키·인증서만 대상으로 하며 공개키 객체를 검색하지 않습니다. 파티션 안에서 생성한 공개키도 동일합니다. 따라서 공개키 연산(서명 검증, RSA-OAEP 암호화)은 label 대신 공개키 PEM을 지정해 수행하고, 주입한 공개키 확인은 handle로 합니다. 이때도 LunaProvider가 공개키를 세션 객체로 파티션에 올리므로 연산은 HSM 안에서 수행되며, 공개키에는 보호할 비밀이 없으므로 보안상 차이는 없습니다.

주입한 개인키의 CKA_UNWRAP 기본값

LunaProvider의 unwrap 기본 템플릿 때문에, 주입한 RSA/EC 개인키는 CKA_UNWRAP=true 상태로 만들어집니다. 이 키로 다른 키를 unwrap 할 수 있다는 뜻이므로, 서명·복호화 전용으로 쓸 키라면 주입 후 이 속성을 내리는 것을 권장합니다.

label 중복 주의

같은 label로 키를 다시 주입하면 기존 객체가 교체되지 않고 같은 label을 가진 객체가 하나 더 생깁니다. 이 경우 label 조회 결과가 어느 쪽을 가리킬지 보장되지 않습니다. 주입 전에 같은 label의 객체가 있는지 조회해 주십시오.

다음 단계

이 문서를 읽은 뒤 진행할 작업은 다음과 같습니다.