Docs Menu
Docs Home
/ /

사용 중 암호화

사용 중 암호화는 MongoDB 컬렉션의 민감한 데이터를 암호화하는 두 가지 기능을 제공합니다.

  • 클라이언트 사이드 필드 레벨 암호화 - 클라이언트 사이드 특정 데이터 필드를 암호화합니다.

  • Queryable Encryption - 암호화됨 필드를 쿼리 기능 을 유지하면서 데이터를 암호화합니다.

두 기능 모두 서버 관리자를 포함한 권한이 없는 당사자가 암호화됨 데이터를 읽을 수 없도록 보장합니다.

사용 중 암호화 사용하려면 libmongocrypt 을 종속성으로 설치해야 합니다. 전체 설치 가이드는 MongoDB Server 매뉴얼의 libmongocrypt 설치 지침 을 참조하세요.

libmongocrypt을(를) 설치한 후 다음 예시 와 같이 -DENABLE_CLIENT_SIDE_ENCRYPTION=ON (으)로 C 운전자 구성하여 사용 중 암호화 활성화 .

$ cd mongo-c-driver
$ mkdir cmake-build && cd cmake-build
$ cmake -DENABLE_CLIENT_SIDE_ENCRYPTION=ON ..
$ cmake --build . --target install

자동 암호화 지원 하려면 다음 종속성 중 하나가 필요합니다.

  • mongocryptd 실행 파일입니다. 설치 지침은 MongoDB Server 매뉴얼의 mongocryptd 가이드를 참조하십시오.

  • crypt_shared 라이브러리. 자세한 내용은 MongoDB Server 매뉴얼의 자동 암호화 공유 라이브러리 가이드 참조하세요.

자동 암호화로 구성된 mongoc_client_t 또는 mongoc_client_pool_t 가 자동으로 crypt_shared 라이브러리를 로드하려고 시도합니다. crypt_shared 라이브러리 로드에 실패하면 mongoc_client_t 또는 mongoc_client_pool_t 가 애플리케이션의 PATH에서 mongocryptd 프로세스를 생성하려고 시도합니다. crypt_sharedmongocryptd 사용을 구성하려면 mongoc_auto_encryption_opts_set_extra를 참조하세요.

명시적 암호화 및 키 관리 위해서는 mongoc_client_encryption_t를 사용하세요. mongoc_client_enable_auto_encryptionmongoc_client_pool_enable_auto_encryption 을 사용하여 자동 암호화 활성화 .

Queryable Encryption (QE) 및 클라이언트 사이드 필드 레벨 암호화 (CSFLE) 기능은 몇 가지 예외를 제외하고는 대부분 동일한 API를 공유합니다.

관리자와 개발자는 CSFLE를 사용하여 다른 MongoDB 암호화 기능 외에도 특정 데이터 필드를 암호화할 수 있습니다.

CSFLE를 사용하면 서버 사이드 구성이나 지시문 없이 클라이언트 사이드에서 필드를 암호화할 수 있습니다. CSFLE는 서버 관리자를 포함한 권한이 없는 당사자가 암호화된 데이터를 읽을 수 없도록 애플리케이션이 보장해야 하는 워크로드를 지원합니다.

명령의 민감한 필드가 자동으로 암호화되는 자동 암호화 에는 쿼리 분석에 대한 엔터프라이즈 전용 종속성이 필요합니다. 자세한 내용은 쿼리 분석 을 참조하세요.

The Client-Side Field Level Encryption guide in the MongoDB Server manual

mongoc_client_t 객체 에서 mongoc_client_enable_auto_encryption 을 호출하여 자동 암호화 활성화합니다. 다음 예시에서는 mongoc_client_encryption_t 를 사용하여 새 암호화 데이터 키를 생성하고 자동 암호화 설정 방법을 보여 줍니다.

참고

자동 암호화 에는 MongoDB Enterprise Advanced 4.2 이상 또는 MongoDB 4.2 이상의 Atlas cluster 필요합니다. MongoDB Server 의 커뮤니티 버전은 자동 암호 해독 및 명시적 암호화를 지원합니다.

스키마 맵을 사용하여 자동 암호화 규칙을 지정할 수 있습니다. 스키마 맵을 생성하려면 mongoc_auto_encryption_opts_set_schema_map 함수를 호출합니다. 자동 암호화 규칙은 JSON Schema 구문의 엄격한 하위 집합을 사용합니다.

스키마 맵을 제공하면 서버 에서 얻은 JSON Schema에 의존하는 것보다 더 강력한 보안이 제공됩니다. 악의적인 서버 가 잘못된 JSON schema 를 광고하여 클라이언트 를 속여 암호화되어야 하는 암호화됨 되지 않은 데이터를 보내도록 할 수 있습니다.

스키마 맵에 제공된 JSON Schema는 자동 암호화 구성에만 적용 . JSON schema 의 다른 유효성 검사 규칙은 운전자 에서 적용되지 않으므로 오류가 발생합니다.

