MariaDB의 암호화 plugin은 테이블 암호화 기능에 사용됩니다. 암호화 plugin은 키 관리, 실제 데이터의 암호화 및 복호화에 대해 책임이 있습니다.

개념상 책임은 다음과 같이 나뉘어져 있습니다. — 객체를 암호화할 때 (now tables, later may be more) 사용자는 객체에 대한 logical security domain(암호화 키 식별자)을 명시합니다. plugin은 특정한 키 식별자에 대한 actual security policy를 시행합니다. plugin은 어떤 암호화 알고리즘과 사용될 키 길이를 정의합니다. 얼마나 자주 키가 변경 되어야 하는 지 등. 이 모든 것들은 암호화 키 식별자에 의존할 수 있습니다. 예를들어, plugin은 두 개의 키 식별자를 제고알 수 있다면 — 10, "낮은 보안"은 rotation없고 빠른 암호화 알고리즘의 짧은 키를 갖음 그리고 20, "높은 보안"은 긴 키를 갖음. 이것은 자주 변경되고 느리지만 더 보안적인 암호화 알고리즘이다. 사용자는 어떤 테이블이 어떤 키 식별자에 사용되어야 할 지 선택합니다. 사용자는 자신의 데이터를 알고 어떤 보안 정책을 사용할 지 높은 레벨에서 명시합니다. plugin은 이 보안 정책을 구현합니다.

두개의 key 식별자는 MariaDB안에 사용하기 위해 예약해놓습니다. Key id 1은 Inno DB의 redo logs, binary logs 등과 같이 system data를 암호화하는 데 사용됩니다. 이는 항상 존재해야 합니다. Key id 2는 temporary files과 temporary table과 같이 일시적인 data를 암호화할 때 사용합니다. 이것들은 선택적이며 만약 존재하지 않으면 key id 1이 대신 사용되어질 수 있습니다.

Encryption Plugin API

암호화 plugin API는 다음을 할 수 있도록 하기 위해 만들어졌습니다 :

  • 키 관리를 구현하는 것, 요청에 따라 서버에 암호화 키를 제공하고 내부 정책에 의해 그것들을 변경합니다.
  • plugin에 의해 정의된 알고리즘으로 실제 데이터 암호화 및 복호화를 구현하는 것

API 반영하는 법은 다음과 같습니다 :

/* returned from get_latest_key_version() */
#define ENCRYPTION_KEY_VERSION_INVALID        (~(unsigned int)0)
#define ENCRYPTION_KEY_NOT_ENCRYPTED          (0)

#define ENCRYPTION_KEY_SYSTEM_DATA             1
#define ENCRYPTION_KEY_TEMPORARY_DATA          2

/* returned from get_key()  */
#define ENCRYPTION_KEY_BUFFER_TOO_SMALL    (100)

typedef int (*encrypt_decrypt_func)(const unsigned char* src, unsigned int slen,
                                    unsigned char* dst, unsigned int* dlen,
                                    const unsigned char* key, unsigned int klen,
                                    const unsigned char* iv, unsigned int ivlen,
                                    int no_padding, unsigned int key_id,
                                    unsigned int key_version);

struct st_mariadb_encryption
{
  int interface_version;                        /**< version plugin uses */

  /**
    function returning latest key version for a given key id

    @return a version or ENCRYPTION_KEY_VERSION_INVALID to indicate an error.
  */
  unsigned int (*get_latest_key_version)(unsigned int key_id);

  /**
    function returning a key for a key version

    @param key_id       the requested key id
    @param version      the requested key version
    @param key          the key will be stored there. Can be NULL -
                        in which case no key will be returned
    @param key_length   in: key buffer size
                        out: the actual length of the key

    This method can be used to query the key length - the required
    buffer size - by passing key==NULL.

    If the buffer size is less than the key length the content of the
    key buffer is undefined (the plugin is free to partially fill it with
    the key data or leave it untouched).

    @return 0 on success, or
            ENCRYPTION_KEY_VERSION_INVALID, ENCRYPTION_KEY_BUFFER_TOO_SMALL
            or any other non-zero number for errors
  */
  unsigned int (*get_key)(unsigned int key_id, unsigned int version,
                          unsigned char *key, unsigned int *key_length);

  encrypt_decrypt_func encrypt;
  encrypt_decrypt_func decrypt;
};

