MongoDB 4.2 의 새로운 기능, 클라이언트 측 필드 레벨 암호화 (CSFLE라고도 함)를 사용하면 관리자와 개발자가 다른 MongoDB 암호화 기능 외에도 특정 데이터 필드를 암호화할 수 있습니다.
개발자는 CSFLE를 사용하여 서버 사이드 구성이나 지시문 없이 클라이언트 사이드에서 필드를 암호화할 수 있습니다. CSFLE는 서버 관리자를 포함한 권한이 없는 당사자가 암호화됨 데이터를 읽을 수 없도록 애플리케이션이 보장해야 하는 워크로드를 지원합니다.
명령의 민감한 필드가 자동으로 암호화됨 되는 자동 암호화 에는 쿼리 분석에 대한 엔터프라이즈 전용 종속성이 필요합니다. 자세한 내용은 사용 중 암호화 를 참조하세요.
팁
자동 클라이언트 사이드 필드 레벨 암호화
자동 암호화 mongoc_client_t 에서 mongoc_client_enable_auto_encryption을 호출하여 활성화합니다. 다음 예제에서는 mongoc_client_encryption_t를 사용하여 자동 암호화 설정하다 하여 새 암호화 데이터 키를 생성하는 방법을 보여줍니다.
참고
자동 암호화에는 MongoDB 4.2 엔터프라이즈 또는 MongoDB 4.2 이 필요합니다. Atlas cluster. 서버의 커뮤니티 버전은 자동 암호 해독과 명시적 암호화를 지원합니다.
로컬 자동 암호화 규칙 제공
다음 예시 mongoc_auto_encryption_opts_set_schema_map으로 설정하다 스키마 맵을 사용하여 자동 암호화 규칙을 지정하는 방법을 보여줍니다. 자동 암호화 규칙은 JSON Schema 구문의 엄격한 하위 집합을 사용하여 표현됩니다.
스키마 맵을 제공하면 서버 에서 얻은 JSON Schema에 의존하는 것보다 더 강력한 보안이 제공됩니다. 악의적인 서버 가 잘못된 JSON schema 를 광고하여 클라이언트 를 속여 암호화되어야 하는 암호화됨 되지 않은 데이터를 보내도록 할 수 있습니다.
스키마 맵에 제공된 JSON Schema는 자동 암호화 구성에만 적용 됩니다. JSON schema 의 다른 유효성 검사 규칙은 운전자 에서 적용되지 않으므로 오류가 발생합니다.
/* Helper method to create a new data key in the key vault, a schema to use that * key, and writes the schema to a file for later use. */ static bool create_schema_file (bson_t *kms_providers, const char *keyvault_db, const char *keyvault_coll, mongoc_client_t *keyvault_client, bson_error_t *error) { mongoc_client_encryption_t *client_encryption = NULL; mongoc_client_encryption_opts_t *client_encryption_opts = NULL; mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL; bson_value_t datakey_id = {0}; char *keyaltnames[] = {"mongoc_encryption_example_1"}; bson_t *schema = NULL; char *schema_string = NULL; size_t schema_string_len; FILE *outfile = NULL; bool ret = false; client_encryption_opts = mongoc_client_encryption_opts_new (); mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts, kms_providers); mongoc_client_encryption_opts_set_keyvault_namespace (client_encryption_opts, keyvault_db, keyvault_coll); mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts, keyvault_client); client_encryption = mongoc_client_encryption_new (client_encryption_opts, error); if (!client_encryption) { goto fail; } /* Create a new data key and json schema for the encryptedField. * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules */ datakey_opts = mongoc_client_encryption_datakey_opts_new (); mongoc_client_encryption_datakey_opts_set_keyaltnames (datakey_opts, keyaltnames, 1); if (!mongoc_client_encryption_create_datakey (client_encryption, "local", datakey_opts, &datakey_id, error)) { goto fail; } /* Create a schema describing that "encryptedField" is a string encrypted * with the newly created data key using deterministic encryption. */ schema = BCON_NEW ( "properties", "{", "encryptedField", "{", "encrypt", "{", "keyId", "[", BCON_BIN (datakey_id.value.v_binary.subtype, datakey_id.value.v_binary.data, datakey_id.value.v_binary.data_len), "]", "bsonType", "string", "algorithm", MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC, "}", "}", "}", "bsonType", "object"); /* Use canonical JSON so that other drivers and tools will be * able to parse the MongoDB extended JSON file. */ schema_string = bson_as_canonical_extended_json (schema, &schema_string_len); outfile = fopen ("jsonSchema.json", "w"); if (0 == fwrite (schema_string, sizeof (char), schema_string_len, outfile)) { fprintf (stderr, "failed to write to file\n"); goto fail; } ret = true; fail: mongoc_client_encryption_destroy (client_encryption); mongoc_client_encryption_datakey_opts_destroy (datakey_opts); mongoc_client_encryption_opts_destroy (client_encryption_opts); bson_free (schema_string); bson_destroy (schema); bson_value_destroy (&datakey_id); if (outfile) { fclose (outfile); } return ret; } /* This example demonstrates how to use automatic encryption with a client-side * schema map using the enterprise version of MongoDB */ int main (void) { /* The collection used to store the encryption data keys. */ /* The collection used to store the encrypted documents in this example. */ int exit_status = EXIT_FAILURE; bool ret; uint8_t *local_masterkey = NULL; uint32_t local_masterkey_len; bson_t *kms_providers = NULL; bson_error_t error = {0}; bson_t *index_keys = NULL; bson_t *index_opts = NULL; mongoc_index_model_t *index_model = NULL; bson_json_reader_t *reader = NULL; bson_t schema = BSON_INITIALIZER; bson_t *schema_map = NULL; /* The MongoClient used to access the key vault (keyvault_namespace). */ mongoc_client_t *keyvault_client = NULL; mongoc_collection_t *keyvault_coll = NULL; mongoc_auto_encryption_opts_t *auto_encryption_opts = NULL; mongoc_client_t *client = NULL; mongoc_collection_t *coll = NULL; bson_t *to_insert = NULL; mongoc_client_t *unencrypted_client = NULL; mongoc_collection_t *unencrypted_coll = NULL; mongoc_init (); /* Configure the master key. This must be the same master key that was used * to create the encryption key. */ local_masterkey = hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len); if (!local_masterkey || local_masterkey_len != 96) { fprintf (stderr, "Specify LOCAL_MASTERKEY environment variable as a " "secure random 96 byte hex value.\n"); goto fail; } kms_providers = BCON_NEW ("local", "{", "key", BCON_BIN (0, local_masterkey, local_masterkey_len), "}"); /* Set up the key vault for this example. */ keyvault_client = mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption-keyvault"); BSON_ASSERT (keyvault_client); keyvault_coll = mongoc_client_get_collection (keyvault_client, KEYVAULT_DB, KEYVAULT_COLL); mongoc_collection_drop (keyvault_coll, NULL); /* Create a unique index to ensure that two data keys cannot share the same * keyAltName. This is recommended practice for the key vault. */ index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1)); index_opts = BCON_NEW ("unique", BCON_BOOL (true), "partialFilterExpression", "{", "keyAltNames", "{", "$exists", BCON_BOOL (true), "}", "}"); index_model = mongoc_index_model_new (index_keys, index_opts); ret = mongoc_collection_create_indexes_with_opts ( keyvault_coll, &index_model, 1, NULL /* opts */, NULL /* reply */, &error); if (!ret) { goto fail; } /* Create a new data key and a schema using it for encryption. Save the * schema to the file jsonSchema.json */ ret = create_schema_file (kms_providers, KEYVAULT_DB, KEYVAULT_COLL, keyvault_client, &error); if (!ret) { goto fail; } /* Load the JSON Schema and construct the local schema_map option. */ reader = bson_json_reader_new_from_file ("jsonSchema.json", &error); if (!reader) { goto fail; } bson_json_reader_read (reader, &schema, &error); /* Construct the schema map, mapping the namespace of the collection to the * schema describing encryption. */ schema_map = BCON_NEW (ENCRYPTED_DB "." ENCRYPTED_COLL, BCON_DOCUMENT (&schema)); auto_encryption_opts = mongoc_auto_encryption_opts_new (); mongoc_auto_encryption_opts_set_keyvault_client (auto_encryption_opts, keyvault_client); mongoc_auto_encryption_opts_set_keyvault_namespace (auto_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL); mongoc_auto_encryption_opts_set_kms_providers (auto_encryption_opts, kms_providers); mongoc_auto_encryption_opts_set_schema_map (auto_encryption_opts, schema_map); client = mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption"); BSON_ASSERT (client); /* Enable automatic encryption. It will determine that encryption is * necessary from the schema map instead of relying on the server to provide * a schema. */ ret = mongoc_client_enable_auto_encryption (client, auto_encryption_opts, &error); if (!ret) { goto fail; } coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL); /* Clear old data */ mongoc_collection_drop (coll, NULL); to_insert = BCON_NEW ("encryptedField", "123456789"); ret = mongoc_collection_insert_one (coll, to_insert, NULL /* opts */, NULL /* reply */, &error); if (!ret) { goto fail; } printf ("decrypted document: "); if (!print_one_document (coll, &error)) { goto fail; } printf ("\n"); unencrypted_client = mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption-unencrypted"); BSON_ASSERT (unencrypted_client); unencrypted_coll = mongoc_client_get_collection (unencrypted_client, ENCRYPTED_DB, ENCRYPTED_COLL); printf ("encrypted document: "); if (!print_one_document (unencrypted_coll, &error)) { goto fail; } printf ("\n"); exit_status = EXIT_SUCCESS; fail: if (error.code) { fprintf (stderr, "error: %s\n", error.message); } bson_free (local_masterkey); bson_destroy (kms_providers); mongoc_collection_destroy (keyvault_coll); mongoc_index_model_destroy (index_model); bson_destroy (index_opts); bson_destroy (index_keys); bson_json_reader_destroy (reader); mongoc_auto_encryption_opts_destroy (auto_encryption_opts); mongoc_collection_destroy (coll); mongoc_client_destroy (client); bson_destroy (to_insert); mongoc_collection_destroy (unencrypted_coll); mongoc_client_destroy (unencrypted_client); mongoc_client_destroy (keyvault_client); bson_destroy (&schema); bson_destroy (schema_map); mongoc_cleanup (); return exit_status; }
서버측 필드 레벨 암호화 시행
MongoDB 4.2 서버 는 스키마 유효성 검사 를 사용하여 컬렉션 의 특정 필드에 암호화 를 시행하다 기능을 지원합니다. 이 스키마 유효성 검사 는 애플리케이션 이 "encrypt" JSON schema 키워드로 표시된 필드에 암호화되지 않은 값을 삽입하는 것을 방지합니다.
다음 예시 mongoc_client_encryption_t를 사용하여 자동 암호화 설정하다 하여 새 암호화 데이터 키를 생성하고 필요한 JSON Schema로 컬렉션 생성하는 방법을 보여 줍니다.
/* Helper method to create and return a JSON schema to use for encryption. The caller will use the returned schema for server-side encryption validation. */ static bson_t * create_schema (bson_t *kms_providers, const char *keyvault_db, const char *keyvault_coll, mongoc_client_t *keyvault_client, bson_error_t *error) { mongoc_client_encryption_t *client_encryption = NULL; mongoc_client_encryption_opts_t *client_encryption_opts = NULL; mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL; bson_value_t datakey_id = {0}; char *keyaltnames[] = {"mongoc_encryption_example_2"}; bson_t *schema = NULL; client_encryption_opts = mongoc_client_encryption_opts_new (); mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts, kms_providers); mongoc_client_encryption_opts_set_keyvault_namespace (client_encryption_opts, keyvault_db, keyvault_coll); mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts, keyvault_client); client_encryption = mongoc_client_encryption_new (client_encryption_opts, error); if (!client_encryption) { goto fail; } /* Create a new data key and json schema for the encryptedField. * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules */ datakey_opts = mongoc_client_encryption_datakey_opts_new (); mongoc_client_encryption_datakey_opts_set_keyaltnames (datakey_opts, keyaltnames, 1); if (!mongoc_client_encryption_create_datakey (client_encryption, "local", datakey_opts, &datakey_id, error)) { goto fail; } /* Create a schema describing that "encryptedField" is a string encrypted * with the newly created data key using deterministic encryption. */ schema = BCON_NEW ( "properties", "{", "encryptedField", "{", "encrypt", "{", "keyId", "[", BCON_BIN (datakey_id.value.v_binary.subtype, datakey_id.value.v_binary.data, datakey_id.value.v_binary.data_len), "]", "bsonType", "string", "algorithm", MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC, "}", "}", "}", "bsonType", "object"); fail: mongoc_client_encryption_destroy (client_encryption); mongoc_client_encryption_datakey_opts_destroy (datakey_opts); mongoc_client_encryption_opts_destroy (client_encryption_opts); bson_value_destroy (&datakey_id); return schema; } /* This example demonstrates how to use automatic encryption with a server-side * schema using the enterprise version of MongoDB */ int main (void) { /* The collection used to store the encryption data keys. */ /* The collection used to store the encrypted documents in this example. */ int exit_status = EXIT_FAILURE; bool ret; uint8_t *local_masterkey = NULL; uint32_t local_masterkey_len; bson_t *kms_providers = NULL; bson_error_t error = {0}; bson_t *index_keys = NULL; bson_t *index_opts = NULL; mongoc_index_model_t *index_model = NULL; bson_json_reader_t *reader = NULL; bson_t *schema = NULL; /* The MongoClient used to access the key vault (keyvault_namespace). */ mongoc_client_t *keyvault_client = NULL; mongoc_collection_t *keyvault_coll = NULL; mongoc_auto_encryption_opts_t *auto_encryption_opts = NULL; mongoc_client_t *client = NULL; mongoc_collection_t *coll = NULL; bson_t *to_insert = NULL; mongoc_client_t *unencrypted_client = NULL; mongoc_collection_t *unencrypted_coll = NULL; bson_t *create_cmd = NULL; bson_t *create_cmd_opts = NULL; mongoc_write_concern_t *wc = NULL; mongoc_init (); /* Configure the master key. This must be the same master key that was used * to create * the encryption key. */ local_masterkey = hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len); if (!local_masterkey || local_masterkey_len != 96) { fprintf (stderr, "Specify LOCAL_MASTERKEY environment variable as a " "secure random 96 byte hex value.\n"); goto fail; } kms_providers = BCON_NEW ("local", "{", "key", BCON_BIN (0, local_masterkey, local_masterkey_len), "}"); /* Set up the key vault for this example. */ keyvault_client = mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption-keyvault"); BSON_ASSERT (keyvault_client); keyvault_coll = mongoc_client_get_collection (keyvault_client, KEYVAULT_DB, KEYVAULT_COLL); mongoc_collection_drop (keyvault_coll, NULL); /* Create a unique index to ensure that two data keys cannot share the same * keyAltName. This is recommended practice for the key vault. */ index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1)); index_opts = BCON_NEW ("unique", BCON_BOOL (true), "partialFilterExpression", "{", "keyAltNames", "{", "$exists", BCON_BOOL (true), "}", "}"); index_model = mongoc_index_model_new (index_keys, index_opts); ret = mongoc_collection_create_indexes_with_opts ( keyvault_coll, &index_model, 1, NULL /* opts */, NULL /* reply */, &error); if (!ret) { goto fail; } auto_encryption_opts = mongoc_auto_encryption_opts_new (); mongoc_auto_encryption_opts_set_keyvault_client (auto_encryption_opts, keyvault_client); mongoc_auto_encryption_opts_set_keyvault_namespace (auto_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL); mongoc_auto_encryption_opts_set_kms_providers (auto_encryption_opts, kms_providers); schema = create_schema (kms_providers, KEYVAULT_DB, KEYVAULT_COLL, keyvault_client, &error); if (!schema) { goto fail; } client = mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption"); BSON_ASSERT (client); ret = mongoc_client_enable_auto_encryption (client, auto_encryption_opts, &error); if (!ret) { goto fail; } coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL); /* Clear old data */ mongoc_collection_drop (coll, NULL); /* Create the collection with the encryption JSON Schema. */ create_cmd = BCON_NEW ("create", ENCRYPTED_COLL, "validator", "{", "$jsonSchema", BCON_DOCUMENT (schema), "}"); wc = mongoc_write_concern_new (); mongoc_write_concern_set_wmajority (wc, 0); create_cmd_opts = bson_new (); mongoc_write_concern_append (wc, create_cmd_opts); ret = mongoc_client_command_with_opts ( client, ENCRYPTED_DB, create_cmd, NULL /* read prefs */, create_cmd_opts, NULL /* reply */, &error); if (!ret) { goto fail; } to_insert = BCON_NEW ("encryptedField", "123456789"); ret = mongoc_collection_insert_one (coll, to_insert, NULL /* opts */, NULL /* reply */, &error); if (!ret) { goto fail; } printf ("decrypted document: "); if (!print_one_document (coll, &error)) { goto fail; } printf ("\n"); unencrypted_client = mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption-unencrypted"); BSON_ASSERT (unencrypted_client); unencrypted_coll = mongoc_client_get_collection (unencrypted_client, ENCRYPTED_DB, ENCRYPTED_COLL); printf ("encrypted document: "); if (!print_one_document (unencrypted_coll, &error)) { goto fail; } printf ("\n"); /* Expect a server-side error if inserting with the unencrypted collection. */ ret = mongoc_collection_insert_one (unencrypted_coll, to_insert, NULL /* opts */, NULL /* reply */, &error); if (!ret) { printf ("insert with unencrypted collection failed: %s\n", error.message); memset (&error, 0, sizeof (error)); } exit_status = EXIT_SUCCESS; fail: if (error.code) { fprintf (stderr, "error: %s\n", error.message); } bson_free (local_masterkey); bson_destroy (kms_providers); mongoc_collection_destroy (keyvault_coll); mongoc_index_model_destroy (index_model); bson_destroy (index_opts); bson_destroy (index_keys); bson_json_reader_destroy (reader); mongoc_auto_encryption_opts_destroy (auto_encryption_opts); mongoc_collection_destroy (coll); mongoc_client_destroy (client); bson_destroy (to_insert); mongoc_collection_destroy (unencrypted_coll); mongoc_client_destroy (unencrypted_client); mongoc_client_destroy (keyvault_client); bson_destroy (schema); bson_destroy (create_cmd); bson_destroy (create_cmd_opts); mongoc_write_concern_destroy (wc); mongoc_cleanup (); return exit_status; }
명시적 암호화
명시적 암호화 는 MongoDB 커뮤니티 기능 이며 쿼리 분석(mongocryptd
crypt_shared
또는)을 사용하지 않습니다. 명시적 암호화 mongoc_client_encryption_t 클래스에서 제공합니다. 예시 들면 다음과 같습니다.
/* This example demonstrates how to use explicit encryption and decryption using * the community version of MongoDB */ int main (void) { /* The collection used to store the encryption data keys. */ /* The collection used to store the encrypted documents in this example. */ int exit_status = EXIT_FAILURE; bool ret; uint8_t *local_masterkey = NULL; uint32_t local_masterkey_len; bson_t *kms_providers = NULL; bson_error_t error = {0}; bson_t *index_keys = NULL; bson_t *index_opts = NULL; mongoc_index_model_t *index_model = NULL; bson_t *schema = NULL; mongoc_client_t *client = NULL; mongoc_collection_t *coll = NULL; mongoc_collection_t *keyvault_coll = NULL; bson_t *to_insert = NULL; bson_t *create_cmd = NULL; bson_t *create_cmd_opts = NULL; mongoc_write_concern_t *wc = NULL; mongoc_client_encryption_t *client_encryption = NULL; mongoc_client_encryption_opts_t *client_encryption_opts = NULL; mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL; char *keyaltnames[] = {"mongoc_encryption_example_3"}; bson_value_t datakey_id = {0}; bson_value_t encrypted_field = {0}; bson_value_t to_encrypt = {0}; mongoc_client_encryption_encrypt_opts_t *encrypt_opts = NULL; bson_value_t decrypted = {0}; mongoc_init (); /* Configure the master key. This must be the same master key that was used * to create the encryption key. */ local_masterkey = hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len); if (!local_masterkey || local_masterkey_len != 96) { fprintf (stderr, "Specify LOCAL_MASTERKEY environment variable as a " "secure random 96 byte hex value.\n"); goto fail; } kms_providers = BCON_NEW ("local", "{", "key", BCON_BIN (0, local_masterkey, local_masterkey_len), "}"); /* The mongoc_client_t used to read/write application data. */ client = mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption"); coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL); /* Clear old data */ mongoc_collection_drop (coll, NULL); /* Set up the key vault for this example. */ keyvault_coll = mongoc_client_get_collection (client, KEYVAULT_DB, KEYVAULT_COLL); mongoc_collection_drop (keyvault_coll, NULL); /* Create a unique index to ensure that two data keys cannot share the same * keyAltName. This is recommended practice for the key vault. */ index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1)); index_opts = BCON_NEW ("unique", BCON_BOOL (true), "partialFilterExpression", "{", "keyAltNames", "{", "$exists", BCON_BOOL (true), "}", "}"); index_model = mongoc_index_model_new (index_keys, index_opts); ret = mongoc_collection_create_indexes_with_opts ( keyvault_coll, &index_model, 1, NULL /* opts */, NULL /* reply */, &error); if (!ret) { goto fail; } client_encryption_opts = mongoc_client_encryption_opts_new (); mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts, kms_providers); mongoc_client_encryption_opts_set_keyvault_namespace (client_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL); /* Set a mongoc_client_t to use for reading/writing to the key vault. This * can be the same mongoc_client_t used by the main application. */ mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts, client); client_encryption = mongoc_client_encryption_new (client_encryption_opts, &error); if (!client_encryption) { goto fail; } /* Create a new data key for the encryptedField. * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules */ datakey_opts = mongoc_client_encryption_datakey_opts_new (); mongoc_client_encryption_datakey_opts_set_keyaltnames (datakey_opts, keyaltnames, 1); if (!mongoc_client_encryption_create_datakey (client_encryption, "local", datakey_opts, &datakey_id, &error)) { goto fail; } /* Explicitly encrypt a field */ encrypt_opts = mongoc_client_encryption_encrypt_opts_new (); mongoc_client_encryption_encrypt_opts_set_algorithm (encrypt_opts, MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC); mongoc_client_encryption_encrypt_opts_set_keyid (encrypt_opts, &datakey_id); to_encrypt.value_type = BSON_TYPE_UTF8; to_encrypt.value.v_utf8.str = "123456789"; const size_t len = strlen (to_encrypt.value.v_utf8.str); BSON_ASSERT (bson_in_range_unsigned (uint32_t, len)); to_encrypt.value.v_utf8.len = (uint32_t) len; ret = mongoc_client_encryption_encrypt (client_encryption, &to_encrypt, encrypt_opts, &encrypted_field, &error); if (!ret) { goto fail; } to_insert = bson_new (); BSON_APPEND_VALUE (to_insert, "encryptedField", &encrypted_field); ret = mongoc_collection_insert_one (coll, to_insert, NULL /* opts */, NULL /* reply */, &error); if (!ret) { goto fail; } printf ("encrypted document: "); if (!print_one_document (coll, &error)) { goto fail; } printf ("\n"); /* Explicitly decrypt a field */ ret = mongoc_client_encryption_decrypt (client_encryption, &encrypted_field, &decrypted, &error); if (!ret) { goto fail; } printf ("decrypted value: %s\n", decrypted.value.v_utf8.str); exit_status = EXIT_SUCCESS; fail: if (error.code) { fprintf (stderr, "error: %s\n", error.message); } bson_free (local_masterkey); bson_destroy (kms_providers); mongoc_collection_destroy (keyvault_coll); mongoc_index_model_destroy (index_model); bson_destroy (index_opts); bson_destroy (index_keys); mongoc_collection_destroy (coll); mongoc_client_destroy (client); bson_destroy (to_insert); bson_destroy (schema); bson_destroy (create_cmd); bson_destroy (create_cmd_opts); mongoc_write_concern_destroy (wc); mongoc_client_encryption_destroy (client_encryption); mongoc_client_encryption_datakey_opts_destroy (datakey_opts); mongoc_client_encryption_opts_destroy (client_encryption_opts); bson_value_destroy (&encrypted_field); mongoc_client_encryption_encrypt_opts_destroy (encrypt_opts); bson_value_destroy (&decrypted); bson_value_destroy (&datakey_id); mongoc_cleanup (); return exit_status; }
자동 암호 해독을 통한 명시적 암호화
자동 암호화 에는 MongoDB 4.2 엔터프라이즈 또는 MongoDB 4.2 Atlas cluster 가 필요하지만, 모든 사용자에 대해 자동 암호 해독이 지원됩니다. 자동 암호화 없이 자동 암호 해독을 구성하려면 bypass_auto_encryption=True
mongoc_auto_encryption_opts_t에서 를설정하다 .
/* This example demonstrates how to set up automatic decryption without * automatic encryption using the community version of MongoDB */ int main (void) { /* The collection used to store the encryption data keys. */ /* The collection used to store the encrypted documents in this example. */ int exit_status = EXIT_FAILURE; bool ret; uint8_t *local_masterkey = NULL; uint32_t local_masterkey_len; bson_t *kms_providers = NULL; bson_error_t error = {0}; bson_t *index_keys = NULL; bson_t *index_opts = NULL; mongoc_index_model_t *index_model = NULL; bson_t *schema = NULL; mongoc_client_t *client = NULL; mongoc_collection_t *coll = NULL; mongoc_collection_t *keyvault_coll = NULL; bson_t *to_insert = NULL; bson_t *create_cmd = NULL; bson_t *create_cmd_opts = NULL; mongoc_write_concern_t *wc = NULL; mongoc_client_encryption_t *client_encryption = NULL; mongoc_client_encryption_opts_t *client_encryption_opts = NULL; mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL; char *keyaltnames[] = {"mongoc_encryption_example_4"}; bson_value_t datakey_id = {0}; bson_value_t encrypted_field = {0}; bson_value_t to_encrypt = {0}; mongoc_client_encryption_encrypt_opts_t *encrypt_opts = NULL; bson_value_t decrypted = {0}; mongoc_auto_encryption_opts_t *auto_encryption_opts = NULL; mongoc_client_t *unencrypted_client = NULL; mongoc_collection_t *unencrypted_coll = NULL; mongoc_init (); /* Configure the master key. This must be the same master key that was used * to create the encryption key. */ local_masterkey = hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len); if (!local_masterkey || local_masterkey_len != 96) { fprintf (stderr, "Specify LOCAL_MASTERKEY environment variable as a " "secure random 96 byte hex value.\n"); goto fail; } kms_providers = BCON_NEW ("local", "{", "key", BCON_BIN (0, local_masterkey, local_masterkey_len), "}"); client = mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption"); auto_encryption_opts = mongoc_auto_encryption_opts_new (); mongoc_auto_encryption_opts_set_keyvault_namespace (auto_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL); mongoc_auto_encryption_opts_set_kms_providers (auto_encryption_opts, kms_providers); /* Setting bypass_auto_encryption to true disables automatic encryption but * keeps the automatic decryption behavior. bypass_auto_encryption will also * disable spawning mongocryptd */ mongoc_auto_encryption_opts_set_bypass_auto_encryption (auto_encryption_opts, true); /* Once bypass_auto_encryption is set, community users can enable auto * encryption on the client. This will, in fact, only perform automatic * decryption. */ ret = mongoc_client_enable_auto_encryption (client, auto_encryption_opts, &error); if (!ret) { goto fail; } /* Now that automatic decryption is on, we can test it by inserting a * document with an explicitly encrypted value into the collection. When we * look up the document later, it should be automatically decrypted for us. */ coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL); /* Clear old data */ mongoc_collection_drop (coll, NULL); /* Set up the key vault for this example. */ keyvault_coll = mongoc_client_get_collection (client, KEYVAULT_DB, KEYVAULT_COLL); mongoc_collection_drop (keyvault_coll, NULL); /* Create a unique index to ensure that two data keys cannot share the same * keyAltName. This is recommended practice for the key vault. */ index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1)); index_opts = BCON_NEW ("unique", BCON_BOOL (true), "partialFilterExpression", "{", "keyAltNames", "{", "$exists", BCON_BOOL (true), "}", "}"); index_model = mongoc_index_model_new (index_keys, index_opts); ret = mongoc_collection_create_indexes_with_opts ( keyvault_coll, &index_model, 1, NULL /* opts */, NULL /* reply */, &error); if (!ret) { goto fail; } client_encryption_opts = mongoc_client_encryption_opts_new (); mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts, kms_providers); mongoc_client_encryption_opts_set_keyvault_namespace (client_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL); /* The key vault client is used for reading to/from the key vault. This can * be the same mongoc_client_t used by the application. */ mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts, client); client_encryption = mongoc_client_encryption_new (client_encryption_opts, &error); if (!client_encryption) { goto fail; } /* Create a new data key for the encryptedField. * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules */ datakey_opts = mongoc_client_encryption_datakey_opts_new (); mongoc_client_encryption_datakey_opts_set_keyaltnames (datakey_opts, keyaltnames, 1); ret = mongoc_client_encryption_create_datakey (client_encryption, "local", datakey_opts, &datakey_id, &error); if (!ret) { goto fail; } /* Explicitly encrypt a field. */ encrypt_opts = mongoc_client_encryption_encrypt_opts_new (); mongoc_client_encryption_encrypt_opts_set_algorithm (encrypt_opts, MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC); mongoc_client_encryption_encrypt_opts_set_keyaltname (encrypt_opts, "mongoc_encryption_example_4"); to_encrypt.value_type = BSON_TYPE_UTF8; to_encrypt.value.v_utf8.str = "123456789"; const size_t len = strlen (to_encrypt.value.v_utf8.str); BSON_ASSERT (bson_in_range_unsigned (uint32_t, len)); to_encrypt.value.v_utf8.len = (uint32_t) len; ret = mongoc_client_encryption_encrypt (client_encryption, &to_encrypt, encrypt_opts, &encrypted_field, &error); if (!ret) { goto fail; } to_insert = bson_new (); BSON_APPEND_VALUE (to_insert, "encryptedField", &encrypted_field); ret = mongoc_collection_insert_one (coll, to_insert, NULL /* opts */, NULL /* reply */, &error); if (!ret) { goto fail; } /* When we retrieve the document, any encrypted fields will get automatically * decrypted by the driver. */ printf ("decrypted document: "); if (!print_one_document (coll, &error)) { goto fail; } printf ("\n"); unencrypted_client = mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption"); unencrypted_coll = mongoc_client_get_collection (unencrypted_client, ENCRYPTED_DB, ENCRYPTED_COLL); printf ("encrypted document: "); if (!print_one_document (unencrypted_coll, &error)) { goto fail; } printf ("\n"); exit_status = EXIT_SUCCESS; fail: if (error.code) { fprintf (stderr, "error: %s\n", error.message); } bson_free (local_masterkey); bson_destroy (kms_providers); mongoc_collection_destroy (keyvault_coll); mongoc_index_model_destroy (index_model); bson_destroy (index_opts); bson_destroy (index_keys); mongoc_collection_destroy (coll); mongoc_client_destroy (client); bson_destroy (to_insert); bson_destroy (schema); bson_destroy (create_cmd); bson_destroy (create_cmd_opts); mongoc_write_concern_destroy (wc); mongoc_client_encryption_destroy (client_encryption); mongoc_client_encryption_datakey_opts_destroy (datakey_opts); mongoc_client_encryption_opts_destroy (client_encryption_opts); bson_value_destroy (&encrypted_field); mongoc_client_encryption_encrypt_opts_destroy (encrypt_opts); bson_value_destroy (&decrypted); bson_value_destroy (&datakey_id); mongoc_collection_destroy (unencrypted_coll); mongoc_client_destroy (unencrypted_client); mongoc_auto_encryption_opts_destroy (auto_encryption_opts); mongoc_cleanup (); return exit_status; }