---
title: "도브러너 DRM 키 임포트 API 가이드"
description: "도브러너 DRM 키 임포트 API를 사용하여 기존 콘텐츠 암호화 키 데이터를 도브러너 키 데이터베이스로 가져올 수 있습니다."
---
> For the complete documentation index, see [llms.txt](/llms.txt).

`도브러너 DRM 키 임포트 API`는 기존 콘텐츠 암호화 키 데이터를 도브러너 키 데이터베이스로 임포트할 때 사용할 수 있는 API입니다. 도브러너 라이선스 서버를 이용해 DRM 라이선스를 생성하기 위해서는 사전에 DRM 키 데이터를 임포트하거나 라이선스 요청 시 해당 콘텐츠의 키를 토큰에 설정(`외부 키` 방식 연동)해야 합니다.

이 API의 사용 사례는 크게 두 가지입니다.

- **타 DRM 서비스 제공사에서 마이그레이션하는 경우**
	- 타 DRM 서비스를 사용하다가 도브러너 멀티DRM 서비스로 전환하고자 하는 경우, 이 API를 통해 기존 DRM 콘텐츠의 키 데이터를 가져올 수 있습니다.
	- 임포트할 키 데이터가 많을 경우에는 별도의 일괄 가져오기(Bulk import) 프로세스에 대해 헬프데스크로 문의하시기 바랍니다.
- **두 개의 DRM 서비스 업체 동시 이용하기**
	- 가용성을 위해 도브러너와 타 DRM 서비스를 동시에 사용하고자 하는 경우, 타 DRM 업체를 통해 패키징된 콘텐츠의 키 데이터를 이 API를 사용하여 도브러너 키 서버로 가져올 수 있습니다.

## 전제 조건

키 임포트 API를 이용하기 위해서는 도브러너 서비스에 계정이 있어야 하며, 도브러너 콘솔의 DRM 설정 화면 또는 헬프데스크를 통해 `사이트 키`, `액세스 키`, `KMS 토큰`을 발급받아야 합니다. 그 후 아래 사양에 따라 API를 연동합니다.

## API 요청

### 요청 URL 및 메소드

- URL: `https://drm-kms.doverunner.com/v2/importKey/{kmsToken}`

> `{kmsToken}` 부분의 경우 도브러너 콘솔 또는 헬프데스크를 통해 확인한 KMS 토큰 값으로 대체해야 합니다.

- 메소드: `POST` (데이터 추가용) / `PUT` (기존 데이터 업데이트용)

### 요청 본문

API 요청 URL을 호출할 때 요청 본문(request body)을 아래에 설명된 JSON 데이터로 설정합니다.

```json
{
    "data": "<암호화된 `콘텐츠 목록 JSON` 데이터>",
    "timestamp": "<요청 시점의 타임스탬프>",
    "hash": "<해시 값>"
}
```

|명칭 |형식 |설명 |
|:---|:---|:---|
|`data` |String | AES 암호화된 `콘텐츠 목록 JSON` (Base64 인코딩) |
|`timestamp` |String | 요청 데이터 생성 시점의 타임스탬프 값. `yyyy-mm-ddThh:mm:ssZ` 형식 (GMT 시간대) |
|`hash` |String | `access key`, `data`, `timestamp` 값을 연결한 문자열의 SHA256 해시 값 |

#### 요청 본문 예제

```json
{
  "data" : "gU/IyXPvB58D0LxvJblM980lUG7is1RtW4uDO1n+PBD5j942YEZTQEvtYWemITBuXwZsrh/y6XLdRnqt7zGKcSu6IgpEZiXkjfGN6QkejtGKw9tNfX34P9p2HOjioTyaGxKS9UyxgkxWdT5TUvTsBAZMyTXfKz7pyYtH8Db5WtSC6+Ve6i1U+uSVwJ383/ukZ1uIsfIxqW8Sd2hjBHcFlJwDgereHb0e79",
  "timestamp" : "2023-04-14T23:59:59Z",  
  "hash" : "XokH+97vUFgrtNthJQnRn1xQ2LXrwTm+UYqhWZT06CE="
}
```

위 JSON 데이터의 각 항목를 생성하기 위한 규격은 다음의 안내를 참고하시기 바랍니다.

### 콘텐츠 목록 JSON

키를 임포트할 콘텐츠에 대한 정보를 다음과 같이 JSON 형식으로 생성합니다.