다음 예시 mongoc_auto_encryption_opts_set_schema_map() 함수를 사용하여 자동 암호화 규칙을 지정하는 스키마 맵을 만듭니다.

client-side-encryption-schema-map.c
#include <mongoc/mongoc.h>
#include <stdio.h>
#include <stdlib.h>
#define FAIL(...) \
fprintf(stderr, "Error [%s:%d]:\n", __FILE__, __LINE__); \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n"); \
abort();
// `init_bson` creates BSON from JSON. Aborts on error. Use the `BSON_STR()` macro to avoid quotes.
#define init_bson(bson, json) \
if (!bson_init_from_json(&bson, json, -1, &error)) { \
FAIL("Failed to create BSON: %s", error.message); \
}
int
main(void)
{
bson_error_t error;
// The key vault collection stores encrypted data keys:
const char *keyvault_db_name = "keyvault";
const char *keyvault_coll_name = "datakeys";
// The encrypted collection stores application data:
const char *encrypted_db_name = "db";
const char *encrypted_coll_name = "coll";
// Set `local_key` to a 96 byte base64-encoded string:
const char *local_key =
"qx/3ydlPRXgUrBvSBWLsllUTaYDcS/pyaVo27qBHkS2AFePjInwhzCmDWHdmCYPmzhO4lRBzeZKFjSafduLL5z5DMvR/"
"QFfV4zc7btcVmV3QWbDwqZyn6G+Y18ToLHyK";
const char *uri = "mongodb://localhost/?appname=client-side-encryption";
mongoc_init();
// Configure KMS providers used to encrypt data keys:
bson_t kms_providers;
{
char *as_json = bson_strdup_printf(BSON_STR({"local" : {"key" : "%s"}}), local_key);
init_bson(kms_providers, as_json);
bson_free(as_json);
}
// Set up key vault collection:
mongoc_client_t *keyvault_client;
{
keyvault_client = mongoc_client_new(uri);
if (!keyvault_client) {
FAIL("Failed to create keyvault client");
}
mongoc_collection_t *coll = mongoc_client_get_collection(keyvault_client, keyvault_db_name, keyvault_coll_name);
mongoc_collection_drop(coll, NULL); // Clear pre-existing data.
// Create index to ensure keys have unique keyAltNames:
bson_t index_keys, index_opts;
init_bson(index_keys, BSON_STR({"keyAltNames" : 1}));
init_bson(index_opts,
BSON_STR({"unique" : true, "partialFilterExpression" : {"keyAltNames" : {"$exists" : true}}}));
mongoc_index_model_t *index_model = mongoc_index_model_new(&index_keys, &index_opts);
if (!mongoc_collection_create_indexes_with_opts(
coll, &index_model, 1, NULL /* opts */, NULL /* reply */, &error)) {
FAIL("Failed to create index: %s", error.message);
}
mongoc_index_model_destroy(index_model);
bson_destroy(&index_opts);
bson_destroy(&index_keys);
mongoc_collection_destroy(coll);
}
// Create ClientEncryption object:
mongoc_client_encryption_t *client_encryption;
{
mongoc_client_encryption_opts_t *ce_opts = mongoc_client_encryption_opts_new();
mongoc_client_encryption_opts_set_kms_providers(ce_opts, &kms_providers);
mongoc_client_encryption_opts_set_keyvault_namespace(ce_opts, keyvault_db_name, keyvault_coll_name);
mongoc_client_encryption_opts_set_keyvault_client(ce_opts, keyvault_client);
client_encryption = mongoc_client_encryption_new(ce_opts, &error);
if (!client_encryption) {
FAIL("Failed to create ClientEncryption: %s", error.message);
}
mongoc_client_encryption_opts_destroy(ce_opts);
}
// Create data key (see:
// https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules):
bson_value_t datakey_id;
{
mongoc_client_encryption_datakey_opts_t *dk_opts = mongoc_client_encryption_datakey_opts_new();
if (!mongoc_client_encryption_create_datakey(client_encryption, "local", dk_opts, &datakey_id, &error)) {
FAIL("Failed to create data key: %s", error.message);
}
mongoc_client_encryption_datakey_opts_destroy(dk_opts);
}
// Create a schema map:
bson_t schema_map = BSON_INITIALIZER;
{
/*
{
"db.coll": {
"properties" : {
"encryptedField" : {
"encrypt" : {
"keyId" : [ "<key ID>" ],
"bsonType" : "string",
"algorithm" : "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
}
}
},
"bsonType" : "object"
}
}
*/
bson_t key_ids = BSON_INITIALIZER;
BSON_APPEND_VALUE(&key_ids, "0", &datakey_id);
bson_t encrypt = BSON_INITIALIZER;
BSON_APPEND_ARRAY(&encrypt, "keyId", &key_ids);
BSON_APPEND_UTF8(&encrypt, "bsonType", "string");
BSON_APPEND_UTF8(&encrypt, "algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic");
bson_t encryptedField = BSON_INITIALIZER;
BSON_APPEND_DOCUMENT(&encryptedField, "encrypt", &encrypt);
bson_t properties = BSON_INITIALIZER;
BSON_APPEND_DOCUMENT(&properties, "encryptedField", &encryptedField);
bson_t db_coll = BSON_INITIALIZER;
BSON_APPEND_DOCUMENT(&db_coll, "properties", &properties);
BSON_APPEND_UTF8(&db_coll, "bsonType", "object");
BSON_APPEND_DOCUMENT(&schema_map, "db.coll", &db_coll);
bson_destroy(&key_ids);
bson_destroy(&db_coll);
bson_destroy(&encrypt);
bson_destroy(&encryptedField);
bson_destroy(&properties);
}
// Create client configured to automatically encrypt:
mongoc_client_t *encrypted_client;
{
encrypted_client = mongoc_client_new(uri);
if (!encrypted_client) {
FAIL("Failed to create client");
}
mongoc_auto_encryption_opts_t *ae_opts = mongoc_auto_encryption_opts_new();
mongoc_auto_encryption_opts_set_schema_map(ae_opts, &schema_map);
mongoc_auto_encryption_opts_set_keyvault_namespace(ae_opts, keyvault_db_name, keyvault_coll_name);
mongoc_auto_encryption_opts_set_kms_providers(ae_opts, &kms_providers);
if (!mongoc_client_enable_auto_encryption(encrypted_client, ae_opts, &error)) {
FAIL("Failed to enable auto encryption: %s", error.message);
}
mongoc_auto_encryption_opts_destroy(ae_opts);
}
// Insert a document:
mongoc_collection_t *encrypted_coll =
mongoc_client_get_collection(encrypted_client, encrypted_db_name, encrypted_coll_name);
{
mongoc_collection_drop(encrypted_coll, NULL); // Clear pre-existing data.
bson_t to_insert = BSON_INITIALIZER;
BSON_APPEND_UTF8(&to_insert, "encryptedField", "foobar");
if (!mongoc_collection_insert_one(encrypted_coll, &to_insert, NULL /* opts */, NULL /* reply */, &error)) {
FAIL("Failed to insert: %s", error.message);
}
char *as_str = bson_as_relaxed_extended_json(&to_insert, NULL);
printf("Inserted document with automatic encryption: %s\n", as_str);
bson_free(as_str);
bson_destroy(&to_insert);
}
// Retrieve document with automatic decryption:
{
bson_t filter = BSON_INITIALIZER;
mongoc_cursor_t *cursor = mongoc_collection_find_with_opts(encrypted_coll, &filter, NULL, NULL);
const bson_t *result;
if (!mongoc_cursor_next(cursor, &result)) {
FAIL("Failed to find inserted document: %s", error.message);
}
char *as_str = bson_as_relaxed_extended_json(result, NULL);
printf("Retrieved document with automatic decryption: %s\n", as_str);
bson_free(as_str);
mongoc_cursor_destroy(cursor);
bson_destroy(&filter);
}
// Retrieve document without decryption:
{
mongoc_collection_t *unencrypted_coll =
mongoc_client_get_collection(keyvault_client, encrypted_db_name, encrypted_coll_name);
bson_t filter = BSON_INITIALIZER;
mongoc_cursor_t *cursor = mongoc_collection_find_with_opts(unencrypted_coll, &filter, NULL, NULL);
const bson_t *result;
if (!mongoc_cursor_next(cursor, &result)) {
FAIL("Failed to find inserted document: %s", error.message);
}
char *as_str = bson_as_relaxed_extended_json(result, NULL);
printf("Retrieved document without automatic decryption: %s\n", as_str);
bson_free(as_str);
mongoc_cursor_destroy(cursor);
bson_destroy(&filter);
mongoc_collection_destroy(unencrypted_coll);
}
mongoc_collection_destroy(encrypted_coll);
mongoc_client_destroy(encrypted_client);
bson_destroy(&schema_map);
bson_value_destroy(&datakey_id);
mongoc_client_encryption_destroy(client_encryption);
bson_destroy(&kms_providers);
mongoc_client_destroy(keyvault_client);
mongoc_cleanup();
return 0;
}

