- 인쇄
- PDF
키 생성/관리
- 인쇄
- PDF
VPC 환경에서 이용 가능합니다.
키를 생성하는 메커니즘의 유형, 키의 속성, 나타날 수 있는 에러 코드, 키 공유 방법에 관해 설명합니다.
BIP32 메커니즘 구현은 Thales 공식 문서를 기반으로 작성되었습니다. 사용 가이드에서 안내하는 내용 외에 더 많은 내용을 살펴보려면 BIP32 Mechanism Support and Implementation을 참고해 주십시오.
키 생성
BIP32 키는 파생 방식으로 생성할 수 있으며, 파생을 위해 다음의 두 메커니즘을 사용할 수 있습니다.
CKM_BIP32_MASTER_DERIVE
시드에서 마스터 키 페어를 파생하는 메커니즘입니다.
입력 키는 CKK_GENERIC_SECRET
유형(128-512비트 크기)이어야 합니다.
1개의 시드에서 2개의 키를 도출하며, 이를 위해 2개의 템플릿을 입력으로 받아들이고 2개의 파생된 키 핸들을 출력해야 합니다.
C_DeriveKey()
의 마지막 3개 인수(pTemplate
, ulAttributeCount
, phKey
)는 null 또는 0이어야 합니다. 이 중 하나라도 null이 아닌 경우 CKR_ARGUMENTS_BAD
가 반환됩니다.
템플릿과 반환된 핸들은 공개 및 개인으로 레이블이 지정된 메커니즘 매개 변수를 통해 전달됩니다. 공개 또는 개인 키를 생성하지 않으려면 매개 변수를 0 또는 null로 남겨 주십시오.
typedef struct CK_BIP32_MASTER_DERIVE_PARAMS {
CK_ATTRIBUTE_PTR pPublicKeyTemplate;
CK_ULONG ulPublicKeyAttributeCount;
CK_ATTRIBUTE_PTR pPrivateKeyTemplate;
CK_ULONG ulPrivateKeyAttributeCount;
CK_OBJECT_HANDLE hPublicKey; // output parameter
CK_OBJECT_HANDLE hPrivateKey; // output parameter
} CK_BIP32_MASTER_DERIVE_PARAMS;
CKM_BIP32_CHILD_DERIVE
부모 키에서 자식 키를 파생하는 메커니즘입니다.
키 페어의 개인 및 공개 부분을 모두 생성할 수 있으며 BIP32 공개 또는 개인 키를 입력으로 받아들일 수 있습니다.
공개에서 개인으로 파생을 시도하면 오류가 반환됩니다.
마스터 키 파생과 마찬가지로 템플릿 및 키 핸들 출력은 메커니즘 매개 변수를 통해 전달됩니다. 공개 또는 개인 키를 생성하지 않으려면 매개 변수를 0 또는 null로 남겨 주십시오.
BIP32 및 BIP44 규격은 지갑 구조와 사용 사례에 대한 권장 사항을 제공합니다. 키 트리를 구성하는 방법과 특정 키의 강화 여부를 결정하는 데 좋은 참고 자료로 볼 수 있습니다. 잠재적인 보안 취약을 방지하려면 권장하는 규격을 준수해 주십시오.
이 메커니즘은 키 계층 구조에서 여러 수준 아래에 있는 키를 생성할 때 사용할 수 있습니다. 키의 경로는 pulPath
및 ulPathLen
으로 지정됩니다. 경로는 정수 배열(키 인덱스)입니다. 경로는 입력 키에 상대적입니다. 예를 들어, 경로가 [5, 1, 4]이고 입력 키의 경로가 m/0이면 결과 경로는 m/0/5/1/4이 됩니다.
typedef struct CK_BIP32_CHILD_DERIVE_PARAMS {
CK_ATTRIBUTE_PTR pPublicKeyTemplate;
CK_ULONG ulPublicKeyAttributeCount;
CK_ATTRIBUTE_PTR pPrivateKeyTemplate;
CK_ULONG ulPrivateKeyAttributeCount;
CK_ULONG_PTR pulPath;
CK_ULONG ulPathLen;
CK_OBJECT_HANDLE hPublicKey; // output parameter
CK_OBJECT_HANDLE hPrivateKey; // output parameter
CK_ULONG ulPathErrorIndex; // output parameter
} CK_BIP32_CHILD_DERIVE_PARAMS;
메커니즘 에러 코드
메커니즘 사용 시 나타날 수 있는 오류는 다음과 같습니다.
에러 코드 | 설명 |
---|---|
CKR_BIP32_CHILD_INDEX_INVALID |
|
CKR_BIP32_INVALID_HARDENED_DERIVATION | 공개 키에서 강화 키(hardened key) 파생을 시도할 때 반환되는 에러(BIP32 규격은 해당 형태의 파생 미지원) |
CKR_BIP32_MASTER_SEED_LEN_INVALID | 마스터 키 생성 시 시드의 길이가 권장 규격인 128-512비트에서 벗어날 때 반환되는 에러 |
CKR_BIP32_MASTER_SEED_INVALID |
|
CKR_BIP32_INVALID_KEY_PATH_LEN | ulPathLen이 0이거나 255보다 클 때 반환되는 에러. BIP44 표준은 길이 5의 경로만 요구하므로 이 제한은 모든 고객에게 허용되어야 함. |
키 속성
메커니즘을 통해 생성된 키의 속성은 다음과 같습니다.
속성 | 설명 |
---|---|
CKA_BIP32_CHAIN_CODE | 체인 코드. BIP32 키에 필수적이며 향후 키를 도출하는 데 사용. 공개 키와 개인 키는 해당 값 공유. 읽기 전용 값. |
CKA_BIP32_VERSION_BYTES | 버전 바이트. BIP32 키를 추가로 식별하는 데 사용. 메인 비트코인과 테스트 네트워크 중 키가 어디에서 사용되는지 확인하는 데 도움을 줌. CKG_BIP32_VERSION_MAINNET_PUB/PRIV 가 기본값으로 지정되며, 필요한 경우 키 생성 시 CKG_BIP32_VERSION_TESTNET_PUB/PRIV 로 설정 가능. |
CKA_BIP32_CHILD_INDEX | 자식 인덱스. 키를 도출하는 데 사용된 인덱스로 저장된 값. CKF_BIP32_HARDENED 비트 집합의 인덱스는 강화된 자식 키로 간주. 마스터 키의 자식 인덱스는 0. 공개 키와 개인 키는 해당 값 공유. 읽기 전용 값. |
CKA_BIP32_CHILD_DEPTH | 키 트리에서 자식 키의 수준. 마스터 키의 수준은 0. 공개 키와 개인 키는 해당 값 공유. 읽기 전용 값. |
CKA_BIP32_ID | 키의 고유 식별자. 압축된 공개 키의 HASH160에서 파생. 값의 처음 32비트를 지문이라 칭함. (CKA_ID는 사용자가 입력할 수 있는 속성 때문에 해당 용도로 사용하지 않음) 공개 키와 개인 키는 해당 값 공유. 읽기 전용 값. |
CKA_BIP32_FINGERPRINT , CKA_BIP32_PARENT_FINGERPRINT | 키의 지문 및 부모 키의 지문. BIP32 키 식별자의 처음 32비트값. 마스터 키의 부모 지문은 0. 키를 식별하는 데 사용될 수 있지만 지갑 소프트웨어에서 충돌 처리 필요. (CKA_BIP32_ID는 길이가 길어 충돌이 문제가 되지 않기에 키 식별을 위해서는 CKA_BIP32_ID 사용 권장) 공개 키와 개인 키는 해당 값 공유. 읽기 전용 값. |
CKA_BIP32_ID 관련 참고 사항
부모 ID는 필요하지 않으므로 부모 ID에 대한 특성은 없습니다. 키를 사용하는 예상 시나리오가 키를 도출하고 사용한 다음 삭제하는 것임을 고려할 때, 지문이나 ID를 기반으로 키가 어떻게 구성되는지 알아낼 필요는 없어야 합니다. 간혹 키 트리를 다시 검색해야 할 경우 부모의 지문을 이용할 수 있지만 이땐 지갑 소프트웨어에서 부수적인 충돌을 모두 처리해야 합니다. BIP32 설계자는 부모 ID가 직렬 키에 포함될 만큼 중요하지는 않은 것으로 판단했기 때문에 고유 식별자 값에서도 제외됩니다.
키 가져오기/내보내기
기존의 키를 가져오거나 생성한 키를 내보낼 수 있습니다.
공개 키
직렬화 형식(serialization format)이 지원되어 기존 BIP32 키를 가져올 수 있습니다. 공개 키의 경우 가져오기 및 내보내기를 용이하게 하기 위해 라이브러리에서 여러 기능을 지원합니다.
CK_RV CA_Bip32ImportPubKey( //키 가져오기
CK_SESSION_HANDLE hSession,
CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount,
const CK_CHAR_PTR pKey, //in BIP32 serialization format
CK_OBJECT_HANDLE_PTR phObject
);
CK_RV CA_Bip32ExportPubKey( //키 내보내기
CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hObject,
CK_CHAR_PTR pKey, //in BIP32 serialization format
CK_ULONG_PTR pulKeyLen //on input contains max. buffer size, returns
// actual size
);
공개 키를 가져오려면 함수 CA_Bip32ImportPubKey()
를 사용해 주십시오.
C_CreateObject()
와 유사하지만 직렬화된 공개 키에 대한 추가 매개 변수가 필요합니다.- 전달되는 템플릿에는
CKA_TOKEN
,CKA_PRIVATE
,CKA_DERIVE
등의 BIP32 비포함 속성도 포함되어야 합니다. - 함수를 실행하면 공개 키가 디코딩되고 BIP32 속성을 모두 가져온 후 두 속성 집합을 모두 사용해 HSM에서 공개 키를 생성합니다.
직렬화된 확장 공개 키를 가져올 때 구현된 결과물에서 공개 키 데이터의 X 좌표가 곡선의 한 점에 대응하는지 확인해야 합니다. 대응하지 않으면 해당 키는 유효하지 않습니다.
공개 키를 내보내려면 함수 CA_Bip32ExportPubKey()
를 사용해 주십시오.
- 지정된 객체는 HSM에서 추출되고 BIP32 형식으로 인코딩 됩니다.
- 결과는 NULL 종단 문자열이며 pKey 매개 변수에 배치됩니다. pKey의 길이는 최대 112자이며,
CKG_BIP32_MAX_SERIALIZED_LEN
으로 정의됩니다. 키 직렬화에 일부 문자가 필요하지 않을 수 있고 사용되지 않은 문자는 0으로 설정됩니다.
코드 사용의 구체적인 예시를 보려면 샘플 코드를 참고해 주십시오.
개인 키
개인 키는 기존 PKCS#11 기능으로 가져오고 내보낼 수 있습니다. HSM이 복제 대신 키 랩 모델을 사용하는 경우에만 기능을 사용할 수 있습니다.
- 개인 키를 가져오려면 직렬화된 키의
C_Encrypt*()
를 호출한 후C_UnwrapKey()
를 호출해 주십시오. - 개인 키를 내보내려면
C_WrapKey()
를 호출한 후C_Decrypt*()
를 호출해 주십시오. C_WrapKey()
및C_UnwrapKey()
를 사용하여 HSM에서 키를 저장하거나 HSM 간에 키를 이동할 수 있습니다.
코드 사용의 구체적인 예시를 보려면 샘플 코드를 참고해 주십시오.
BIP32 직렬화 형식
확장된 공개 및 개인 키는 다음과 같이 직렬화됩니다.
- 4바이트: 버전 바이트
- 메인 네트워크: 0x0488B21E public, 0x0488ADE4 private
- 테스트 네트워크: 0x043587CF public, 0x04358394 private
- 1바이트: 깊이 - 마스터 노드의 경우 0x00, 수준 1 파생 키의 경우 0x01, ...
- 4바이트: 부모 키의 지문(마스터 키의 경우 0x00000000)
- 4바이트: 자식 번호(인덱스) – 32비트 부호 없는 정수(최상위 비트가 먼저 있음, 마스터 키의 경우 0x00000000)
- 32바이트: 체인 코드
- 32바이트: 공개 키 또는 개인 키 데이터
총 78바이트인 이 구조는 Base58의 다른 비트코인 데이터처럼 인코딩 되는데, 먼저 32개의 체크섬 비트(더블 SHA-256 체크섬에서 파생됨)를 추가한 다음 Base58 표현으로 변환됩니다. 따라서 CKG_BIP32_MAX_SERIALIZED_LEN
값만큼의 Base58 인코딩 문자열이 생성됩니다. 버전 바이트를 선택하기 때문에 Base58 표현은 메인 네트워크에서는 'xprv' 또는 'xpub'으로, 테스트 네트워크에서는 'tprv' 또는 'tpub'으로 시작합니다.