> For the complete documentation index, see [llms.txt](https://docs.medcrypt.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.medcrypt.com/ko/guardian/understand-device-provisioning/extract-certificates-from-provisioned-devices.md).

# 프로비저닝된 기기에서 인증서 추출

## API를 통해 인증서 추출

Guardian API를 통해 키와 인증서를 추출하려면 Guardian Library를 사용하여 인증서 및 키 추출의 두 단계를 완료해야 합니다.

### **C# 예제**

```csharp
public static void GetKeyAndCerts()
{
    medcrypt.guardian.InitializeFiles initializeFiles =
        new medcrypt.guardian.InitializeFiles();

    /* 프로비저닝된 파일을 파일 구조로 읽어 들임 */
    initializeFiles.trustStore =
        File.ReadAllBytes(@"TrustStore.mcts");
    initializeFiles.privateIdentity =
        File.ReadAllBytes(@"PrivateIdentity.mcpi");
    initializeFiles.certifiedProfile =
        File.ReadAllBytes(@"CertifiedProfile.mcp");

    /* 프로비저닝 시스템에 관한 고객 데이터 */
    string componentHandle = "my_component_handle";
    string hardwareId = "my_serial_number";
    string serviceName = "my_service_name";

    /* 입력 옵션을 사용하거나 기본값 생성 */
    medcrypt.guardian.InitializeOptions options =
       new medcrypt.guardian.InitializeOptions();

    /* 구성된 작업(키 및 인증서)을 위해 guardian 초기화 */
    medcrypt.guardian.Guardian gdn = new medcrypt.guardian.Guardian();

    gdn.Initialize(
        initializeFiles,
        componentHandle,
        hardwareId,
        new medcrypt.guardian.InitializeOptions());

    List<byte[]> certs = null;
    byte[] key = null;

    medcrypt.guardian.IService service = gdn.FindService(serviceName);

    /* 키 가져오기 */
    key = service.GetCertificateKey(KeyFormat.PKCS8_PEM);

    /* 인증서 체인의 길이를 가져오고 모든 인증서를 출력
        목록에 추가 */
    ulong chainLen = service.GetCertificateChainLength();
    certs = new List<byte[]>();
    for (ulong i = 0; i < chainLen; i++)
    {
        certs.Add(service.GetCertificate(i, CertFormat.PEM));
    }
}
```

### **C++ 예제**

```cpp
#include "medcrypt/guardian/GuardianSystem.h"
#include "medcrypt/guardian/Utilities/Files/FileHelpers.h"

#define MSG(x) { printf x; printf("\n"); }
#define MSG_INFO(x) { MSG(x); }
#define MSG_ERROR(x) { printf("ERROR: "); MSG(x); }
#define MSG_WARNING(x) { printf("WARNING: "); MSG(x); }
#define ARBITRARY_KEY_SIZE 128
#define ARBITRARY_CERT_SIZE 3 * 1024

bool GetKeyAndCerts()
{
    medcrypt::guardian::Status status;
    medcrypt::guardian::utilities::InitializeFiles in_files;
    std::string in_component_handle = "my_component_handle";
    std::string in_hardware_id = "my_serial_number";
    std::string in_provisioning_profile_folder =
        "/path/to/provisioned/profile/folder/";
    std::string in_service_name = "my_service_name";

    /* 제공된 guardian 초기화 */
    medcrypt::guardian::Guardian guardian;
    status = guardian.Initialize(
        in_files,
        in_component_handle.c_str(),
        in_hardware_id.c_str(),
        medcrypt::guardian::InitializeOptions());

    /* OK가 아닌 오류 코드 확인 및 출력 */
    if (EXTRACT_STATUS(status) != medcrypt::guardian::GuardianStatusEnum::OK) {
        MSG_ERROR(("guardian을 초기화할 수 없습니다 [%s]",
            medcrypt::guardian::GuardianStatusEnum::NameOf(
                EXTRACT_STATUS(status)).c_str()));
        return false;
    }

    std::unique_ptr<medcrypt::guardian::Service> service;
    /* 이름으로 원하는 서비스를 찾음 */
    status = guardian.FindService(in_service_name.c_str(), &service);

    /* OK가 아닌 오류 코드 확인 및 출력 */
    if (EXTRACT_STATUS(status) != medcrypt::guardian::GuardianStatusEnum::OK) {
        MSG_ERROR(("서비스를 찾을 수 없음 [%s] [%s]",
            in_service_name.c_str(),
            medcrypt::guardian::GuardianStatusEnum::NameOf(
                EXTRACT_STATUS(status)).c_str()));
        return false;
    }

    std::list<std::vector<char>> io_certs;
    std::vector<unsigned char> io_key;

    io_key.assign(ARBITRARY_KEY_SIZE, '\0');
    size_t size = io_key.size();

    /* pkcs8 인코딩 키 가져오기 */
    status = service->GetCertificateKey(io_key.data(), &size);
    if (EXTRACT_STATUS(status) != medcrypt::guardian::GuardianStatusEnum::OK) {
        MSG_ERROR(("키를 가져올 수 없음 [%s]",
            medcrypt::guardian::GuardianStatusEnum::NameOf(
                EXTRACT_STATUS(status)).c_str()));
        return false;
    }
    io_key.resize(size);

    /* 인증서 체인에서 사용 가능한 인증서 모두 가져오기 */
    size_t chain_length = service->GetCertificateChainLength();
    io_certs.clear();
    for (size_t i = 0; i < chain_length; i++) {
        io_certs.emplace_back();
        size = service->GetCertificateSize(i);
        io_certs.back().assign(size, '\0');

        /* 인증서 가져오기 */
        status = service->GetCertificate(
            i,
            io_certs.back().data(),
            &size);

        if (EXTRACT_STATUS(status) != medcrypt::guardian::GuardianStatusEnum::OK) {
            MSG_ERROR(("인증서를 가져올 수 없습니다 [%u] [%s]",
                (unsigned int)i,
                medcrypt::guardian::GuardianStatusEnum::NameOf(
                    EXTRACT_STATUS(status)).c_str()));
            return false;
        }
    }

    return true;
}
```

###

### C 예제

```c
#define MAX_GDN_SIZE 15 * 1024 /* 필요에 따라 늘리십시오. 이 메모리는 스택에 할당할 필요가 없습니다. */
#define ARBITRARY_BUF_SIZE 5 * 1024 /* 필요에 따라 늘리십시오 */
#define ARBITRARY_KEY_SIZE 128
#define ARBITRARY_CERT_SIZE 3 * 1024
#define LEAF_CERT_IDX 0

/* guardian 스트림에서 사용할 쓰기 콜백 예제 설정 */
static bool sample_callback(mcg_guardian_ostream_t *stream,
                            const uint8_t *buf,
                            size_t count)
{
    size_t i;
    uint8_t *dest = (uint8_t*)stream->state;
    stream->state = dest + count;

    for (i = 0; i < count; i++)
        dest[i] = buf[i];

    return true;
}

static bool get_key_and_certs()
{
    mcg_status status = MCG_STATUS_FAIL;
    mcg_initialize_options_t init_options = {0};
    mcg_initialize_files_t init_files;
    mcg_guardian_istream_t ts, pi, cp;
    size_t cert_chain_path_length = 0;
    size_t cert_chain_length = 0;

    /* guardian 메모리 영역을 생성합니다. 이 메모리는 어떤 소스에서 가져와도 되지만
        연속된 블록이어야 합니다. */
    mcg_memory_t mcg_memory = {NULL, 0, 0};
    uint8_t memory_buffer[MAX_GDN_SIZE] = {0};
    mcg_memory.mem = &memory_buffer[0];
    mcg_memory.size = sizeof(memory_buffer);

    /* 이 프로비저닝 시스템에 관한 고객 데이터 */
    char component_handle[] = "my_component";
    char hardware_id[] = "my_serial_number";
    char service_name[] = "my_service";

    /* 트러스트 저장소를 이 버퍼로 읽고, in_ts_len을 실제 크기로 설정합니다 */
    uint8_t in_ts[ARBITRARY_BUF_SIZE] = {0};
    size_t in_ts_len = 1234;

    /* 개인 ID를 이 버퍼로 읽고, in_pi_len을 실제 크기로 설정합니다 */
    uint8_t in_pi[ARBITRARY_BUF_SIZE] = {0};
    size_t in_pi_len = 1234;

    /* 인증된 프로필을 이 버퍼로 읽고, in_cp_len을 실제 크기로 설정합니다 */
    uint8_t in_cp[ARBITRARY_BUF_SIZE] = {0};
    size_t in_cp_len = 1234;

    /* 출력 버퍼 */
    uint8_t io_key_buf[ARBITRARY_BUF_SIZE] = {0};
    size_t io_key_buf_len = sizeof(io_key_buf);

    uint8_t io_cert_buf[ARBITRARY_BUF_SIZE] = {0};
    size_t io_cert_buf_len = sizeof(io_cert_buf);

    mcg_guardian_ostream_t out_key;
    mcg_guardian_ostream_t out_cert;

    /* 제공된 ts/pi/cp 바이트 버퍼에서 스트림을 생성합니다. */
    ts = mcg_istream_from_buffer((const uint8_t*)in_ts, in_ts_len);
    pi = mcg_istream_from_buffer((const uint8_t*)in_pi, in_pi_len);
    cp = mcg_istream_from_buffer((const uint8_t*)in_cp, in_cp_len);

    /* 스트림을 mcg_initialize_files_t에 로드합니다 */
    init_files.trust_store = &ts;
    init_files.private_identity = &pi;
    init_files.certified_profile = &cp;

    status = mcg_gdn_initialize(
        &mcg_memory,
        &init_files,
        component_handle,
        hardware_id,
        &init_options);

    if (status)
    {
        /* Return failure */
        return false;
    }

    /* setup buffer backed key output stream */
    out_key.write_callback = &sample_callback;
    out_key.max_size = io_key_buf_len;
    out_key.bytes_written = 0;
    out_key.state = io_key_buf;

    status = mcg_gdn_write_key(&mcg_memory,
                             service_name,
                             true, /* true = PEM, false = DER */
                             &out_key);
    if (status)
    {
        printf("Failed to write key");
        return false;
    }

    /* setup buffer backed single cert output stream */
    out_cert.write_callback = &sample_callback;
    out_cert.max_size = io_cert_buf_len;
    out_cert.bytes_written = 0;
    out_cert.state = io_cert_buf;

    status = mcg_gdn_write_cert(&mcg_memory,
                        service_name,
                        LEAF_CERT_IDX, /* Note: Only writes a single certificate */
                        true, /* true = PEM, false = DER */
                        &out_cert);

    if (status)
    {
        printf("Failed to write cert");
        return false;
    }

    return true;
}
```

## 명령줄을 통해 인증서 추출

프로비저닝된 디바이스를 사용하여 해당 디바이스의 인증 프로필(CP)에서 사전 설정된 키와 인증서를 추출하는 방법을 설명합니다. 명령줄을 통한 인증서 추출은 다음 인증서 및 키 추출 단계를 수행하는 `mcguard_cert_extract` 유틸리티를 사용하는 방식으로 진행됩니다.

1. 디바이스의 인증 프로필을 사용하여 Guardian을 초기화합니다.
2. 키와 필요한 인증서를 추출합니다.

* 모든 명령줄 유틸리티는 작업 디렉터리 방식을 사용합니다. 인증서를 추출하는 동안 `mcguard_cert_extract` 유틸리티는 작업 디렉터리에 다음 파일이 있는지 확인합니다. `.mcts`, `.mcpip` 및 `.mcpp` 파일입니다.
* 꺾쇠괄호 <> 안의 인수는 표시된 입력 데이터로 바꿔야 합니다(예: 구성 요소 핸들이 device1인 경우 `<my_component>` , 이를 다음과 같이 바꿀 수 있습니다. `device1`).

```bash
# 구문 
./mcguard_cert_extract --component <my_component> --hardware-id <my_hardwareid> --service <my_service> --key-dir <key_output_dir> --cert-dir <cert_output_dir> <path to provisioned profile>

# 예시
./mcguard_cert_extract --component my_device --hardware-id my_device_001 --service my_service --key-dir /home/user/guardian/keys --cert-dir /home/user/guardian/certs /home/user/guardian/provisioned_profile
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.medcrypt.com/ko/guardian/understand-device-provisioning/extract-certificates-from-provisioned-devices.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
