--- title: "샘플 코드" slug: "hsm-bip32-code-vpc" tags: ["HSM", "Hardware Security Module", "SafeNet Luna Client", "BIP32"] updated: 2026-10-22T09:08:02Z published: 2026-10-22T09:08:02Z canonical: "guide-gov.ncloud-docs.com/hsm-bip32-code-vpc" --- > ## Documentation Index > Fetch the complete documentation index at: https://guide-gov.ncloud-docs.com/llms.txt > Use this file to discover all available pages before exploring further. # 샘플 코드 VPC 환경에서 이용 가능합니다. 키를 생성하거나 가져오고 내보낼 때 사용되는 샘플 코드를 설명합니다. 참고 BIP32 메커니즘 구현은 Thales 공식 문서를 기반으로 작성되었습니다. 사용 가이드에서 안내하는 내용 외에 더 많은 내용을 살펴보려면 [BIP32 Mechanism Support and Implementation](https://thalesdocs.com/gphsm/luna/7.4/docs/pci/Content/sdk/extensions/BIP32.htm)을 참고해 주십시오. ## 마스터 키 페어 파생 권한이 없는 사용자가 체인 코드를 볼 수 없도록 마스터 공개 및 개인 키의 `CKA_PRIVATE`을 `TRUE`로 설정해 주십시오. 마스터 키는 키 파생 시에만 사용해야 합니다. 템플릿에 속성이 없는 경우 공개/개인 키의 버전 바이트 기본값은 `0x0488B21E/0x0488ADE4`이며, 이는 메인 비트코인 네트워크의 키에 대한 BIP32에 명시된 값입니다. 마스터 키 페어를 파생하는 샘플 코드는 다음과 같습니다. 파생이 완료되면 새로운 키 핸들이 `pubKey` 및 `privKey`에 저장됩니다. ``` CK_ATTRIBUTE pubTemplate[] = { {CKA_TOKEN, &bToken, sizeof(bToken)}, {CKA_PRIVATE, &bTrue, sizeof(bTrue)}, {CKA_DERIVE, &bTrue, sizeof(bTrue)}, {CKA_MODIFIABLE, &bTrue, sizeof(bTrue)}, {CKA_LABEL, pbLabel, strlen(pbLabel)}, }; CK_ATTRIBUTE privTemplate[] = { {CKA_TOKEN, &bToken, sizeof(bToken)}, {CKA_PRIVATE, &bTrue, sizeof(bTrue)}, {CKA_SENSITIVE, &bTrue, sizeof(bTrue)}, {CKA_DERIVE, &bTrue, sizeof(bTrue)}, {CKA_MODIFIABLE, &bTrue, sizeof(bTrue)}, {CKA_LABEL, pbLabel, strlen(pbLabel)}, }; CK_BIP32_MASTER_DERIVE_PARAMS mechParams; mechParams.pPublicKeyTemplate = pubTemplate; mechParams.ulPublicKeyAttributeCount = ARRAY_SIZE(pubTemplate); mechParams.pPrivateKeyTemplate = privTemplate; mechParams.ulPrivateKeyAttributeCount = ARRAY_SIZE(privTemplate); CK_MECHANISM mechanism = {CKM_BIP32_MASTER_DERIVE, &mechParams, sizeof(mechParams)}; CK_RV rv = C_DeriveKey(hSession, &mechanism, hSeedKey, NULL, 0, NULL); // fail if rv != CKR_OK CK_OBJECT_HANDLE pubKey = mechanism.hPublicKey; CK_OBJECT_HANDLE privKey = mechanism.hPrivateKey; ``` ## 하위 리프 키 파생 권한이 없는 사용자가 체인 코드를 볼 수 없도록 마스터 공개 및 개인 키의 `CKA_PRIVATE`을 `TRUE`로 설정해 주십시오. 하위 리프 키(키 트리 최하단에 위치한 키)는 파생에 사용할 수 없으며 서명, 확인, 암호화 및 복호화에 사용해야 합니다. 부모 자식 키를 사용하려면 파생 속성을 설정해야 합니다. 템플릿에 속성이 없는 경우 공개/개인 키의 버전 바이트 기본값은 `0x0488B21E/0x0488ADE4`이며, 이는 메인 비트코인 네트워크의 키에 대한 BIP32에 명시된 값입니다. 하위 리프 키를 파생하는 샘플 코드는 다음과 같습니다. 파생이 완료되면 새로운 키 핸들이 `pubKey` 및 `privKey`에 저장됩니다. `CK_ULONG path`는 BIP44 규약을 따르는 키 페어를 생성하고, BTC를 수신할 때 사용될 수 있습니다. ``` CK_ATTRIBUTE pubTemplate[] = { {CKA_TOKEN, &bToken, sizeof(bToken)}, {CKA_PRIVATE, &bTrue, sizeof(bTrue)}, {CKA_ENCRYPT, &bTrue, sizeof(bTrue)}, {CKA_VERIFY, &bTrue, sizeof(bTrue)}, {CKA_MODIFIABLE, &bTrue, sizeof(bTrue)}, {CKA_LABEL, pbLabel, strlen(pbLabel)}, }; CK_ATTRIBUTE privTemplate[] = { {CKA_TOKEN, &bToken, sizeof(bToken)}, {CKA_PRIVATE, &bTrue, sizeof(bTrue)}, {CKA_SENSITIVE, &bTrue, sizeof(bTrue)}, {CKA_SIGN, &bTrue, sizeof(bTrue)}, {CKA_DECRYPT, &bTrue, sizeof(bTrue)}, {CKA_MODIFIABLE, &bTrue, sizeof(bTrue)}, {CKA_LABEL, pbLabel, strlen(pbLabel)}, }; CK_ULONG path[] = { CKF_BIP32_HARDENED | CKG_BIP44_PURPOSE, CKF_BIP32_HARDENED | CKG_BIP44_COIN_TYPE_BTC, CKF_BIP32_HARDENED | 1, CKG_BIP32_EXTERNAL_CHAIN, 0 }; CK_BIP32_MASTER_DERIVE_PARAMS mechParams; mechParams.pPublicKeyTemplate = pubTemplate; mechParams.ulPublicKeyAttributeCount = ARRAY_SIZE(pubTemplate); mechParams.pPrivateKeyTemplate = privTemplate; mechParams.ulPrivateKeyAttributeCount = ARRAY_SIZE(privTemplate); mechParams.pulPath = path; mechParams.ulPathLen = ARRAY_SIZE(path); CK_MECHANISM mechanism = {CKM_BIP32_CHILD_DERIVE, &mechParams, sizeof(mechParams)}; CK_RV rv = C_DeriveKey(hSession, &mechanism, hMasterPrivKey, NULL, 0, NULL); // fail if rv != CKR_OK CK_OBJECT_HANDLE pubKey = mechanism.hPublicKey; CK_OBJECT_HANDLE privKey = mechanism.hPrivateKey; ``` ## 확장 공개 키 가져오기 확장 공개 키를 가져오는 샘플 코드는 다음과 같습니다. 가져오기가 완료되면 새로 생성된 키의 핸들이 `pubKey`에 저장됩니다. ``` CK_ATTRIBUTE template[] = { {CKA_TOKEN, &bToken, sizeof(bToken)}, {CKA_PRIVATE, &bTrue, sizeof(bTrue)}, {CKA_DERIVE, &bTrue, sizeof(bTrue)}, {CKA_MODIFIABLE, &bTrue, sizeof(bTrue)}, {CKA_LABEL, pbLabel, strlen(pbLabel)}, }; CK_CHAR_PTR encodedKey = “xpub661MyMwAqRbcFtXgS5…”; //BIP32 serialization format CK_OBJECT_HANDLE pubKey; CK_RV rv = CA_Bip32ImportKey(hSession, template, ARRAY_SIZE(template), encodedKey, &pubKey); ``` ## 확장 공개 키 내보내기 확장 공개 키를 내보내는 샘플 코드는 다음과 같습니다. 내보내기가 완료되면 인코딩 된 키가 `encodedKey`(BIP32 직렬화 형식)에 저장됩니다. ``` CK_CHAR encodedKey[CKG_BIP32_MAX_SERIALIZED_LEN+1]; CK_ULONG ulEncodedKeySize = sizeof(encodedKey); CK_RV rv = CA_Bip32ExportPubKey(hSession, hObject, encodedKey, &ulEncodedKeySize ); ``` ## 확장 개인 키 가져오기 확장 개인 키를 가져오는 샘플 코드는 다음과 같습니다. 키의 언랩핑 후 인코딩 된 키의 BIP32 직렬화 형식이 디코딩 됩니다.(템플릿 키 유형은 BIP32에 대해 확인됨) 가져오기가 완료되면 언랩핑 된 키의 핸들이 `hUnwrappedKey`에 저장됩니다. ``` CK_ATTRIBUTE template[] = { {CKA_CLASS &keyClass, sizeof(keyClass)}, {CKA_TOKEN, &bToken, sizeof(bToken)}, {CKA_KEY_TYPE &keyType, sizeof(keyType)}, {CKA_PRIVATE, &bTrue, sizeof(bTrue)}, {CKA_DERIVE, &bTrue, sizeof(bTrue)}, {CKA_MODIFIABLE, &bTrue, sizeof(bTrue)}, {CKA_LABEL, pbLabel, strlen(pbLabel)}, {CKA_SENSITIVE &bTrue, sizeof(bTrue)}, }; CK_CHAR_PTR encodedKey = “xprv9s21ZrQH143K3QTDL4LXw2F…”; CK_MECHANISM mechanism = {CKM_AES_KWP, NULL, 0}; CK_BYTE wrappedKey[256]; CK_ULONG wrappedKeyLen = sizeof(wrappedKey); CK_OBJECT_HANDLE hUnwrappedKey; CK_RV rv = C_EncryptInit(hSession, &mechanism, hWrappingKey); // fail if rv != CKR_OK rv = C_Encrypt(hSession, encodedKey, sizeof(encodedKey), wrappedKey, &wrappedKeyLen); // fail if rv != CKR_OK rv = C_UnwrapKey(hSession, &mechanism, hWrappingKey, wrappedKey, wrappedKeyLen, template, ARRAY_SIZE(template), &hUnwrappedKey); ``` ## 확장 개인 키 내보내기 확장 개인 키를 내보내는 샘플 코드는 다음과 같습니다. 키 랩핑 전에 `C_WrapKey()`는 BIP32 키를 BIP32 직렬화 형식으로 변환시켜야 합니다. 내보내기가 완료되면 직렬화된 키가 `key`에 저장됩니다. ``` CK_MECHANISM mechanism = {CKM_AES_KWP, NULL, 0}; CK_BYTE key[256]; CK_ULONG keyLen = sizeof(key); CK_RV rv = C_WrapKey(hSession, &mechanism, hWrappingKey, hKeyToWrap, key, &keyLen); // fail if rv != CKR_OK rv = C_DecryptInit(hSession, &mechanism, hWrappingKey); // fail if rv != CKR_OK rv = C_Decrypt(hSession, key, keyLen, key, &keyLen); // fail if rv != CKR_OK key[keyLen] = 0 // The key isn’t NULL terminated after C_Decrypt(). ``` ## PKCS#11 명세 암호화 표준인 PKCS#11의 명세는 다음과 같습니다. ``` #define CKK_BIP32 (CKK_VENDOR_DEFINED | 0x14) #define CKM_BIP32_MASTER_DERIVE (CKM_VENDOR_DEFINED | 0xE00) #define CKM_BIP32_CHILD_DERIVE (CKM_VENDOR_DEFINED | 0xE01) #define CKR_BIP32_CHILD_INDEX_INVALID (CKR_VENDOR_DEFINED | 0x83) #define CKR_BIP32_INVALID_HARDENED_DERIVATION (CKR_VENDOR_DEFINED | 0x84) #define CKR_BIP32_MASTER_SEED_LEN_INVALID (CKR_VENDOR_DEFINED | 0x85) #define CKR_BIP32_MASTER_SEED_INVALID (CKR_VENDOR_DEFINED | 0x86) #define CKR_BIP32_INVALID_KEY_PATH_LEN (CKR_VENDOR_DEFINED | 0x87) #define CKA_BIP32_CHAIN_CODE (CKA_VENDOR_DEFINED | 0x1100) #define CKA_BIP32_VERSION_BYTES (CKA_VENDOR_DEFINED | 0x1101) #define CKA_BIP32_CHILD_INDEX (CKA_VENDOR_DEFINED | 0x1102) #define CKA_BIP32_CHILD_DEPTH (CKA_VENDOR_DEFINED | 0x1103) #define CKA_BIP32_ID (CKA_VENDOR_DEFINED | 0x1104) #define CKA_BIP32_FINGERPRINT (CKA_VENDOR_DEFINED | 0x1105) #define CKA_BIP32_PARENT_FINGERPRINT (CKA_VENDOR_DEFINED | 0x1106) #define CKG_BIP32_VERSION_MAINNET_PUB (0x0488B21E) #define CKG_BIP32_VERSION_MAINNET_PRIV (0x0488ADE4) #define CKG_BIP32_VERSION_TESTNET_PUB (0x043587CF) #define CKG_BIP32_VERSION_TESTNET_PRIV (0x04358394) #define CKG_BIP44_PURPOSE (0x0000002C) #define CKG_BIP44_COIN_TYPE_BTC (0x00000000) #define CKG_BIP44_COIN_TYPE_BTC_TESTNET (0x00000001) #define CKG_BIP32_EXTERNAL_CHAIN (0x00000000) #define CKG_BIP32_INTERNAL_CHAIN (0x00000001) #define CKG_BIP32_MAX_SERIALIZED_LEN (112) #define CKF_BIP32_HARDENED (0x80000000) #define CKF_BIP32_MAX_PATH_LEN (255) ```