```json
{
    "content_list": [
        {
            "content_id": "<해당 콘텐츠의 고유 ID>",
            "content_key_list": [
                {
                    "track_type": "<키 값이 적용될 트랙 형식>",
                    "key_id": "<키 ID (16 바이트 길이 16진수 문자열)>",
                    "key": "<암호화 키 (16 바이트 길이 16진수 문자열)>",
                    "iv": "<초기화 벡터 값 (16 바이트 길이 16진수 문자열)>"
                }
            ]
        }
    ]
}
```

|명칭 |형식 |설명 |
|:---|:---|:---|
| `content_list` | JSON array  | 키 임포트 대상 콘텐츠 목록. API 요청 당 최대 100개 콘텐츠까지 입력 가능. |
| `content_id` | String | 콘텐츠의 고유 ID (CID). 최대 200바이트 영숫자 또는 `-`(하이픈), `_`(언더바) 문자. |
| `content_key_list` | JSON array | 해당 콘텐츠에 사용된 암호화 키 데이터 목록. 콘텐츠가 여러 개의 암호화 키로 패키징된 경우, 하나의 콘텐츠에 대해 여러 개의 키 데이터가 있을 수 있습니다. |
| `track_type` | String | 아래 키 데이터가 적용될 트랙을 정의.<br/>- 입력값: `ALL`, `VIDEO`, `AUDIO`, `SD`, `HD`, `UHD1`, `UHD2` 중 하나 |
| `key_id` | String | 키 ID (16 바이트 길이 16진수 문자열) |
| `key` | String | 암호화 키 (16 바이트 길이 16진수 문자열) |
| `iv` | String | 초기화 벡터 값 (16 바이트 길이 16진수 문자열) |

#### 콘텐츠 목록 JSON 예제

**단일 키로 암호화된 두 개의 콘텐츠에 대한 키 데이터 전송**

단일 키로 암호화된 싱글키 콘텐츠의 경우, 오디오 트랙의 암호화 여부에 따라 다음과 같이 키 데이터를 설정할 수 있습니다.

```json
{
    "content_list": [
        {
            "content_id": "content-id-0001",
            "content_key_list": [
                {
                    "track_type": "ALL",   // 싱글키로 비디오 오디오 모두 암호화한 경우
                    "key_id": "43FB9B380AD674A3543125012C3ADC81",
                    "key": "01DF8CCCA8BC6CE330DDDC3A425AABA6",
                    "iv": "A43343F998724B1C335C44356D2E5A54"
                }
            ]
        },
        {
            "content_id": "content-id-0002",
            "content_key_list": [
                {
                    "track_type": "VIDEO",  // 싱글키로 비디오 트랙만 암호화한 경우 (오디오 암호화 스킵)
                    "key_id": "A08A04D48DD356B02C3E609876740475",
                    "key": "864355D6D5B4A1AD6106A93ED096C2CB",
                    "iv": "CCEB68525D22467EE488307B248D3A3C"
                }
            ]
        }
    ]
}
```

**멀티키 패키징된 하나의 콘텐츠 키 데이터 전송**

하나의 콘텐츠 내 비디오/오디오 트랙 별로 서로 다른 암호화 키가 사용된 멀티키 콘텐츠의 경우, 다음과 같이 트랙 별 암호화 키를 설정할 수 있습니다. 비디오 트랙에 `SD`, `HD`, `UHD1` 등의 트랙 유형을 사용하면 각 해상도 트랙 별로 서로 다른 키를 설정할 수 있습니다.

```json
{
    "content_list": [
        {
            "content_id": "multi-key-content-0001",
            "content_key_list": [
                {
                    "track_type": "VIDEO",
                    "key_id": "43FB9B380AD674A3543125012C3ADC81",
                    "key": "01DF8CCCA8BC6CE330DDDC3A425AABA6",
                    "iv": "A43343F998724B1C335C44356D2E5A54"
                },
                {
                    "track_type": "AUDIO",
                    "key_id": "A08A04D48DD356B02C3E609876740475",
                    "key": "864355D6D5B4A1AD6106A93ED096C2CB",
                    "iv": "CCEB68525D22467EE488307B248D3A3C"
                }
            ]
        }
    ]
}
```

### AES256 암호화 및 Base64 인코딩

위와 같이 콘텐츠 목록 JSON을 생성한 후, 아래 정보를 사용하여 해당 JSON 문자열을 암호화합니다.

> AES256 암호화
> - 모드: CBC
> - 키: 32바이트 (도브러너 계정에 대해 생성된 사이트 키 값)
> - iv: 16바이트(0123456789abcdef)
> - 패딩: pkcs7

암호화 결과는 Base64 알고리듬으로 인코딩해야 합니다. 암호화 및 인코딩 구현은 다음 예제 코드를 참조하시기 바랍니다. 최종 결과(base64로 인코딩된 AES 암호화 문자열)는 요청 본문 JSON에 `data` 값으로 설정합니다.

```js
const crypto = require("crypto");

const cipher = crypto.createCipheriv("aes-256-cbc", siteKey, aesIv);
let encryptedJsonData = cipher.update(
  JSON.stringify(contentListJson),
  "utf-8",
  "base64"
);
encryptedJsonData += cipher.final("base64");
```

> 위 예제는 완전한 작동 코드가 아닙니다. 예제를 참고해 실제 고객사에서 사용하는 개발 언어를 통해 암호화 및 인코딩 코드를 구현하시기 바랍니다.

### 해시 값 생성

요청 본문 JSON 데이터의 마지막 부분은 `해시` 값입니다. 해시는 전체 요청 JSON 값의 무결성을 확인하는 데 사용되며 다음과 같이 생성되어야 합니다.

```sh
base64(sha256(<엑세스 키> + <data 문자열> + <타임스탬프 값>))
```

- `엑세스 키`: 도브러너 계정에 대해 생성된 액세스 키 값
- `data 문자열`: AES로 암호화된 콘텐츠 목록 JSON의 base64 문자열. 요청 본문 JSON의 `data`와 동일한 값.
- `타임스탬프 값`: 요청 데이터 생성 시점의 현재 시간. (`yyyy-mm-ddThh:mm:ssZ` 형식, GMT 시간대) 요청 본문 JSON의   `timestamp`와 동일한 값.

#### 해시 입력 문자열 예제

타임스탬프 및 해시 입력 문자열 생성은 아래 예제 코드를 참조하시기 바랍니다.

```js
const timestamp = new Date().toISOString().replace(/\.\d{3}/gi, '');

let accessKey = "LT2FVJDp2Xr018zf4Di6lzvNOv3DKP20";
let data = "gU/IyXPvB58D0LxvJblM980lUG7is1RtW4uDO1n+PBD5j942YEZTQEvtYWemITBuXwZsrh/y6XLdRnqt7zGKcSu6IgpEZiXkjfGN6QkejtGKw9tNfX34P9p2HOjioTyaGxKS9UyxgkxWdT5TUvTsBAZMyTXfKz7pyYtH8Db5WtSC6+Ve6i1U+uSVwJ383/ukZ1uIsfIxqW8Sd2hjBHcFlJwDgereHb0e79";

const hashInput = accessKey + data + timestamp;

let hashString = crypto
  .createHash("sha256")
  .update(hashInput)
  .digest("base64");
```

> 위 예제는 완전한 작동 코드가 아닙니다. 예제를 참고해 실제 고객사에서 사용하는 개발 언어를 통해 암호화 및 인코딩 코드를 구현하시기 바랍니다.

## API 응답

### 응답 규격

요청 본문 JSON 데이터와 함께 API URL을 호출하면 아래와 같은 응답 데이터를 받게 됩니다.

```json
{
	"error_code": "<error code>",
	"message": "<error message>"
}
```

### 에러 코드

|코드 |메시지 |설명 |
|:---|:---|:-----|
| 0000 | Success | 키 데이터를 도브러너 KMS로 성공적으로 가져왔습니다. |
| 2509 | Failed to insert the key list | 도브러너 API 서버에 문제가 발생했습니다. 헬프데스크로 문의해 주세요. |
| 2510 | Failed to decrypt the required value | `data` 값의 복호화에 실패했습니다. 해당 값과 관련된 API 요청 구현을 확인해 주세요. |
| 2511 | Content ID already exists | 시스템에 이미 등록된 콘텐츠 ID의 키 데이터는 신규 등록할 수 없습니다. 데이터를 업데이트하려면 `POST` 대신 `PUT` 방식을 사용하시기 바랍니다. |
| 2512 | The number of contents exceed 100 | 한 번의 API 요청에 100개 이상의 콘텐츠 ID를 입력할 수 없습니다. |
| 2513 | Hash verification failed | 해시 문자열 생성에 문제가 있습니다. 규격에 따라 생성되었는지 다시 확인해 주시기 바랍니다. |
| 2514 | Failed to update the key list | 도브러너 API 서버에 문제가 발생했습니다. 헬프데스크로 문의해주세요. |