- 인쇄
- PDF
샘플 코드
- 인쇄
- PDF
VPC 환경에서 이용 가능합니다.
키를 생성하거나 가져오고 내보낼 때 사용되는 샘플 코드를 설명합니다.
BIP32 메커니즘 구현은 Thales 공식 문서를 기반으로 작성되었습니다. 사용 가이드에서 안내하는 내용 외에 더 많은 내용을 살펴보려면 BIP32 Mechanism Support and Implementation을 참고해 주십시오.
마스터 키 페어 파생
권한이 없는 사용자가 체인 코드를 볼 수 없도록 마스터 공개 및 개인 키의 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)