CSFLE explicit encryption golang Hello World example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
CSFLE explicit encryption golang Hello World example | |
brew install mongodb/brew/libmongocrypt | |
go get go.mongodb.org/mongo-driver/mongo | |
go get go.mongodb.org/mongo-driver/bson | |
go get go.mongodb.org/mongo-driver/mongo/options | |
go get go.mongodb.org/mongo-driver/mongo/readpref | |
go get go.mongodb.org/mongo-driver/bson/primitive | |
go clean --cache | |
go build -tags cse csfle_golang_explicit.go | |
OR | |
go run -tags cse csfle_golang_explicit.go | |
*/ | |
package main | |
import ( | |
"context" | |
"fmt" | |
"go.mongodb.org/mongo-driver/bson" | |
"go.mongodb.org/mongo-driver/bson/primitive" | |
"go.mongodb.org/mongo-driver/mongo" | |
"go.mongodb.org/mongo-driver/mongo/options" | |
) | |
func main() { | |
var uri = "mongodb://localhost:27017" | |
// localMasterKey must be the same master key that was used to create the | |
// encryption key. Obviously, don't use this example key in production. | |
var localMasterKey = "E7h/7bm+gvHPosEhZLB96Nms4Lrn2zV90vKpVJIo7UMn9112iex7dPeHHKVt088kNr3Zv+ZpBGZTYFI7yVm49eIysA7PwXdZ/QpNcwuw9Ut5rYiXXf4UA8G9fNNkYonQ" | |
kmsProviders := map[string]map[string]interface{}{ | |
"local": { | |
"key": localMasterKey, | |
}, | |
} | |
// The MongoDB namespace (db.collection) used to store the encryption data | |
// keys. | |
keyVaultDBName, keyVaultCollName := "encryption", "__keyVault" | |
keyVaultNamespace := keyVaultDBName + "." + keyVaultCollName | |
// The Client used to read/write application data. | |
client, err := mongo.Connect( | |
context.TODO(), | |
options.Client().ApplyURI(uri)) | |
if err != nil { | |
panic(err) | |
} | |
defer func() { _ = client.Disconnect(context.TODO()) }() | |
// Get a handle to the application collection and clear existing data. | |
coll := client.Database("test").Collection("coll") | |
_ = coll.Drop(context.TODO()) | |
// Set up the key vault for this example. | |
keyVaultColl := client.Database(keyVaultDBName).Collection(keyVaultCollName) | |
_ = keyVaultColl.Drop(context.TODO()) | |
// Ensure that two data keys cannot share the same keyAltName. | |
keyVaultIndex := mongo.IndexModel{ | |
Keys: bson.D{{Key: "keyAltNames", Value: 1}}, | |
Options: options.Index(). | |
SetUnique(true). | |
SetPartialFilterExpression(bson.D{ | |
{Key: "keyAltNames", Value: bson.D{ | |
{Key: "$exists", Value: true}, | |
}}, | |
}), | |
} | |
_, err = keyVaultColl.Indexes().CreateOne(context.TODO(), keyVaultIndex) | |
if err != nil { | |
panic(err) | |
} | |
// Create the ClientEncryption object to use for explicit | |
// encryption/decryption. The Client passed to NewClientEncryption is used | |
// to read/write to the key vault. This can be the same Client used by the | |
// main application. | |
clientEncryptionOpts := options.ClientEncryption(). | |
SetKmsProviders(kmsProviders). | |
SetKeyVaultNamespace(keyVaultNamespace) | |
clientEncryption, err := mongo.NewClientEncryption(client, clientEncryptionOpts) | |
if err != nil { | |
panic(err) | |
} | |
defer func() { _ = clientEncryption.Close(context.TODO()) }() | |
// Create a new data key for the encrypted field. | |
dataKeyOpts := options.DataKey(). | |
SetKeyAltNames([]string{"go_encryption_example"}) | |
dataKeyID, err := clientEncryption.CreateDataKey( | |
context.TODO(), | |
"local", | |
dataKeyOpts) | |
if err != nil { | |
panic(err) | |
} | |
// Create a bson.RawValue to encrypt and encrypt it using the key that was | |
// just created. | |
rawValueType, rawValueData, err := bson.MarshalValue("Hello, 世界!") | |
if err != nil { | |
panic(err) | |
} | |
rawValue := bson.RawValue{Type: rawValueType, Value: rawValueData} | |
encryptionOpts := options.Encrypt(). | |
SetAlgorithm("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"). | |
SetKeyID(dataKeyID) | |
encryptedField, err := clientEncryption.Encrypt( | |
context.TODO(), | |
rawValue, | |
encryptionOpts) | |
if err != nil { | |
panic(err) | |
} | |
// Insert a document with the encrypted field and then find it. | |
_, err = coll.InsertOne( | |
context.TODO(), | |
bson.D{{Key: "encryptedField", Value: encryptedField}}) | |
if err != nil { | |
panic(err) | |
} | |
var foundDoc bson.M | |
err = coll.FindOne(context.TODO(), bson.D{}).Decode(&foundDoc) | |
if err != nil { | |
panic(err) | |
} | |
// Decrypt the encrypted field in the found document. | |
decrypted, err := clientEncryption.Decrypt( | |
context.TODO(), | |
foundDoc["encryptedField"].(primitive.Binary)) | |
if err != nil { | |
panic(err) | |
} | |
fmt.Printf("Decrypted value: %s\n", decrypted) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ ./csfle_golang_explicit | |
Decrypted value: "Hello, 世界!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment