๋น ๋ฅธ ์์
์ด ํ์ด์ง์ ๋ด์ฉ
- ๊ฐ์
- ์์ํ๊ธฐ ์ ์
- ์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์ ์ฝ๋
- ์ ์ฐจ
- ๊ณ ๊ฐ ๋ง์คํฐ ํค ์์ฑ
- ํค ๋ณผํธ collection์ ๊ณ ์ ์ธ๋ฑ์ค ๋ง๋ค๊ธฐ
- ๋ฐ์ดํฐ ์ํธํ ํค ์์ฑ
- MongoClient ๊ตฌ์ฑ
- ์ํธํ๋ ํ๋๊ฐ ์๋ ๋ฌธ์ ์ฝ์ ํ๊ธฐ
- ์ํธํ๋ ํ๋๋ก ๋ฌธ์ ๊ฒ์ํ๊ธฐ
- ์์ธํ ์์๋ณด๊ธฐ
๊ฐ์
์ด ๊ฐ์ด๋์์๋ ์๋ CSFLE(ํด๋ผ์ด์ธํธ ์ธก ํ๋ ๋ ๋ฒจ ์ํธํ) ๋ฐ MongoDB ๋๋ผ์ด๋ฒ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฌธ์๋ฅผ ์ํธํํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค.
์ด ๊ฐ์ด๋๋ฅผ ์๋ฃํ ํ์๋ ๋ค์ ์ง์๊ณผ ์ํํธ์จ์ด๋ฅผ ๊ฐ๊ฒ ๋ฉ๋๋ค.
๋ฌธ์์ ํ๋๋ฅผ ์ํธํํ๋๋ก ๋๋ผ์ด๋ฒ๋ฅผ ๊ตฌ์ฑํ๋ ๋จ๊ณ๋ฅผ ์ดํดํฉ๋๋ค.
์๋ํ์ง๋ง ํ๋ก๋์ ์ค๋น๊ฐ ๋์ง ์์ ํด๋ผ์ด์ธํธ ์ ํ๋ฆฌ์ผ์ด์ ์ผ๋ก ์๋ ํด๋ผ์ด์ธํธ ์ธก ํ๋ ๋ ๋ฒจ ์ํธํ๋ฅผ ํ์ฉํฉ๋๋ค.
์ค์
์ด ์ ํ๋ฆฌ์ผ์ด์ ์ ํ๋ก๋์ ํ๊ฒฝ์์๋ ์ฌ์ฉํ์ง ๋ง์ธ์.
์ด ์์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ํ์ผ ์์คํ ์ ์ํธํ ํค๋ฅผ ์ ์ฅํ๋ฏ๋ก ํค์ ๋ฌด๋จ์ผ๋ก ์ก์ธ์คํ๊ฑฐ๋ ๋ฐ์ดํฐ๋ฅผ ํด๋ ํ๊ธฐ ์ํ ํค๋ฅผ ๋ถ์คํ ์ํ์ด ์์ต๋๋ค.
ํ๋ก๋์ ์ฉ CSFLE ์ง์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง๋๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ฃผ๋ ํํ ๋ฆฌ์ผ์ ๋ณด๋ ค๋ฉด ํํ ๋ฆฌ์ผ์ ์ฐธ์กฐํ์ธ์.
์์ํ๊ธฐ ์ ์
์ด ๊ฐ์ด๋์ ์ฝ๋๋ฅผ ์๋ฃํ๊ณ ์คํํ๋ ค๋ฉด ์ค์น ์๊ตฌ ์ฌํญ ํ์ด์ง์ ํ์๋ ๋๋ก ๊ฐ๋ฐ ํ๊ฒฝ์ ์ค์ ํด์ผ ํฉ๋๋ค.
ํ์ด์ง ์ค๋ฅธ์ชฝ์ Select your language ๋๋กญ๋ค์ด ๋ฉ๋ด์์ ์ฝ๋ ์์๋ฅผ ๋ณด๋ ค๋ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ฅผ ์ ํํฉ๋๋ค.
์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์ ์ฝ๋
์ํ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ์ฒด ์ฝ๋๋ฅผ ๋ณด๋ ค๋ฉด ์ธ์ด ์ ํ๊ธฐ์์ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด ๋ฅผ ์ ํํ์ธ์.
์ ์ฐจ
// You are viewing the C# driver code examples. // Use the dropdown menu to select a different driver.
// You are viewing the Golang driver code examples. // Use the dropdown menu to select a different driver.
์ค์
go build
๋๋ go run
๋ฅผ ์ฌ์ฉํ์ฌ ์ด ๊ฐ์ด๋ ์ Go ์ฝ๋๋ฅผ ๋น๋ํ๊ฑฐ๋ ์คํ ๋๋ ํญ์ cse
๋น๋ ์ ์ฝ ์กฐ๊ฑด์ ํฌํจํ์ฌ CSFLE ๋ฅผ ํ์ฑํ ํ์ธ์. ๋น๋ ์ ์ฝ ์กฐ๊ฑด์ ํฌํจํ๋ ์์ ๋ ๋ค์ shell ๋ช
๋ น์ ์ฐธ์กฐํ์ธ์.
go run -tags cse insert-encrypted-document.go
// You are viewing the Java synchronous driver code examples. // Use the dropdown menu to select a different driver.
// You are viewing the Node.js driver code examples. // Use the dropdown menu to select a different driver.
# You are viewing the Python driver code examples. # Use the dropdown menu to select a different driver.
๊ณ ๊ฐ ๋ง์คํฐ ํค ์์ฑ
CSFLE๋ฅผ ์ํํ๋ ค๋ฉด ๊ณ ๊ฐ ๋ง์คํฐ ํค(CMK)๋ฅผ ์์ฑํด์ผ ํฉ๋๋ค.
96๋ฐ์ดํธ ๊ณ ๊ฐ ๋ง์คํฐ ํค๋ฅผ ์์ฑํ๊ณ ํ์ผ ์์คํ
์ธ ๋ก์ปฌ ํค ์ ๊ณต์ ์ master-key.txt
ํ์ผ๋ก ์ ์ฅํฉ๋๋ค.
const fs = require("fs"); const crypto = require("crypto"); try { fs.writeFileSync("master-key.txt", crypto.randomBytes(96)); } catch (err) { console.error(err); }
using (var randomNumberGenerator = System.Security.Cryptography.RandomNumberGenerator.Create()) { var bytes = new byte[96]; randomNumberGenerator.GetBytes(bytes); var localMasterKeyBase64Write = Convert.ToBase64String(bytes); Console.WriteLine(localMasterKeyBase64Write); File.WriteAllText("master-key.txt", localMasterKeyBase64Write); }
func localMasterKey() []byte { key := make([]byte, 96) if _, err := rand.Read(key); err != nil { log.Fatalf("Unable to create a random 96 byte data key: %v", err) } if err := ioutil.WriteFile("master-key.txt", key, 0644); err != nil { log.Fatalf("Unable to write key to file: %v", err) } return key }
byte[] localMasterKeyWrite = new byte[96]; new SecureRandom().nextBytes(localMasterKeyWrite); try (FileOutputStream stream = new FileOutputStream("master-key.txt")) { stream.write(localMasterKeyWrite); }
import os path = "master-key.txt" file_bytes = os.urandom(96) with open(path, "wb") as f: f.write(file_bytes)
๊ฒฝ๊ณ
ํ๋ก๋์ ์์ ๋ก์ปฌ ํค ํ์ผ ๋ณดํธ
๊ณ ๊ฐ ๋ง์คํฐ ํค๋ฅผ ์๊ฒฉ ํค ๊ด๋ฆฌ ์์คํ ์ ์ ์ฅํ๋ ๊ฒ์ด ์ข์ต๋๋ค. (KMS ). Queryable Encryption ๊ตฌํ ์์ ์๊ฒฉ KMS ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ํ์ต ๋ณด๋ ค๋ฉด ํํ ๋ฆฌ์ผ ๊ฐ์ด๋ ๋ฅผ ์ฐธ์กฐํ์ธ์.
ํ๋ก๋์ ํ๊ฒฝ์์ ๋ก์ปฌ ํค ์ ๊ณต์ ๋ฅผ ์ฌ์ฉํ๊ธฐ๋ก ์ ํํ ๊ฒฝ์ฐ์๋ ๊ฐ๋ณํ ์ฃผ์๋ฅผ ๊ธฐ์ธ์ด๊ณ ํ์ผ ์์คํ ์ ์ ์ฅ ํ์ง ์๋๋ก ํฉ๋๋ค. ์ฌ์ด๋์นด ํ๋ก์ธ์ค ๋ฅผ ์ฌ์ฉํ์ฌ ํด๋ผ์ด์ธํธ ์ ํ๋ฆฌ์ผ์ด์ ์ ํค๋ฅผ ์ฝ์ ํ๊ฑฐ๋ ํค๋ฅผ ์์ ํ๊ฒ ๋ณดํธํ๋ ๋ค๋ฅธ ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
ํ
๋ช ๋ น์ค์์ ๊ณ ๊ฐ ๋ง์คํฐ ํค ์์ฑ
Unix shell ๋๋ PowerShell์์ ๊ณ ๊ฐ ๋ง์คํฐ ํค ๋ฅผ ์์ฑํ๋ ค๋ฉด ๋ค์ ๋ช ๋ น์ ์ฌ์ฉํฉ๋๋ค.
Unix/macOS ์ ธ:
echo $(head -c 96 /dev/urandom | base64 | tr -d '\n') PowerShell:
$r=[byte[]]::new(64);$g=[System.Security.Cryptography.RandomNumberGenerator]::Create();$g.GetBytes($r);[Convert]::ToBase64String($r)
์ด์ ๋ช
๋ น์ ์ถ๋ ฅ์ customer-master-key.txt
ํ์ผ์ ์ ์ฅํฉ๋๋ค.
ํ
์ฐธ์กฐ: ์ฝ๋ ์์ฑ
๊ณ ๊ฐ ๋ง์คํฐ ํค๋ฅผ ๋ง๋ค๊ธฐ ์ํ ์ ์ฒด ์ฝ๋๋ฅผ ๋ณด๋ ค๋ฉด Github ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ์ฐธ์กฐํ์ธ์.
๊ณ ๊ฐ ๋ง์คํฐ ํค๋ฅผ ๋ง๋ค๊ธฐ ์ํ ์ ์ฒด ์ฝ๋๋ฅผ ๋ณด๋ ค๋ฉด Github ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ์ฐธ์กฐํ์ธ์.
๊ณ ๊ฐ ๋ง์คํฐ ํค๋ฅผ ๋ง๋ค๊ธฐ ์ํ ์ ์ฒด ์ฝ๋๋ฅผ ๋ณด๋ ค๋ฉด Github ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ์ฐธ์กฐํ์ธ์.
๊ณ ๊ฐ ๋ง์คํฐ ํค๋ฅผ ๋ง๋ค๊ธฐ ์ํ ์ ์ฒด ์ฝ๋๋ฅผ ๋ณด๋ ค๋ฉด Github ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ์ฐธ์กฐํ์ธ์.
๊ณ ๊ฐ ๋ง์คํฐ ํค๋ฅผ ๋ง๋ค๊ธฐ ์ํ ์ ์ฒด ์ฝ๋๋ฅผ ๋ณด๋ ค๋ฉด Github ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ์ฐธ์กฐํ์ธ์.
ํค ๋ณผํธ collection์ ๊ณ ์ ์ธ๋ฑ์ค ๋ง๋ค๊ธฐ
encryption.__keyVault
๋ค์์คํ์ด์ค์ keyAltNames
ํ๋์ ๋ถ๋ถ ๊ณ ์ ์ธ๋ฑ์ค๋ฅผ ์์ฑํฉ๋๋ค. ์ด ์ธ๋ฑ์ค๋ keyAltNames
๊ฐ ์กด์ฌํ๋ ๋ฌธ์์ ๋ํด partialFilterExpression
์ ๊ฐ์ ธ์ผ ํฉ๋๋ค.
ํด๋ผ์ด์ธํธ ์ธก ํ๋ ๋ ๋ฒจ ์ํธํ๋ ์๋ฒ์์ ์ ์ฉ๋๋ ํค ๋์ฒด ์ด๋ฆ์ ๊ณ ์ ์ฑ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค.
์ ํธํ๋ MongoDB ๋๋ผ์ด๋ฒ์ ํด๋นํ๋ ํญ์ ์ ํํฉ๋๋ค:
var connectionString = "<Your MongoDB URI>"; var keyVaultNamespace = CollectionNamespace.FromFullName("encryption.__keyVault"); var keyVaultClient = new MongoClient(connectionString); var indexOptions = new CreateIndexOptions<BsonDocument>(); indexOptions.Unique = true; indexOptions.PartialFilterExpression = new BsonDocument { { "keyAltNames", new BsonDocument { { "$exists", new BsonBoolean(true) } } } }; var builder = Builders<BsonDocument>.IndexKeys; var indexKeysDocument = builder.Ascending("keyAltNames"); var indexModel = new CreateIndexModel<BsonDocument>(indexKeysDocument, indexOptions); var keyVaultDatabase = keyVaultClient.GetDatabase(keyVaultNamespace.DatabaseNamespace.ToString()); // Drop the Key Vault Collection in case you created this collection // in a previous run of this application. keyVaultDatabase.DropCollection(keyVaultNamespace.CollectionName); // Drop the database storing your encrypted fields as all // the DEKs encrypting those fields were deleted in the preceding line. keyVaultClient.GetDatabase("medicalRecords").DropCollection("patients"); var keyVaultCollection = keyVaultDatabase.GetCollection<BsonDocument>(keyVaultNamespace.CollectionName.ToString()); keyVaultCollection.Indexes.CreateOne(indexModel);
uri := "<Your MongoDB URI>" keyVaultClient, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri)) if err != nil { return fmt.Errorf("Connect error for regular client: %v", err) } defer func() { _ = keyVaultClient.Disconnect(context.TODO()) }() keyVaultColl := "__keyVault" keyVaultDb := "encryption" keyVaultNamespace := keyVaultDb + "." + keyVaultColl keyVaultIndex := mongo.IndexModel{ Keys: bson.D{{"keyAltNames", 1}}, Options: options.Index(). SetUnique(true). SetPartialFilterExpression(bson.D{ {"keyAltNames", bson.D{ {"$exists", true}, }}, }), } // Drop the Key Vault Collection in case you created this collection // in a previous run of this application. if err = keyVaultClient.Database(keyVaultDb).Collection(keyVaultColl).Drop(context.TODO()); err != nil { log.Fatalf("Collection.Drop error: %v", err) } // Drop the database storing your encrypted fields as all // the DEKs encrypting those fields were deleted in the preceding line. if err = keyVaultClient.Database("medicalRecords").Collection("patients").Drop(context.TODO()); err != nil { log.Fatalf("Collection.Drop error: %v", err) } _, err = keyVaultClient.Database(keyVaultDb).Collection(keyVaultColl).Indexes().CreateOne(context.TODO(), keyVaultIndex) if err != nil { panic(err) }
String connectionString = "<Your MongoDB URI>"; String keyVaultDb = "encryption"; String keyVaultColl = "__keyVault"; String keyVaultNamespace = keyVaultDb + "." + keyVaultColl; MongoClient keyVaultClient = MongoClients.create(connectionString); // Drop the Key Vault Collection in case you created this collection // in a previous run of this application. keyVaultClient.getDatabase(keyVaultDb).getCollection(keyVaultColl).drop(); // Drop the database storing your encrypted fields as all // the DEKs encrypting those fields were deleted in the preceding line. keyVaultClient.getDatabase("medicalRecords").getCollection("patients").drop(); MongoCollection keyVaultCollection = keyVaultClient.getDatabase(keyVaultDb).getCollection(keyVaultColl); IndexOptions indexOpts = new IndexOptions().partialFilterExpression(new BsonDocument("keyAltNames", new BsonDocument("$exists", new BsonBoolean(true) ))).unique(true); keyVaultCollection.createIndex(new BsonDocument("keyAltNames", new BsonInt32(1)), indexOpts); keyVaultClient.close();
const uri = "<Your Connection String>"; const keyVaultDatabase = "encryption"; const keyVaultCollection = "__keyVault"; const keyVaultNamespace = `${keyVaultDatabase}.${keyVaultCollection}`; const keyVaultClient = new MongoClient(uri); await keyVaultClient.connect(); const keyVaultDB = keyVaultClient.db(keyVaultDatabase); // Drop the Key Vault Collection in case you created this collection // in a previous run of this application. await keyVaultDB.dropDatabase(); // Drop the database storing your encrypted fields as all // the DEKs encrypting those fields were deleted in the preceding line. await keyVaultClient.db("medicalRecords").dropDatabase(); const keyVaultColl = keyVaultDB.collection(keyVaultCollection); await keyVaultColl.createIndex( { keyAltNames: 1 }, { unique: true, partialFilterExpression: { keyAltNames: { $exists: true } }, } );
connection_string = "<your connection string here>" key_vault_coll = "__keyVault" key_vault_db = "encryption" key_vault_namespace = f"{key_vault_db}.{key_vault_coll}" key_vault_client = MongoClient(connection_string) # Drop the Key Vault Collection in case you created this collection # in a previous run of this application. key_vault_client.drop_database(key_vault_db) # Drop the database storing your encrypted fields as all # the DEKs encrypting those fields were deleted in the preceding line. key_vault_client["medicalRecords"].drop_collection("patients") key_vault_client[key_vault_db][key_vault_coll].create_index( [("keyAltNames", ASCENDING)], unique=True, partialFilterExpression={"keyAltNames": {"$exists": True}}, )
๋ฐ์ดํฐ ์ํธํ ํค ์์ฑ
๊ณ ๊ฐ ๋ง์คํฐ ํค ์ฝ๊ธฐ ๋ฐ KMS ์ ๊ณต์ ์ค์ ์ง์
์ด ๊ฐ์ด๋์ ๊ณ ๊ฐ ๋ง์คํฐ ํค ์์ฑ ๋จ๊ณ์์ ์์ฑํ ๊ณ ๊ฐ ๋ง์คํฐ ํค ํ์ผ์ ๋ด์ฉ์ ์กฐํํฉ๋๋ค.
KMS ์ ๊ณต์ ์ค์ ์์ CMK ๊ฐ์ ์ฌ์ฉํฉ๋๋ค. ํด๋ผ์ด์ธํธ ๋ ์ด๋ฌํ ์ค์ ์ ์ฌ์ฉํ์ฌ CMK ๋ฅผ ๊ฒ์ํฉ๋๋ค. ๋ก์ปฌ ํค ์ ๊ณต์๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์ ๊ณต์ ์ด๋ฆ์
local
๋ก ์ค์ ํ๋ค ํฉ๋๋ค.var kmsProviders = new Dictionary<string, IReadOnlyDictionary<string, object>>(); var provider = "local"; string localMasterKeyBase64Read = File.ReadAllText("master-key.txt"); var localMasterKeyBytes = Convert.FromBase64String(localMasterKeyBase64Read); var localOptions = new Dictionary<string, object> { { "key", localMasterKeyBytes } }; kmsProviders.Add("local", localOptions); key, err := ioutil.ReadFile("master-key.txt") if err != nil { log.Fatalf("Could not read the key from master-key.txt: %v", err) } provider := "local" kmsProviders := map[string]map[string]interface{}{"local": {"key": key}} String kmsProvider = "local"; String path = "master-key.txt"; byte[] localMasterKeyRead = new byte[96]; try (FileInputStream fis = new FileInputStream(path)) { if (fis.read(localMasterKeyRead) < 96) throw new Exception("Expected to read 96 bytes from file"); } Map<String, Object> keyMap = new HashMap<String, Object>(); keyMap.put("key", localMasterKeyRead); Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>(); kmsProviders.put("local", keyMap); const provider = "local"; const path = "./master-key.txt"; const localMasterKey = fs.readFileSync(path); const kmsProviders = { local: { key: localMasterKey, }, }; path = "./master-key.txt" with open(path, "rb") as f: local_master_key = f.read() kms_providers = { "local": { "key": local_master_key # local_master_key variable from the previous step }, } ๋ฐ์ดํฐ ์ํธํ ํค ์์ฑ
MongoDB ์ฐ๊ฒฐ ๋ฌธ์์ด๊ณผ ํค ๋ณผํธ ์ปฌ๋ ์ ๋ค์์คํ์ด์ค๋ฅผ ์ฌ์ฉํ์ฌ ํด๋ผ์ด์ธํธ๋ฅผ ๊ตฌ์ฑํ๊ณ ๋ฐ์ดํฐ ์ํธํ ํค๋ฅผ ๋ง๋ญ๋๋ค.
์ฐธ๊ณ
ํค ๋ณผํธ ์ปฌ๋ ์ ๋ค์์คํ์ด์ค ๊ถํ
์ด ํํ ๋ฆฌ์ผ์ ์๋ฃํ๋ ค๋ฉด ์ ํ๋ฆฌ์ผ์ด์ ์์ MongoDB์ ์ฐ๊ฒฐํ๋ ๋ฐ ์ฌ์ฉํ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฌ์ฉ์์๊ฒ ๋ค์ ๋ค์์คํ์ด์ค์ ๋ํ
dbAdmin
๊ถํ์ด ์์ด์ผ ํฉ๋๋ค.encryption.__keyVault
medicalRecords
database
var clientEncryptionOptions = new ClientEncryptionOptions( keyVaultClient: keyVaultClient, keyVaultNamespace: keyVaultNamespace, kmsProviders: kmsProviders ); var clientEncryption = new ClientEncryption(clientEncryptionOptions); var dataKeyOptions = new DataKeyOptions(); var dataKeyId = clientEncryption.CreateDataKey(provider, dataKeyOptions, CancellationToken.None); var dataKeyIdBase64 = Convert.ToBase64String(GuidConverter.ToBytes(dataKeyId, GuidRepresentation.Standard)); Console.WriteLine($"DataKeyId [base64]: {dataKeyIdBase64}"); clientEncryptionOpts := options.ClientEncryption().SetKeyVaultNamespace(keyVaultNamespace). SetKmsProviders(kmsProviders) clientEnc, err := mongo.NewClientEncryption(keyVaultClient, clientEncryptionOpts) if err != nil { return fmt.Errorf("NewClientEncryption error %v", err) } defer func() { _ = clientEnc.Close(context.TODO()) }() dataKeyOpts := options.DataKey() dataKeyID, err := clientEnc.CreateDataKey(context.TODO(), provider, dataKeyOpts) if err != nil { return fmt.Errorf("create data key error %v", err) } fmt.Printf("DataKeyId [base64]: %s\n", base64.StdEncoding.EncodeToString(dataKeyID.Data)) ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder() .keyVaultMongoClientSettings(MongoClientSettings.builder() .applyConnectionString(new ConnectionString(connectionString)) .build()) .keyVaultNamespace(keyVaultNamespace) .kmsProviders(kmsProviders) .build(); MongoClient regularClient = MongoClients.create(connectionString); ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings); BsonBinary dataKeyId = clientEncryption.createDataKey(kmsProvider, new DataKeyOptions()); String base64DataKeyId = Base64.getEncoder().encodeToString(dataKeyId.getData()); System.out.println("DataKeyId [base64]: " + base64DataKeyId); clientEncryption.close(); const client = new MongoClient(uri); await client.connect(); const encryption = new ClientEncryption(client, { keyVaultNamespace, kmsProviders, }); const key = await encryption.createDataKey(provider); console.log("DataKeyId [base64]: ", key.toString("base64")); await keyVaultClient.close(); await client.close(); ์ฐธ๊ณ
ํด๋ผ์ด์ธํธ ์ํธํ ๊ฐ์ ธ์ค๊ธฐ
Node.js ๋๋ผ์ด๋ฒ v6.0 ์ด์์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ
mongodb
์์ClientEncryption
์(๋ฅผ) ๊ฐ์ ธ์์ผ ํฉ๋๋ค.์ด์ ๋๋ผ์ด๋ฒ ๋ฒ์ ์ ๊ฒฝ์ฐ
mongodb-client-encryption
์์ClientEncryption
์(๋ฅผ) ๊ฐ์ ธ์ต๋๋ค.key_vault_database = "encryption" key_vault_collection = "__keyVault" key_vault_namespace = f"{key_vault_database}.{key_vault_collection}" client = MongoClient(connection_string) client_encryption = ClientEncryption( kms_providers, # pass in the kms_providers variable from the previous step key_vault_namespace, client, CodecOptions(uuid_representation=STANDARD), ) data_key_id = client_encryption.create_data_key("local") base_64_data_key_id = base64.b64encode(data_key_id) print("DataKeyId [base64]: ", base_64_data_key_id) ์ ์ฝ๋์ ์ถ๋ ฅ์ ๋ค์๊ณผ ์ ์ฌํด์ผ ํฉ๋๋ค.
DataKeyId [base64]: 3k13WkSZSLy7kwAAP4HDyQ==
ํ
์ฐธ์กฐ: ์ฝ๋ ์์ฑ
๋ฐ์ดํฐ ์ํธํ ํค๋ฅผ ๋ง๋ค๊ธฐ ์ํ ์ ์ฒด ์ฝ๋๋ฅผ ๋ณด๋ ค๋ฉด Github ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ์ฐธ์กฐํ์ธ์.
๋ฐ์ดํฐ ์ํธํ ํค๋ฅผ ๋ง๋ค๊ธฐ ์ํ ์ ์ฒด ์ฝ๋๋ฅผ ๋ณด๋ ค๋ฉด Github ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ์ฐธ์กฐํ์ธ์.
๋ฐ์ดํฐ ์ํธํ ํค๋ฅผ ๋ง๋ค๊ธฐ ์ํ ์ ์ฒด ์ฝ๋๋ฅผ ๋ณด๋ ค๋ฉด Github ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ์ฐธ์กฐํ์ธ์.
๋ฐ์ดํฐ ์ํธํ ํค๋ฅผ ๋ง๋ค๊ธฐ ์ํ ์ ์ฒด ์ฝ๋๋ฅผ ๋ณด๋ ค๋ฉด Github ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ์ฐธ์กฐํ์ธ์.
๋ฐ์ดํฐ ์ํธํ ํค๋ฅผ ๋ง๋ค๊ธฐ ์ํ ์ ์ฒด ์ฝ๋๋ฅผ ๋ณด๋ ค๋ฉด Github ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ์ฐธ์กฐํ์ธ์.
MongoClient ๊ตฌ์ฑ
ํค ๋ณผํธ collection ๋ค์์คํ์ด์ค ์ง์ ํ๊ธฐ
ํค ๋ณผํธ collection ๋ค์์คํ์ด์ค๋ก
encryption.__keyVault
์ ์ง์ ํฉ๋๋ค.var keyVaultNamespace = CollectionNamespace.FromFullName("encryption.__keyVault"); keyVaultNamespace := "encryption.__keyVault" String keyVaultNamespace = "encryption.__keyVault"; const keyVaultNamespace = "encryption.__keyVault"; key_vault_namespace = "encryption.__keyVault" ๋ก์ปฌ ๊ณ ๊ฐ ๋ง์คํฐ ํค ์ง์
KMS ์ ๊ณต์๋ฅผ ์ง์ ํ๊ณ ํค๋ฅผ ์ธ๋ผ์ธ์ผ๋ก ์ง์ ํฉ๋๋ค.
var kmsProviders = new Dictionary<string, IReadOnlyDictionary<string, object>>(); var provider = "local"; var localMasterKeyPath = "master-key.txt"; string localMasterKeyBase64Read = File.ReadAllText(localMasterKeyPath); var localMasterKeyBytes = Convert.FromBase64String(localMasterKeyBase64Read); var localOptions = new Dictionary<string, object> { { "key", localMasterKeyBytes } }; kmsProviders.Add(provider, localOptions); key, err := ioutil.ReadFile("master-key.txt") if err != nil { log.Fatalf("Could not read the key from master-key.txt: %v", err) } kmsProviders := map[string]map[string]interface{}{"local": {"key": key}} String kmsProvider = "local"; String path = "master-key.txt"; byte[] localMasterKeyRead = new byte[96]; try (FileInputStream fis = new FileInputStream(path)) { if (fis.read(localMasterKeyRead) < 96) throw new Exception("Expected to read 96 bytes from file"); } Map<String, Object> keyMap = new HashMap<String, Object>(); keyMap.put("key", localMasterKeyRead); Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>(); kmsProviders.put("local", keyMap); const fs = require("fs"); const provider = "local"; const path = "./master-key.txt"; const localMasterKey = fs.readFileSync(path); const kmsProviders = { local: { key: localMasterKey, }, }; path = "./master-key.txt" with open(path, "rb") as f: local_master_key = f.read() kms_providers = { "local": { "key": local_master_key # local_master_key variable from the previous step }, } ์ปฌ๋ ์ ์ ๋ํ ์ํธํ ์คํค๋ง ๋ง๋ค๊ธฐ
ํ
๋ฐ์ดํฐ ์ํธํ ํค Base64 ID ์ถ๊ฐํ๊ธฐ
๊ธฐ๋ณธ64 DEK ID๋ฅผ ํฌํจํ๋๋ก ๋ค์ ์ฝ๋๋ฅผ ์ ๋ฐ์ดํธํด์ผ ํฉ๋๋ค. ์ด ๊ฐ์ด๋์ ๋ฐ์ดํฐ ์ํธํ ํค ์์ฑ ๋จ๊ณ์์ ์ด ๊ฐ์ ๋ฐ์์ต๋๋ค.
var keyId = "<Your base64 DEK ID here>"; var schema = new BsonDocument { { "bsonType", "object" }, { "encryptMetadata", new BsonDocument("keyId", new BsonArray(new[] { new BsonBinaryData(Convert.FromBase64String(keyId), BsonBinarySubType.UuidStandard) })) }, { "properties", new BsonDocument { { "ssn", new BsonDocument { { "encrypt", new BsonDocument { { "bsonType", "int" }, { "algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } } } }, { "bloodType", new BsonDocument { { "encrypt", new BsonDocument { { "bsonType", "string" }, { "algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } } } } }, { "medicalRecords", new BsonDocument { { "encrypt", new BsonDocument { { "bsonType", "array" }, { "algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } } } } }, { "insurance", new BsonDocument { { "bsonType", "object" }, { "properties", new BsonDocument { { "policyNumber", new BsonDocument { { "encrypt", new BsonDocument { { "bsonType", "int" }, { "algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } } } } } } } } } } }; var schemaMap = new Dictionary<string, BsonDocument>(); schemaMap.Add(dbNamespace, schema); dek_id := "<Your Base64 DEK ID>" schema_template := `{ "bsonType": "object", "encryptMetadata": { "keyId": [ { "$binary": { "base64": "%s", "subType": "04" } } ] }, "properties": { "insurance": { "bsonType": "object", "properties": { "policyNumber": { "encrypt": { "bsonType": "int", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } } }, "medicalRecords": { "encrypt": { "bsonType": "array", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "bloodType": { "encrypt": { "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "ssn": { "encrypt": { "bsonType": "int", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } } }` schema := fmt.Sprintf(schema_template, dek_id) var schemaDoc bson.Raw if err := bson.UnmarshalExtJSON([]byte(schema), true, &schemaDoc); err != nil { return fmt.Errorf("UnmarshalExtJSON error: %v", err) } schemaMap := map[string]interface{}{ dbName + "." + collName: schemaDoc, } String dekId = "<paste-base-64-encoded-data-encryption-key-id>>"; Document jsonSchema = new Document().append("bsonType", "object").append("encryptMetadata", new Document().append("keyId", new ArrayList<>((Arrays.asList(new Document().append("$binary", new Document() .append("base64", dekId) .append("subType", "04"))))))) .append("properties", new Document() .append("ssn", new Document().append("encrypt", new Document() .append("bsonType", "int") .append("algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"))) .append("bloodType", new Document().append("encrypt", new Document() .append("bsonType", "string") .append("algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Random"))) .append("medicalRecords", new Document().append("encrypt", new Document() .append("bsonType", "array") .append("algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Random"))) .append("insurance", new Document() .append("bsonType", "object") .append("properties", new Document().append("policyNumber", new Document().append("encrypt", new Document() .append("bsonType", "int") .append("algorithm", "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic")))))); HashMap<String, BsonDocument> schemaMap = new HashMap<String, BsonDocument>(); schemaMap.put("medicalRecords.patients", BsonDocument.parse(jsonSchema.toJson())); dataKey = "<Your base64 DEK ID>"; const schema = { bsonType: "object", encryptMetadata: { keyId: [new Binary(Buffer.from(dataKey, "base64"), 4)], }, properties: { insurance: { bsonType: "object", properties: { policyNumber: { encrypt: { bsonType: "int", algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", }, }, }, }, medicalRecords: { encrypt: { bsonType: "array", algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Random", }, }, bloodType: { encrypt: { bsonType: "string", algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Random", }, }, ssn: { encrypt: { bsonType: "int", algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", }, }, }, }; var patientSchema = {}; patientSchema[namespace] = schema; dek_id = b"<paste-base-64-encoded-data-encryption-key-id>" json_schema = { "bsonType": "object", "encryptMetadata": {"keyId": [Binary(base64.b64decode(dek_id), UUID_SUBTYPE)]}, "properties": { "insurance": { "bsonType": "object", "properties": { "policyNumber": { "encrypt": { "bsonType": "int", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", } } }, }, "medicalRecords": { "encrypt": { "bsonType": "array", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", } }, "bloodType": { "encrypt": { "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", } }, "ssn": { "encrypt": { "bsonType": "int", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", } }, }, } patient_schema = {"medicalRecords.patients": json_schema} ์๋ ์ํธํ ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์์น ์ง์
var mongoBinariesPath = "<Full path to your Automatic Encryption Shared Library>"; var extraOptions = new Dictionary<string, object>() { { "cryptSharedLibPath", mongoBinariesPath }, }; extraOptions := map[string]interface{}{ "cryptSharedLibPath": "<Full path to your Automatic Encryption Shared Library>", } Map<String, Object> extraOptions = new HashMap<String, Object>(); extraOptions.put("cryptSharedLibPath", "<Full path to your Automatic Encryption Shared Library>")); const extraOptions = { cryptSharedLibPath: "<Full path to your Automatic Encryption Shared Library>", }; extra_options = { "cryptSharedLibPath": "<Full path to your Automatic Encryption Shared Library>" } ์ฐธ๊ณ
์๋ ์ํธํ ์ต์
์๋ ์ํธํ ์ต์ ์ ์๋ ์ํธํ ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ตฌ์ฑ ์ ๋ณด๋ฅผ ์ ๊ณตํ์ฌ ์ํธํ๋ ํ๋์ ์ก์ธ์คํ ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋์์ ์์ ํฉ๋๋ค.
์๋ ์ํธํ ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํ์ต ๋ณด๋ ค๋ฉด CSFLE ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น ๋ฐ ๊ตฌ์ฑ ํ์ด์ง๋ฅผ ์ฐธ์กฐํ์ธ์.
MongoClient ์์ฑ
๋ค์ ์๋ ์ํธํ ์ค์ ์ ์ฌ์ฉํ์ฌ MongoDB ํด๋ผ์ด์ธํธ ๊ฐ์ฒด๋ฅผ ์ธ์คํด์คํํฉ๋๋ค.
MongoClientSettings.Extensions.AddAutoEncryption(); // .NET/C# Driver v3.0 or later only var clientSettings = MongoClientSettings.FromConnectionString(connectionString); var autoEncryptionOptions = new AutoEncryptionOptions( keyVaultNamespace: keyVaultNamespace, kmsProviders: kmsProviders, schemaMap: schemaMap, extraOptions: extraOptions ); clientSettings.AutoEncryptionOptions = autoEncryptionOptions; var secureClient = new MongoClient(clientSettings); var clientSettings = MongoClientSettings.FromConnectionString(connectionString); var autoEncryptionOptions = new AutoEncryptionOptions( keyVaultNamespace: keyVaultNamespace, kmsProviders: kmsProviders, schemaMap: schemaMap, extraOptions: extraOptions ); clientSettings.AutoEncryptionOptions = autoEncryptionOptions; var secureClient = new MongoClient(clientSettings); autoEncryptionOpts := options.AutoEncryption(). SetKmsProviders(kmsProviders). SetKeyVaultNamespace(keyVaultNamespace). SetSchemaMap(schemaMap). SetExtraOptions(extraOptions) secureClient, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri).SetAutoEncryptionOptions(autoEncryptionOpts)) if err != nil { return fmt.Errorf("Connect error for encrypted client: %v", err) } defer func() { _ = secureClient.Disconnect(context.TODO()) }() MongoClientSettings clientSettings = MongoClientSettings.builder() .applyConnectionString(new ConnectionString(connectionString)) .autoEncryptionSettings(AutoEncryptionSettings.builder() .keyVaultNamespace(keyVaultNamespace) .kmsProviders(kmsProviders) .schemaMap(schemaMap) .extraOptions(extraOptions) .build()) .build(); MongoClient mongoClientSecure = MongoClients.create(clientSettings); const secureClient = new MongoClient(connectionString, { autoEncryption: { keyVaultNamespace, kmsProviders, schemaMap: patientSchema, extraOptions: extraOptions, }, }); fle_opts = AutoEncryptionOpts( kms_providers, key_vault_namespace, schema_map=patient_schema, **extra_options ) secureClient = MongoClient(connection_string, auto_encryption_opts=fle_opts)
์ํธํ๋ ํ๋๊ฐ ์๋ ๋ฌธ์ ์ฝ์ ํ๊ธฐ
CSFLE ์ง์ MongoClient
์ธ์คํด์ค๋ฅผ ์ฌ์ฉํ์ฌ ๋ค์ ์ฝ๋ ์ค๋ํซ์ ์ฌ์ฉํ์ฌ ์ํธํ๋ ํ๋๊ฐ ์๋ ๋ฌธ์๋ฅผ medicalRecords.patients
๋ค์์คํ์ด์ค์ ์ฝ์
ํฉ๋๋ค.
var sampleDocFields = new BsonDocument { { "name", "Jon Doe" }, { "ssn", 145014000 }, { "bloodType", "AB-" }, { "medicalRecords", new BsonArray { new BsonDocument("weight", 180), new BsonDocument("bloodPressure", "120/80") } }, { "insurance", new BsonDocument { { "policyNumber", 123142 }, { "provider", "MaestCare" } } } }; // Construct an auto-encrypting client var secureCollection = secureClient.GetDatabase(db).GetCollection<BsonDocument>(coll); // Insert a document into the collection secureCollection.InsertOne(sampleDocFields);
test_patient := map[string]interface{}{ "name": "Jon Doe", "ssn": 241014209, "bloodType": "AB+", "medicalRecords": []map[string]interface{}{{ "weight": 180, "bloodPressure": "120/80", }}, "insurance": map[string]interface{}{ "provider": "MaestCare", "policyNumber": 123142, }, } if _, err := secureClient.Database(dbName).Collection(collName).InsertOne(context.TODO(), test_patient); err != nil { return fmt.Errorf("InsertOne error: %v", err) }
์ฐธ๊ณ
์์ BSON ๋ฌธ์๋ฅผ ๋ง๋๋ ๋์ bson
ํ๊ทธ๊ฐ ์๋ ๊ตฌ์กฐ์ฒด๋ฅผ ๋๋ผ์ด๋ฒ์ ์ง์ ์ ๋ฌํ์ฌ ์ธ์ฝ๋ฉํ ์ ์์ต๋๋ค.
ArrayList<Document> medicalRecords = new ArrayList<>(); medicalRecords.add(new Document().append("weight", "180")); medicalRecords.add(new Document().append("bloodPressure", "120/80")); Document insurance = new Document() .append("policyNumber", 123142) .append("provider", "MaestCare"); Document patient = new Document() .append("name", "Jon Doe") .append("ssn", 241014209) .append("bloodType", "AB+") .append("medicalRecords", medicalRecords) .append("insurance", insurance); mongoClientSecure.getDatabase(recordsDb).getCollection(recordsColl).insertOne(patient);
try { const writeResult = await secureClient .db(db) .collection(coll) .insertOne({ name: "Jon Doe", ssn: 241014209, bloodType: "AB+", medicalRecords: [{ weight: 180, bloodPressure: "120/80" }], insurance: { policyNumber: 123142, provider: "MaestCare", }, }); } catch (writeError) { console.error("writeError occurred:", writeError); }
def insert_patient( collection, name, ssn, blood_type, medical_records, policy_number, provider ): insurance = {"policyNumber": policy_number, "provider": provider} doc = { "name": name, "ssn": ssn, "bloodType": blood_type, "medicalRecords": medical_records, "insurance": insurance, } collection.insert_one(doc) medical_record = [{"weight": 180, "bloodPressure": "120/80"}] insert_patient( secureClient.medicalRecords.patients, "Jon Doe", 241014209, "AB+", medical_record, 123142, "MaestCare", )
๋ฌธ์๋ฅผ ์ฝ์ ํ๋ฉด CSFLE ํ์ฑํ ํด๋ผ์ด์ธํธ๋ ๋ค์๊ณผ ์ ์ฌํ๋๋ก ๋ฌธ์์ ํ๋๋ฅผ ์ํธํํฉ๋๋ค.
{ "_id": { "$oid": "<_id of your document>" }, "name": "Jon Doe", "ssn": { "$binary": "<cipher-text>", "$type": "6" }, "bloodType": { "$binary": "<cipher-text>", "$type": "6" }, "medicalRecords": { "$binary": "<cipher-text>", "$type": "6" }, "insurance": { "provider": "MaestCare", "policyNumber": { "$binary": "<cipher-text>", "$type": "6" } } }
ํ
์ฐธ์กฐ: ์ฝ๋ ์์ฑ
์ํธํ๋จ ํ๋๊ฐ ์๋ ๋ฌธ์ ๋ฅผ ์ฝ์ ํ๊ธฐ ์ํ ์ ์ฒด ์ฝ๋๋ฅผ ๋ณด๋ ค๋ฉด Github ๋ฆฌํฌ์งํ ๋ฆฌ ๋ฅผ ์ฐธ์กฐํ์ธ์.
์ํธํ๋ ํ๋๊ฐ ์๋ ๋ฌธ์๋ฅผ ์ฝ์ ํ๊ธฐ ์ํ ์ ์ฒด ์ฝ๋๋ฅผ ๋ณด๋ ค๋ฉด Github ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ์ฐธ์กฐํ์ธ์.
์ํธํ๋ ํ๋๊ฐ ์๋ ๋ฌธ์๋ฅผ ์ฝ์ ํ๊ธฐ ์ํ ์ ์ฒด ์ฝ๋๋ฅผ ๋ณด๋ ค๋ฉด Github ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ์ฐธ์กฐํ์ธ์.
์ํธํ๋ ํ๋๊ฐ ์๋ ๋ฌธ์๋ฅผ ์ฝ์ ํ๊ธฐ ์ํ ์ ์ฒด ์ฝ๋๋ฅผ ๋ณด๋ ค๋ฉด Github ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ์ฐธ์กฐํ์ธ์.
์ํธํ๋ ํ๋๊ฐ ์๋ ๋ฌธ์๋ฅผ ์ฝ์ ํ๊ธฐ ์ํ ์ ์ฒด ์ฝ๋๋ฅผ ๋ณด๋ ค๋ฉด Github ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ์ฐธ์กฐํ์ธ์.
์ํธํ๋ ํ๋๋ก ๋ฌธ์ ๊ฒ์ํ๊ธฐ
์ด ๊ฐ์ด๋์ ์ํธํ๋ ํ๋๊ฐ ์๋ ๋ฌธ์ ์ฝ์ ๋จ๊ณ์์ ์ฝ์ ํ ์ํธํ๋ ํ๋๊ฐ ์๋ ๋ฌธ์๋ฅผ ๊ฒ์ํฉ๋๋ค.
๋ค์ ์ฝ๋ ์ค๋ํซ์ ์๋ CSFLE๋ฅผ ์ฌ์ฉํ๋๋ก ๊ตฌ์ฑ๋ ํด๋ผ์ด์ธํธ์ ์๋ CSFLE๋ฅผ ์ฌ์ฉํ๋๋ก ๊ตฌ์ฑ๋์ง ์์ ํด๋ผ์ด์ธํธ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฌธ์์ ๋ํด ์ฟผ๋ฆฌํจ์ผ๋ก์จ CSFLE์ ๊ธฐ๋ฅ์ ๋ณด์ฌ ์ค๋๋ค.
Console.WriteLine("Finding a document with regular (non-encrypted) client."); var filter = Builders<BsonDocument>.Filter.Eq("name", "Jon Doe"); var regularResult = regularCollection.Find(filter).Limit(1).ToList()[0]; Console.WriteLine($"\n{regularResult}\n"); Console.WriteLine("Finding a document with encrypted client"); var ssnFilter = Builders<BsonDocument>.Filter.Eq("name", "Jon Doe"); var secureResult = secureCollection.Find(ssnFilter).Limit(1).First(); Console.WriteLine($"\n{secureResult}\n");
fmt.Println("Finding a document with regular (non-encrypted) client.") var resultRegular bson.M err = regularClient.Database(dbName).Collection(collName).FindOne(context.TODO(), bson.D{{"name", "Jon Doe"}}).Decode(&resultRegular) if err != nil { panic(err) } outputRegular, err := json.MarshalIndent(resultRegular, "", " ") if err != nil { panic(err) } fmt.Printf("%s\n", outputRegular) fmt.Println("Finding a document with encrypted client") var resultSecure bson.M err = secureClient.Database(dbName).Collection(collName).FindOne(context.TODO(), bson.D{{"name", "Jon Doe"}}).Decode(&resultSecure) if err != nil { panic(err) } outputSecure, err := json.MarshalIndent(resultSecure, "", " ") if err != nil { panic(err) } fmt.Printf("%s\n", outputSecure)
System.out.println("Finding a document with regular (non-encrypted) client."); Document docRegular = mongoClientRegular.getDatabase(recordsDb).getCollection(recordsColl).find(eq("name", "Jon Doe")).first(); System.out.println(docRegular.toJson()); System.out.println("Finding a document with encrypted client"); Document docSecure = mongoClientSecure.getDatabase(recordsDb).getCollection(recordsColl).find(eq("name", "Jon Doe")).first(); System.out.println(docSecure.toJson());
console.log("Finding a document with regular (non-encrypted) client."); console.log( await regularClient.db(db).collection(coll).findOne({ name: /Jon/ }) ); console.log("Finding a document with encrypted client"); console.log( await secureClient.db(db).collection(coll).findOne({ name: /Jon/ }) );
print("Finding a document with regular (non-encrypted) client.") result = regularClient.medicalRecords.patients.find_one({"name": "Jon Doe"}) pprint.pprint(result) print("Finding a document with encrypted client") pprint.pprint(secureClient.medicalRecords.patients.find_one({"name": "Jon Doe"}))
์ด์ ์ฝ๋ ์ค๋ํซ์ ์ถ๋ ฅ์ ๋ค์๊ณผ ๊ฐ์์ผ ํฉ๋๋ค.
Finding a document with regular (non-encrypted) client. { _id: new ObjectId("629a452e0861b3130887103a"), name: 'Jon Doe', ssn: new Binary(Buffer.from("0217482732d8014cdd9ffdd6e2966e5e7910c20697e5f4fa95710aafc9153f0a3dc769c8a132a604b468732ff1f4d8349ded3244b59cbfb41444a210f28b21ea1b6c737508d9d30e8baa30c1d8070c4d5e26", "hex"), 6), bloodType: new Binary(Buffer.from("0217482732d8014cdd9ffdd6e2966e5e79022e238536dfd8caadb4d7751ac940e0f195addd7e5c67b61022d02faa90283ab69e02303c7e4001d1996128428bf037dea8bbf59fbb20c583cbcff2bf3e2519b4", "hex"), 6), 'key-id': 'demo-data-key', medicalRecords: new Binary(Buffer.from("0217482732d8014cdd9ffdd6e2966e5e790405163a3207cff175455106f57eef14e5610c49a99bcbd14a7db9c5284e45e3ee30c149354015f941440bf54725d6492fb3b8704bc7c411cff6c868e4e13c58233c3d5ed9593eca4e4d027d76d3705b6d1f3b3c9e2ceee195fd944b553eb27eee69e5e67c338f146f8445995664980bf0", "hex"), 6), insurance: { policyNumber: new Binary(Buffer.from("0217482732d8014cdd9ffdd6e2966e5e79108decd85c05be3fec099e015f9d26d9234605dc959cc1a19b63072f7ffda99db38c7b487de0572a03b2139ac3ee163bcc40c8508f366ce92a5dd36e38b3c742f7", "hex"), 6), provider: 'MaestCare' } } Finding a document with encrypted client { _id: new ObjectId("629a452e0861b3130887103a"), name: 'Jon Doe', ssn: 241014209, bloodType: 'AB+', 'key-id': 'demo-data-key', medicalRecords: [ { weight: 180, bloodPressure: '120/80' } ], insurance: { policyNumber: 123142, provider: 'MaestCare' } }
ํ
์ฐธ์กฐ: ์ฝ๋ ์์ฑ
์ํธํ๋จ ํ๋๊ฐ ์๋ ๋ฌธ์ ๋ฅผ ์ฐพ๊ธฐ ์ํ ์ ์ฒด ์ฝ๋๋ฅผ ๋ณด๋ ค๋ฉด Github ๋ฆฌํฌ์งํ ๋ฆฌ ๋ฅผ ์ฐธ์กฐํ์ธ์.
์ํธํ๋ ํ๋๊ฐ ์๋ ๋ฌธ์๋ฅผ ์ฐพ๊ธฐ ์ํ ์ ์ฒด ์ฝ๋๋ฅผ ๋ณด๋ ค๋ฉด Github ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ์ฐธ์กฐํ์ธ์.
์ํธํ๋ ํ๋๊ฐ ์๋ ๋ฌธ์๋ฅผ ์ฐพ๊ธฐ ์ํ ์ ์ฒด ์ฝ๋๋ฅผ ๋ณด๋ ค๋ฉด Github ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ์ฐธ์กฐํ์ธ์.
์ํธํ๋ ํ๋๊ฐ ์๋ ๋ฌธ์๋ฅผ ์ฐพ๊ธฐ ์ํ ์ ์ฒด ์ฝ๋๋ฅผ ๋ณด๋ ค๋ฉด Github ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ์ฐธ์กฐํ์ธ์.
์ํธํ๋ ํ๋๊ฐ ์๋ ๋ฌธ์๋ฅผ ์ฐพ๊ธฐ ์ํ ์ ์ฒด ์ฝ๋๋ฅผ ๋ณด๋ ค๋ฉด Github ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ์ฐธ์กฐํ์ธ์.
์์ธํ ์์๋ณด๊ธฐ
์๊ฒฉ KMS๋ฅผ ์ฌ์ฉํ์ฌ ํ๋ก๋์ ์ ์ฆ์ ์ฌ์ฉ ๊ฐ๋ฅํ CSFLE์ ๋ํ ํํ ๋ฆฌ์ผ์ ๋ณด๋ ค๋ฉด ํํ ๋ฆฌ์ผ์ ์ฐธ์กฐํ์ธ์ .
CSFLE ์๋ ๋ฐฉ์์ ์์๋ณด๋ ค๋ฉด ๊ธฐ๋ณธ ์ฌํญ์ ์ฐธ์กฐํ์ธ์.
์ด ๊ฐ์ด๋์ ์ธ๊ธ๋ ์ฃผ์ ์ ๋ํด ์์ธํ ์์๋ณด๋ ค๋ฉด ๋ค์ ๋งํฌ๋ฅผ ์ฐธ์กฐํ์ธ์: