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 매뉴얼의 자동 암호화 공유 라이브러리 가이드 참조하세요.

자동 crypt_shared 암호화 crypt_shared 로 구성된 mongoc_client_t 또는 mongoc_client_pool_t가 자동으로 라이브러리를 로드하려고 시도합니다. 라이브러리 로드에 실패하면 mongoc_client_t 또는 mongoc_client_pool_t가 mongocryptd 애플리케이션의 에서 프로세스 생성하려고 PATH 시도합니다. 및 사용을 구성하려면 crypt_shared mongocryptd 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 Schema 유효성 검사 규칙으로 구성된 컬렉션 모두 생성해야 합니다.

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 제품은 자동 암호 해독을 지원 . 자동 복호화를 사용하여 명시적 암호화를 구성하려면 bypass_auto_encryption=True 다음 예시 와 같이 mongoc_auto_encryption_opts_t 에서 을 설정하다 .

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 자세한 6.0 70 내용은 MongoDB Server 매뉴얼에서 을 로 업그레이드를 참조하세요.

이 기능 에 대한 자세한 내용은 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 이상

중요

버전 불일치 오류

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

돌아가기

인증

이 페이지의 내용