샘플 코드

Prev Next

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

키를 생성하거나 가져오고 내보낼 때 사용되는 샘플 코드를 설명합니다.

참고

BIP32 메커니즘 구현은 Thales 공식 문서를 기반으로 작성되었습니다. 사용 가이드에서 안내하는 내용 외에 더 많은 내용을 살펴보려면 BIP32 Mechanism Support and Implementation을 참고해 주십시오.

권한이 없는 사용자가 체인 코드를 볼 수 없도록 마스터 공개 및 개인 키의 CKA_PRIVATETRUE로 설정해 주십시오. 마스터 키는 키 파생 시에만 사용해야 합니다. 템플릿에 속성이 없는 경우 공개/개인 키의 버전 바이트 기본값은 0x0488B21E/0x0488ADE4이며, 이는 메인 비트코인 네트워크의 키에 대한 BIP32에 명시된 값입니다.

마스터 키 페어를 파생하는 샘플 코드는 다음과 같습니다. 파생이 완료되면 새로운 키 핸들이 pubKeyprivKey에 저장됩니다.

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;
Plain text

권한이 없는 사용자가 체인 코드를 볼 수 없도록 마스터 공개 및 개인 키의 CKA_PRIVATETRUE로 설정해 주십시오. 하위 리프 키(키 트리 최하단에 위치한 키)는 파생에 사용할 수 없으며 서명, 확인, 암호화 및 복호화에 사용해야 합니다. 부모 자식 키를 사용하려면 파생 속성을 설정해야 합니다. 템플릿에 속성이 없는 경우 공개/개인 키의 버전 바이트 기본값은 0x0488B21E/0x0488ADE4이며, 이는 메인 비트코인 네트워크의 키에 대한 BIP32에 명시된 값입니다.

하위 리프 키를 파생하는 샘플 코드는 다음과 같습니다. 파생이 완료되면 새로운 키 핸들이 pubKeyprivKey에 저장됩니다. 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;
Plain text

확장 공개 키를 가져오는 샘플 코드는 다음과 같습니다. 가져오기가 완료되면 새로 생성된 키의 핸들이 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);
Plain text

확장 공개 키를 내보내는 샘플 코드는 다음과 같습니다. 내보내기가 완료되면 인코딩 된 키가 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 );
Plain text

확장 개인 키를 가져오는 샘플 코드는 다음과 같습니다. 키의 언랩핑 후 인코딩 된 키의 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); 
Plain text

확장 개인 키를 내보내는 샘플 코드는 다음과 같습니다. 키 랩핑 전에 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().
Plain text

암호화 표준인 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)
Plain text