MongoDB Server 스키마 유효성 검사 사용하여 컬렉션 의 특정 필드에 암호화 시행하다 있도록 지원합니다. 이 스키마 유효성 검사 애플리케이션 encrypt JSON Schema 키워드로 표시된 필드에 암호화되지 않은 값을 삽입하는 것을 방지합니다.

서버 측 시행을 구현 하려면 다음 예시 와 같이 암호화 데이터 키와 적절한 JSON 스키마 유효성 검사 규칙으로 구성된 컬렉션 모두 생성해야 합니다.

client-side-encryption-server-schema.c
#include <mongoc/mongoc.h>
#include <stdio.h>
#include <stdlib.h>
#define FAIL(...) \
fprintf(stderr, "Error [%s:%d]:\n", __FILE__, __LINE__); \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n"); \
abort();
// `init_bson` creates BSON from JSON. Aborts on error. Use the `BSON_STR()` macro to avoid quotes.
#define init_bson(bson, json) \
if (!bson_init_from_json(&bson, json, -1, &error)) { \
FAIL("Failed to create BSON: %s", error.message); \
}
int
main(void)
{
bson_error_t error;
// The key vault collection stores encrypted data keys:
const char *keyvault_db_name = "keyvault";
const char *keyvault_coll_name = "datakeys";
// The encrypted collection stores application data:
const char *encrypted_db_name = "db";
const char *encrypted_coll_name = "coll";
// Set `local_key` to a 96 byte base64-encoded string:
const char *local_key =
"qx/3ydlPRXgUrBvSBWLsllUTaYDcS/pyaVo27qBHkS2AFePjInwhzCmDWHdmCYPmzhO4lRBzeZKFjSafduLL5z5DMvR/"
"QFfV4zc7btcVmV3QWbDwqZyn6G+Y18ToLHyK";
const char *uri = "mongodb://localhost/?appname=client-side-encryption";
mongoc_init();
// Configure KMS providers used to encrypt data keys:
bson_t kms_providers;
{
char *as_json = bson_strdup_printf(BSON_STR({"local" : {"key" : "%s"}}), local_key);
init_bson(kms_providers, as_json);
bson_free(as_json);
}
// Set up key vault collection:
mongoc_client_t *keyvault_client;
{
keyvault_client = mongoc_client_new(uri);
if (!keyvault_client) {
FAIL("Failed to create keyvault client");
}
mongoc_collection_t *coll = mongoc_client_get_collection(keyvault_client, keyvault_db_name, keyvault_coll_name);
mongoc_collection_drop(coll, NULL); // Clear pre-existing data.
// Create index to ensure keys have unique keyAltNames:
bson_t index_keys, index_opts;
init_bson(index_keys, BSON_STR({"keyAltNames" : 1}));
init_bson(index_opts,
BSON_STR({"unique" : true, "partialFilterExpression" : {"keyAltNames" : {"$exists" : true}}}));
mongoc_index_model_t *index_model = mongoc_index_model_new(&index_keys, &index_opts);
if (!mongoc_collection_create_indexes_with_opts(
coll, &index_model, 1, NULL /* opts */, NULL /* reply */, &error)) {
FAIL("Failed to create index: %s", error.message);
}
mongoc_index_model_destroy(index_model);
bson_destroy(&index_opts);
bson_destroy(&index_keys);
mongoc_collection_destroy(coll);
}
// Create ClientEncryption object:
mongoc_client_encryption_t *client_encryption;
{
mongoc_client_encryption_opts_t *ce_opts = mongoc_client_encryption_opts_new();
mongoc_client_encryption_opts_set_kms_providers(ce_opts, &kms_providers);
mongoc_client_encryption_opts_set_keyvault_namespace(ce_opts, keyvault_db_name, keyvault_coll_name);
mongoc_client_encryption_opts_set_keyvault_client(ce_opts, keyvault_client);
client_encryption = mongoc_client_encryption_new(ce_opts, &error);
if (!client_encryption) {
FAIL("Failed to create ClientEncryption: %s", error.message);
}
mongoc_client_encryption_opts_destroy(ce_opts);
}
// Create data key (see:
// https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules):
bson_value_t datakey_id;
{
mongoc_client_encryption_datakey_opts_t *dk_opts = mongoc_client_encryption_datakey_opts_new();
if (!mongoc_client_encryption_create_datakey(client_encryption, "local", dk_opts, &datakey_id, &error)) {
FAIL("Failed to create data key: %s", error.message);
}
mongoc_client_encryption_datakey_opts_destroy(dk_opts);
}
// Create collection with remote schema:
bson_t schema = BSON_INITIALIZER;
{
/*
{
"properties" : {
"encryptedField" : {
"encrypt" : {
"keyId" : [ "<key ID>" ],
"bsonType" : "string",
"algorithm" : "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
}
}
},
"bsonType" : "object"
}
*/
bson_t key_ids = BSON_INITIALIZER;
BSON_APPEND_VALUE(&key_ids, "0", &datakey_id);
bson_t encrypt = BSON_INITIALIZER;
BSON_APPEND_ARRAY(&encrypt, "keyId", &key_ids);
BSON_APPEND_UTF8(&encrypt, "bsonType", "string");
BSON_APPEND_UTF8(&encrypt, "algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic");
bson_t encryptedField = BSON_INITIALIZER;
BSON_APPEND_DOCUMENT(&encryptedField, "encrypt", &encrypt);
bson_t properties = BSON_INITIALIZER;
BSON_APPEND_DOCUMENT(&properties, "encryptedField", &encryptedField);
BSON_APPEND_DOCUMENT(&schema, "properties", &properties);
BSON_APPEND_UTF8(&schema, "bsonType", "object");
bson_destroy(&key_ids);
bson_destroy(&encrypt);
bson_destroy(&encryptedField);
bson_destroy(&properties);
}
// Create client configured to automatically encrypt:
mongoc_client_t *encrypted_client;
{
encrypted_client = mongoc_client_new(uri);
if (!encrypted_client) {
FAIL("Failed to create client");
}
mongoc_auto_encryption_opts_t *ae_opts = mongoc_auto_encryption_opts_new();
mongoc_auto_encryption_opts_set_keyvault_namespace(ae_opts, keyvault_db_name, keyvault_coll_name);
mongoc_auto_encryption_opts_set_kms_providers(ae_opts, &kms_providers);
if (!mongoc_client_enable_auto_encryption(encrypted_client, ae_opts, &error)) {
FAIL("Failed to enable auto encryption: %s", error.message);
}
mongoc_auto_encryption_opts_destroy(ae_opts);
}
// Clear pre-existing data:
{
mongoc_collection_t *coll =
mongoc_client_get_collection(encrypted_client, encrypted_db_name, encrypted_coll_name);
mongoc_collection_drop(coll, NULL);
mongoc_collection_destroy(coll);
}
// Create collection with server-side schema:
mongoc_collection_t *encrypted_coll;
{
mongoc_database_t *db = mongoc_client_get_database(encrypted_client, encrypted_db_name);
bson_t create_opts = BSON_INITIALIZER; // { validator: { $jsonSchema: <schema> } }
bson_t json_schema = BSON_INITIALIZER;
BSON_APPEND_DOCUMENT(&json_schema, "$jsonSchema", &schema);
BSON_APPEND_DOCUMENT(&create_opts, "validator", &json_schema);
encrypted_coll = mongoc_database_create_collection(db, encrypted_coll_name, &create_opts, &error);
if (!encrypted_coll) {
FAIL("Failed to create collection: %s", error.message);
}
bson_destroy(&json_schema);
bson_destroy(&create_opts);
mongoc_database_destroy(db);
}
// Insert a document:
{
bson_t to_insert = BSON_INITIALIZER;
BSON_APPEND_UTF8(&to_insert, "encryptedField", "foobar");
if (!mongoc_collection_insert_one(encrypted_coll, &to_insert, NULL /* opts */, NULL /* reply */, &error)) {
FAIL("Failed to insert: %s", error.message);
}
char *as_str = bson_as_relaxed_extended_json(&to_insert, NULL);
printf("Inserted document with automatic encryption: %s\n", as_str);
bson_free(as_str);
bson_destroy(&to_insert);
}
// Retrieve document with automatic decryption:
{
bson_t filter = BSON_INITIALIZER;
mongoc_cursor_t *cursor = mongoc_collection_find_with_opts(encrypted_coll, &filter, NULL, NULL);
const bson_t *result;
if (!mongoc_cursor_next(cursor, &result)) {
FAIL("Failed to find inserted document: %s", error.message);
}
char *as_str = bson_as_relaxed_extended_json(result, NULL);
printf("Retrieved document with automatic decryption: %s\n", as_str);
bson_free(as_str);
mongoc_cursor_destroy(cursor);
bson_destroy(&filter);
}
// Retrieve document without automatic decryption:
{
mongoc_collection_t *unencrypted_coll =
mongoc_client_get_collection(keyvault_client, encrypted_db_name, encrypted_coll_name);
bson_t filter = BSON_INITIALIZER;
mongoc_cursor_t *cursor = mongoc_collection_find_with_opts(unencrypted_coll, &filter, NULL, NULL);
const bson_t *result;
if (!mongoc_cursor_next(cursor, &result)) {
FAIL("Failed to find inserted document: %s", error.message);
}
char *as_str = bson_as_relaxed_extended_json(result, NULL);
printf("Retrieved document without automatic decryption: %s\n", as_str);
bson_free(as_str);
mongoc_cursor_destroy(cursor);
bson_destroy(&filter);
mongoc_collection_destroy(unencrypted_coll);
}
mongoc_collection_destroy(encrypted_coll);
bson_value_destroy(&datakey_id);
mongoc_client_destroy(encrypted_client);
bson_destroy(&schema);
mongoc_client_encryption_destroy(client_encryption);
bson_destroy(&kms_providers);
mongoc_client_destroy(keyvault_client);
mongoc_cleanup();
return 0;
}