첫번째 방법은 key rotation에 사용됩니다. key rotation을 지원하지 않는 plugin— 예, file_key_management — 은 어떤 유효한 key id에 대한 고정된 버전을 반환할 수 있습니다. 유효하지 않은 key id에 대한 에러에도 반환해야 한다는 점에 유의하십시오. ENCRYPTION_KEY_NOT_ENCRYPTED는 데이터가 아직 암호화 되어지지 않았음을 의미합니다.

두번째 방법은 키 관리에 사용됩니다. 서버는 명확한 키 식별자와 명확한 키 버전에 상응하는 키를 회수하기 위해 사용합니다.

마지막 두 방법들은 실제 데이터를 암호화 및 복호화 하는 데 수행됩니다. 그들이 사용하는 키와 키 식별자 그리고 버전을 모두 가지고 있습니다. 서버는 get_key()에 의해 반환된 본래의 암호화 키로부터 session-specific, user-specific, or a tablespace-specific key를 얻을 수 있기 때문에 필요로 합니다. 한편, 암호화 알고리즘은 키 식별자와 버전에 의존할 수 있습니다. (example_key_management plugin 또한 암호화 알고리즘과 같이 키 식별자와 버전에 의존합니다) 그래서 plugin은 데이터를 암호화 하기 위해 그것들을 알 필요가 있습니다.

암호화/복호화 방법은 선택적입니다 — 만약 설정되지 않은 경우 ( debug_key_management plugin으로 ), 서버는 AES_CBC로 돌아갈 것입니다.

MariaDB 소스 트리는 세 암호화 plugin을 가지고 있습니다 :

  • file_key_management — 이 plugin은 파일로부터 암호화 키를 읽습니다. 암호화 키 식별자를 지원하고 암호화 키 버전은 지원하지 않습니다. 두 개의 암호화 알고리즘을 지원하며 사용자가 어떤 것을 사용할 지 선택하는 것을 허용합니다. 자세한 사항은 여기 참조.
  • example_key_management — 랜덤한 시간을 기반으로 생성된 키를 사용하고 키 식별자를 무시하며 키 rotation을 지원합니다. 암호화 알고리즘으로 AES_ECB 와AES_CBC를 사용하고 키 버전과 함께 그것들을 자동적으로 변경합니다.
  • debug_key_management — 키는 버전으로부터 생성되며, 사용자는 수동적으로 키 rotation을 제어합니다. 오직 key identifier 1을 지원하며, AES_CBC 만 사용합니다.

모든 이 plugin들은 꽤 간단하며 암호화 plugin API의 좋은 예들을 제공합니다.

Encryption Service

암호화는 일반적으로 스토리지 엔진 내부 매우 낮은 level에서 필요로 합니다. 이 스토리지 엔진은 암호화를 제공하고 암호화와 키 관리 기능에 접근하기 위해서 필요합니다. 서버에서 일부 기능에 대해 접근할 수 있는 plugin에 대해 일반적인 방법은 서비스를 통하는 것입니다. 이러한 경우 스토리지 엔진(그리고 기타 이해관계가 있는 plugin)을 사용할 수 있도록 서버는 암호화 서비스를 제공합니다. 이러한 서비스 기능들은 암호화 plugin에 방식에 연결되어 있습니다.( 위 설명과 같이 )

서비스 기능은 다음과 같이 선언합니다 :

unsigned int encryption_key_get_latest_version(unsigned int key_id);
unsigned int encryption_key_id_exists(unsigned int key_id);
unsigned int encryption_key_version_exists(unsigned int key_id, unsigned int key_version);
unsigned int encryption_key_get(unsigned int key_id, unsigned int key_version,
                                unsigned char*key_buf, unsigned int*key_length);
int encryption_encrypt(const unsigned char* src, unsigned int slen,
                       unsigned char* dst, unsigned int* dlen,
                       const unsigned char* key, unsigned int klen,
                       const unsigned char* iv, unsigned int ivlen,
                       int no_padding, unsigned int key_id, unsigned int key_version);
int encryption_decrypt(const unsigned char* src, unsigned int slen,
                       unsigned char* dst, unsigned int* dlen,
                       const unsigned char* key, unsigned int klen,
                       const unsigned char* iv, unsigned int ivlen,
                       int no_padding, unsigned int key_id, unsigned int key_version);

Comments

Comments loading...