명시적 암호화 사용하여 데이터베이스 에서 수행하는 각 작업에 대해 문서 의 필드를 암호화하는 방법을 지정할 수 있습니다. 명시적 암호화 사용할 때는 자체 암호화 데이터 키와 암호화 옵션을 정의해야 합니다.

명시적 암호화 는 MongoDB Community Edition 기능 이며 쿼리 분석 (mongocryptd 또는 crypt_shared)을 사용하지 않습니다. 명시적 암호화는 mongoc_client_encryption_t 클래스를 사용합니다. 다음 예시 명시적 암호화 및 암호 해독을 사용하는 방법을 보여 줍니다.

client-side-encryption-explicit.c
#include <mongoc/mongoc.h>
#include <stdio.h>
#include <stdlib.h>
#define FAIL(...) \
fprintf(stderr, "Error [%s:%d]:\n", __FILE__, __LINE__); \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n"); \
abort();
// `init_bson` creates BSON from JSON. Aborts on error. Use the `BSON_STR()` macro to avoid quotes.
#define init_bson(bson, json) \
if (!bson_init_from_json(&bson, json, -1, &error)) { \
FAIL("Failed to create BSON: %s", error.message); \
}
int
main(void)
{
bson_error_t error;
// The key vault collection stores encrypted data keys:
const char *keyvault_db_name = "keyvault";
const char *keyvault_coll_name = "datakeys";
// Set `local_key` to a 96 byte base64-encoded string:
const char *local_key =
"qx/3ydlPRXgUrBvSBWLsllUTaYDcS/pyaVo27qBHkS2AFePjInwhzCmDWHdmCYPmzhO4lRBzeZKFjSafduLL5z5DMvR/"
"QFfV4zc7btcVmV3QWbDwqZyn6G+Y18ToLHyK";
const char *uri = "mongodb://localhost/?appname=client-side-encryption";
mongoc_init();
// Create client:
mongoc_client_t *client = mongoc_client_new(uri);
if (!client) {
FAIL("Failed to create client");
}
// Configure KMS providers used to encrypt data keys:
bson_t kms_providers;
{
char *as_json = bson_strdup_printf(BSON_STR({"local" : {"key" : "%s"}}), local_key);
init_bson(kms_providers, as_json);
bson_free(as_json);
}
// Set up key vault collection:
{
mongoc_collection_t *coll = mongoc_client_get_collection(client, keyvault_db_name, keyvault_coll_name);
mongoc_collection_drop(coll, NULL); // Clear pre-existing data.
// Create index to ensure keys have unique keyAltNames:
bson_t index_keys, index_opts;
init_bson(index_keys, BSON_STR({"keyAltNames" : 1}));
init_bson(index_opts,
BSON_STR({"unique" : true, "partialFilterExpression" : {"keyAltNames" : {"$exists" : true}}}));
mongoc_index_model_t *index_model = mongoc_index_model_new(&index_keys, &index_opts);
if (!mongoc_collection_create_indexes_with_opts(
coll, &index_model, 1, NULL /* opts */, NULL /* reply */, &error)) {
FAIL("Failed to create index: %s", error.message);
}
mongoc_index_model_destroy(index_model);
bson_destroy(&index_opts);
bson_destroy(&index_keys);
mongoc_collection_destroy(coll);
}
// Create ClientEncryption object:
mongoc_client_encryption_t *client_encryption;
{
mongoc_client_encryption_opts_t *ce_opts = mongoc_client_encryption_opts_new();
mongoc_client_encryption_opts_set_kms_providers(ce_opts, &kms_providers);
mongoc_client_encryption_opts_set_keyvault_namespace(ce_opts, keyvault_db_name, keyvault_coll_name);
mongoc_client_encryption_opts_set_keyvault_client(ce_opts, client);
client_encryption = mongoc_client_encryption_new(ce_opts, &error);
if (!client_encryption) {
FAIL("Failed to create ClientEncryption: %s", error.message);
}
mongoc_client_encryption_opts_destroy(ce_opts);
}
// Create data key (see:
// https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules):
bson_value_t datakey_id;
{
mongoc_client_encryption_datakey_opts_t *dk_opts = mongoc_client_encryption_datakey_opts_new();
if (!mongoc_client_encryption_create_datakey(client_encryption, "local", dk_opts, &datakey_id, &error)) {
FAIL("Failed to create data key: %s", error.message);
}
mongoc_client_encryption_datakey_opts_destroy(dk_opts);
}
// Explicitly encrypt a value:
bson_value_t encrypted_value;
{
mongoc_client_encryption_encrypt_opts_t *e_opts = mongoc_client_encryption_encrypt_opts_new();
mongoc_client_encryption_encrypt_opts_set_algorithm(e_opts, MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC);
mongoc_client_encryption_encrypt_opts_set_keyid(e_opts, &datakey_id);
bson_value_t to_encrypt = {.value_type = BSON_TYPE_INT32, .value = {.v_int32 = 123}};
if (!mongoc_client_encryption_encrypt(client_encryption, &to_encrypt, e_opts, &encrypted_value, &error)) {
FAIL("Failed to encrypt field: %s", error.message);
}
mongoc_client_encryption_encrypt_opts_destroy(e_opts);
}
// Explicitly decrypt a value:
{
bson_value_t decrypted_value;
if (!mongoc_client_encryption_decrypt(client_encryption, &encrypted_value, &decrypted_value, &error)) {
FAIL("Failed to decrypt field: %s", error.message);
}
printf("Decrypted value: %" PRId32 "\n", decrypted_value.value.v_int32);
bson_value_destroy(&decrypted_value);
}
bson_value_destroy(&encrypted_value);
bson_value_destroy(&datakey_id);
mongoc_client_encryption_destroy(client_encryption);
bson_destroy(&kms_providers);
mongoc_client_destroy(client);
mongoc_cleanup();
return 0;
}

자동 암호화 MongoDB Enterprise Advanced 또는 MongoDB Atlas cluster 필요하지만 모든 MongoDB Server 제품은 자동 암호 해독을 지원 . 자동 복호화를 사용하여 명시적 암호화를 구성하려면 다음 예시와 같이 mongoc_auto_encryption_opts_t에서 bypass_auto_encryption=True 을(를) 설정합니다.

client-side-encryption-auto-decryption.c
#include <mongoc/mongoc.h>
#include <stdio.h>
#include <stdlib.h>
#define FAIL(...) \
fprintf(stderr, "Error [%s:%d]:\n", __FILE__, __LINE__); \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n"); \
abort();
// `init_bson` creates BSON from JSON. Aborts on error. Use the `BSON_STR()` macro to avoid quotes.
#define init_bson(bson, json) \
if (!bson_init_from_json(&bson, json, -1, &error)) { \
FAIL("Failed to create BSON: %s", error.message); \
}
int
main(void)
{
bson_error_t error;
// The key vault collection stores encrypted data keys:
const char *keyvault_db_name = "keyvault";
const char *keyvault_coll_name = "datakeys";
// The encrypted collection stores application data:
const char *encrypted_db_name = "db";
const char *encrypted_coll_name = "coll";
// Set `local_key` to a 96 byte base64-encoded string:
const char *local_key =
"qx/3ydlPRXgUrBvSBWLsllUTaYDcS/pyaVo27qBHkS2AFePjInwhzCmDWHdmCYPmzhO4lRBzeZKFjSafduLL5z5DMvR/"
"QFfV4zc7btcVmV3QWbDwqZyn6G+Y18ToLHyK";
const char *uri = "mongodb://localhost/?appname=client-side-encryption";
mongoc_init();
// Configure KMS providers used to encrypt data keys:
bson_t kms_providers;
{
char *as_json = bson_strdup_printf(BSON_STR({"local" : {"key" : "%s"}}), local_key);
init_bson(kms_providers, as_json);
bson_free(as_json);
}
// Create client configured to automatically decrypt:
mongoc_client_t *client;
{
client = mongoc_client_new(uri);
if (!client) {
FAIL("Failed to create client");
}
mongoc_auto_encryption_opts_t *ae_opts = mongoc_auto_encryption_opts_new();
// Bypass automatic encryption (requires mongocryptd/crypt_shared) but keep automatic decryption:
mongoc_auto_encryption_opts_set_bypass_auto_encryption(ae_opts, true);
mongoc_auto_encryption_opts_set_keyvault_namespace(ae_opts, keyvault_db_name, keyvault_coll_name);
mongoc_auto_encryption_opts_set_kms_providers(ae_opts, &kms_providers);
if (!mongoc_client_enable_auto_encryption(client, ae_opts, &error)) {
FAIL("Failed to enable auto encryption: %s", error.message);
}
mongoc_auto_encryption_opts_destroy(ae_opts);
}
// Set up key vault collection:
{
mongoc_collection_t *coll = mongoc_client_get_collection(client, keyvault_db_name, keyvault_coll_name);
mongoc_collection_drop(coll, NULL); // Clear pre-existing data.
// Create index to ensure keys have unique keyAltNames:
bson_t index_keys, index_opts;
init_bson(index_keys, BSON_STR({"keyAltNames" : 1}));
init_bson(index_opts,
BSON_STR({"unique" : true, "partialFilterExpression" : {"keyAltNames" : {"$exists" : true}}}));
mongoc_index_model_t *index_model = mongoc_index_model_new(&index_keys, &index_opts);
if (!mongoc_collection_create_indexes_with_opts(
coll, &index_model, 1, NULL /* opts */, NULL /* reply */, &error)) {
FAIL("Failed to create index: %s", error.message);
}
mongoc_index_model_destroy(index_model);
bson_destroy(&index_opts);
bson_destroy(&index_keys);
mongoc_collection_destroy(coll);
}
// Create ClientEncryption object:
mongoc_client_encryption_t *client_encryption;
{
mongoc_client_encryption_opts_t *ce_opts = mongoc_client_encryption_opts_new();
mongoc_client_encryption_opts_set_kms_providers(ce_opts, &kms_providers);
mongoc_client_encryption_opts_set_keyvault_namespace(ce_opts, keyvault_db_name, keyvault_coll_name);
mongoc_client_encryption_opts_set_keyvault_client(ce_opts, client);
client_encryption = mongoc_client_encryption_new(ce_opts, &error);
if (!client_encryption) {
FAIL("Failed to create ClientEncryption: %s", error.message);
}
mongoc_client_encryption_opts_destroy(ce_opts);
}
// Create data key (see:
// https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules):
bson_value_t datakey_id;
{
mongoc_client_encryption_datakey_opts_t *dk_opts = mongoc_client_encryption_datakey_opts_new();
if (!mongoc_client_encryption_create_datakey(client_encryption, "local", dk_opts, &datakey_id, &error)) {
FAIL("Failed to create data key: %s", error.message);
}
mongoc_client_encryption_datakey_opts_destroy(dk_opts);
}
// Explicitly encrypt a value:
bson_value_t encrypted_value;
{
mongoc_client_encryption_encrypt_opts_t *e_opts = mongoc_client_encryption_encrypt_opts_new();
mongoc_client_encryption_encrypt_opts_set_algorithm(e_opts, MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC);
mongoc_client_encryption_encrypt_opts_set_keyid(e_opts, &datakey_id);
bson_value_t to_encrypt = {.value_type = BSON_TYPE_INT32, .value = {.v_int32 = 123}};
if (!mongoc_client_encryption_encrypt(client_encryption, &to_encrypt, e_opts, &encrypted_value, &error)) {
FAIL("Failed to encrypt field: %s", error.message);
}
mongoc_client_encryption_encrypt_opts_destroy(e_opts);
}
// Insert document with encrypted payload:
mongoc_collection_t *encrypted_coll = mongoc_client_get_collection(client, encrypted_db_name, encrypted_coll_name);
{
mongoc_collection_drop(encrypted_coll, NULL); // Clear pre-existing data.
bson_t to_insert = BSON_INITIALIZER;
BSON_APPEND_VALUE(&to_insert, "encryptedField", &encrypted_value);
if (!mongoc_collection_insert_one(encrypted_coll, &to_insert, NULL /* opts */, NULL /* reply */, &error)) {
FAIL("Failed to insert: %s", error.message);
}
char *as_str = bson_as_relaxed_extended_json(&to_insert, NULL);
printf("Inserted document with encrypted payload: %s\n", as_str);
bson_free(as_str);
bson_destroy(&to_insert);
}
// Retrieve document (automatically decrypts):
{
bson_t filter = BSON_INITIALIZER;
mongoc_cursor_t *cursor = mongoc_collection_find_with_opts(encrypted_coll, &filter, NULL, NULL);
const bson_t *result;
if (!mongoc_cursor_next(cursor, &result)) {
FAIL("Failed to find inserted document: %s", error.message);
}
char *as_str = bson_as_relaxed_extended_json(result, NULL);
printf("Retrieved document with automatic decryption: %s\n", as_str);
bson_free(as_str);
mongoc_cursor_destroy(cursor);
bson_destroy(&filter);
}
mongoc_collection_destroy(encrypted_coll);
bson_value_destroy(&encrypted_value);
bson_value_destroy(&datakey_id);
mongoc_client_encryption_destroy(client_encryption);
bson_destroy(&kms_providers);
mongoc_client_destroy(client);
mongoc_cleanup();
return 0;
}

Queryable Encryption은 차세대 사용 중 암호화 기능으로, MongoDB Server 버전 6.0에서 미리보기 기능으로 처음 도입되었으며, MongoDB 7.0에서는 정식 버전(GA) 기능으로 출시되었습니다. Queryable Encryption은 암호화된 필드에 대한 동일성 검색을 지원하고 각 값을 고유하게 암호화합니다.

참고

QE에는 MongoDB Server 7.0 이상이 필요합니다.

MongoDB Server 배포서버 를 6.0 에서 7.0으로 업그레이드하는 방법에 대한 자세한 내용은 MongoDB Server 매뉴얼에서 6.0 을 7.0으로 업그레이드 를 참조하세요.

이 기능에 대한 자세한 내용은 MongoDB Server 매뉴얼의 Queryable Encryption 가이드를 참조하세요.

MongoDB Server 6.0 은 Queryable Encryption 공개 기술 미리 보기로 도입했습니다. MongoDB Server 7.0 에는 서로 다른 버전의 드라이버 라이브러리와 서버 간의 호환성에 영향을 미치는 Queryable Encryption 프로토콜에 대한 호환성이 손상되는 변경이 포함되어 있습니다.

다음 표는 Queryable Encryption 과 호환되는 버전을 보여줍니다.

libmongocrypt
libmongoc
호환되는 MongoDB Server 버전

1.7.x 및 이전 버전

1.23.x 및 이전 버전

6.0 전용

1.8.0 이상

1.24.0 이상

7.0 이상

중요

버전 불일치 오류

앞의 표에 나열된 호환되지 않는 버전의 패키지를 사용하면 서버 오류가 발생합니다.

돌아가기

인증

이 페이지의 내용