private BsonBinaryData ExplicitEncrypt(
            ClientEncryption clientEncryption,
            EncryptOptions encryptOptions,
            BsonValue value,
            bool async)
        {
            BsonBinaryData encryptedValue;

            if (async)
            {
                encryptedValue = clientEncryption
                                 .EncryptAsync(
                    value,
                    encryptOptions,
                    CancellationToken.None)
                                 .GetAwaiter()
                                 .GetResult();
            }
            else
            {
                encryptedValue = clientEncryption.Encrypt(
                    value,
                    encryptOptions,
                    CancellationToken.None);
            }

            return(encryptedValue);
        }
Exemple #2
0
        public void InitializesIv(EncryptionAlgorithm algorithm)
        {
            // Use a 256-bit key which will be truncated based on the selected algorithm.
            byte[] k = new byte[] { 0xe2, 0x7e, 0xd0, 0xc8, 0x45, 0x12, 0xbb, 0xd5, 0x5b, 0x6a, 0xf4, 0x34, 0xd2, 0x37, 0xc1, 0x1f, 0xeb, 0xa3, 0x11, 0x87, 0x0f, 0x80, 0xf2, 0xc2, 0xe3, 0x36, 0x42, 0x60, 0xf3, 0x1c, 0x82, 0xc8 };

            JsonWebKey key = new JsonWebKey(new[] { KeyOperation.Encrypt, KeyOperation.Decrypt })
            {
                K = k,
            };

            AesCryptographyProvider provider = new AesCryptographyProvider(key, null);

            byte[] plaintext = Encoding.UTF8.GetBytes("plaintext");

            EncryptOptions encryptOptions = new EncryptOptions(algorithm, plaintext, null, null);
            EncryptResult  encrypted      = provider.Encrypt(encryptOptions, default);

            Assert.IsNotNull(encryptOptions.Iv);
            CollectionAssert.AreEqual(encryptOptions.Iv, encrypted.Iv);

            DecryptOptions decryptOptions = new DecryptOptions(algorithm, encrypted.Ciphertext, encrypted.Iv);
            DecryptResult  decrypted      = provider.Decrypt(decryptOptions, default);

            Assert.IsNotNull(decrypted);

            // AES-CBC will be zero-padded.
            StringAssert.StartsWith("plaintext", Encoding.UTF8.GetString(decrypted.Plaintext));
        }
Exemple #3
0
        public void RequiresPlaintext()
        {
            ArgumentNullException ex = Assert.Throws <ArgumentNullException>(() => EncryptOptions.Rsa15Options(null));

            Assert.AreEqual("plaintext", ex.ParamName);

            ex = Assert.Throws <ArgumentNullException>(() => EncryptOptions.RsaOaepOptions(null));
            Assert.AreEqual("plaintext", ex.ParamName);

            ex = Assert.Throws <ArgumentNullException>(() => EncryptOptions.RsaOaep256Options(null));
            Assert.AreEqual("plaintext", ex.ParamName);

            ex = Assert.Throws <ArgumentNullException>(() => EncryptOptions.A128GcmOptions(null));
            Assert.AreEqual("plaintext", ex.ParamName);

            Assert.DoesNotThrow(() => EncryptOptions.A128GcmOptions(Array.Empty <byte>(), null));

            ex = Assert.Throws <ArgumentNullException>(() => EncryptOptions.A192GcmOptions(null));
            Assert.AreEqual("plaintext", ex.ParamName);

            Assert.DoesNotThrow(() => EncryptOptions.A192GcmOptions(Array.Empty <byte>(), null));

            ex = Assert.Throws <ArgumentNullException>(() => EncryptOptions.A256GcmOptions(null));
            Assert.AreEqual("plaintext", ex.ParamName);

            Assert.DoesNotThrow(() => EncryptOptions.A256GcmOptions(Array.Empty <byte>(), null));

            ex = Assert.Throws <ArgumentNullException>(() => EncryptOptions.A128CbcOptions(null));
            Assert.AreEqual("plaintext", ex.ParamName);

            Assert.DoesNotThrow(() => EncryptOptions.A128CbcOptions(Array.Empty <byte>(), null));

            ex = Assert.Throws <ArgumentNullException>(() => EncryptOptions.A128CbcOptions(null));
            Assert.AreEqual("plaintext", ex.ParamName);

            Assert.DoesNotThrow(() => EncryptOptions.A192CbcOptions(Array.Empty <byte>(), null));

            ex = Assert.Throws <ArgumentNullException>(() => EncryptOptions.A128CbcOptions(null));
            Assert.AreEqual("plaintext", ex.ParamName);

            Assert.DoesNotThrow(() => EncryptOptions.A256CbcOptions(Array.Empty <byte>(), null));

            ex = Assert.Throws <ArgumentNullException>(() => EncryptOptions.A128CbcPadOptions(null));
            Assert.AreEqual("plaintext", ex.ParamName);

            Assert.DoesNotThrow(() => EncryptOptions.A128CbcPadOptions(Array.Empty <byte>(), null));

            ex = Assert.Throws <ArgumentNullException>(() => EncryptOptions.A128CbcPadOptions(null));
            Assert.AreEqual("plaintext", ex.ParamName);

            Assert.DoesNotThrow(() => EncryptOptions.A192CbcPadOptions(Array.Empty <byte>(), null));

            ex = Assert.Throws <ArgumentNullException>(() => EncryptOptions.A128CbcPadOptions(null));
            Assert.AreEqual("plaintext", ex.ParamName);

            Assert.DoesNotThrow(() => EncryptOptions.A256CbcPadOptions(Array.Empty <byte>(), null));
        }
        public void EncryptOptionsOnlyRequired()
        {
            byte[]         buffer  = new byte[] { 0, 1, 2, 3 };
            EncryptOptions options = CryptographyModelFactory.EncryptOptions(EncryptionAlgorithm.A128Cbc, buffer);

            Assert.AreEqual(EncryptionAlgorithm.A128Cbc, options.Algorithm);
            CollectionAssert.AreEqual(buffer, options.Plaintext);
            Assert.IsNull(options.Iv);
            Assert.IsNull(options.AdditionalAuthenticatedData);
        }
Exemple #5
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="opts"></param>
        /// <returns></returns>
        private static string Encrypt(EncryptOptions opts)
        {
            var encryptedString = StringCipher.Encrypt(opts.PlainString, opts.PassPhrase);

            var result = $"Encrypted cipher [{encryptedString}] generated by encrypting plain string [{opts.PlainString}] with pass phrase [{opts.PassPhrase}]";

            DisplayOutput(result);

            return(encryptedString);
        }
        public void ClientSideExplicitEncryptionAndDecryptionTour()
        {
            RequireServer.Check().Supports(Feature.ClientSideEncryption);

            var localMasterKey = Convert.FromBase64String(LocalMasterKey);

            var kmsProviders = new Dictionary <string, IReadOnlyDictionary <string, object> >();
            var localKey     = new Dictionary <string, object>
            {
                { "key", localMasterKey }
            };

            kmsProviders.Add("local", localKey);

            var keyVaultNamespace = CollectionNamespace.FromFullName("encryption.__keyVault");
            var keyVaultClient    = new MongoClient("mongodb://localhost");
            var keyVaultDatabase  = keyVaultClient.GetDatabase(keyVaultNamespace.DatabaseNamespace.DatabaseName);

            keyVaultDatabase.DropCollection(keyVaultNamespace.CollectionName);

            // Create the ClientEncryption instance
            var clientEncryptionSettings = new ClientEncryptionOptions(
                keyVaultClient,
                keyVaultNamespace,
                kmsProviders);

            using (var clientEncryption = new ClientEncryption(clientEncryptionSettings))
            {
                var dataKeyId = clientEncryption.CreateDataKey(
                    "local",
                    new DataKeyOptions(),
                    CancellationToken.None);

                var originalString = "123456789";
                _output.WriteLine($"Original string {originalString}.");

                // Explicitly encrypt a field
                var encryptOptions = new EncryptOptions(
                    EncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic.ToString(),
                    keyId: dataKeyId);
                var encryptedFieldValue = clientEncryption.Encrypt(
                    originalString,
                    encryptOptions,
                    CancellationToken.None);
                _output.WriteLine($"Encrypted value {encryptedFieldValue}.");

                // Explicitly decrypt the field
                var decryptedValue = clientEncryption.Decrypt(encryptedFieldValue, CancellationToken.None);
                _output.WriteLine($"Decrypted value {decryptedValue}.");
            }
        }
Exemple #7
0
        private static void EncryptWallet(EncryptOptions options)
        {
            string path = options.WalletPath;

            path = Path.IsPathRooted(path) || path.StartsWith("~/")
                ? path
                : Path.Join(Path.GetDirectoryName(Path.GetFullPath(path)), path);
            var content          = File.ReadAllBytes(path) ?? throw new Exception($"Cannot read file {path}");
            var key              = Encoding.UTF8.GetBytes(options.WalletPassword).KeccakBytes();
            var crypto           = CryptoProvider.GetCrypto();
            var encryptedContent = crypto.AesGcmEncrypt(key, content);

            using var stream = System.Console.OpenStandardOutput();
            stream.Write(encryptedContent, 0, encryptedContent.Length);
        }
Exemple #8
0
        public void Constructor_should_support_different_algorithm_representations(object algorithm, string expectedAlgorithmRepresentation)
        {
            var alternateKeyName = "test";

            EncryptOptions subject;

            if (algorithm is EncryptionAlgorithm enumedAlgorithm)
            {
                subject = new EncryptOptions(enumedAlgorithm, alternateKeyName: alternateKeyName);
            }
            else
            {
                subject = new EncryptOptions(algorithm.ToString(), alternateKeyName: alternateKeyName);
            }

            subject.Algorithm.Should().Be(expectedAlgorithmRepresentation);
            subject.AlternateKeyName.Should().Be("test");
            subject.KeyId.Should().NotHaveValue();
        }
        public static int RunEncrypt(EncryptOptions opts)
        {
            try
            {
                var collection = new X509Certificate2Collection();
                collection.Import(opts.CertificatePath, opts.Password, X509KeyStorageFlags.PersistKeySet);
                var cert = collection[0];
                var data = File.ReadAllText(opts.FilePath);

                var tdes = new TripleDESCryptoServiceProvider();
                tdes.GenerateKey();
                var    encryptor = tdes.CreateEncryptor();
                byte[] encData;
                using (var msEncrypt = new MemoryStream())
                {
                    using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (var swEncrypt = new StreamWriter(csEncrypt))
                        {
                            swEncrypt.Write(data);
                        }
                        encData = msEncrypt.ToArray();
                    }
                }
                using (var rsa = cert.GetRSAPublicKey())
                {
                    var encryptedKey = rsa.Encrypt(tdes.Key, RSAEncryptionPadding.OaepSHA1);
                    var encryptedIV  = rsa.Encrypt(tdes.IV, RSAEncryptionPadding.OaepSHA1);
                    Console.WriteLine($"Plaintext data: {data}");
                    Console.WriteLine($"Encrypted data: {Encoding.UTF8.GetString(encData)}");
                    var dataTotal = encData.Concat(encryptedKey).Concat(encryptedIV).ToArray();
                    Console.WriteLine($"Total data: {Encoding.UTF8.GetString(dataTotal)}");
                    File.WriteAllBytes(opts.Output, dataTotal);
                }
            }
            catch (Exception e)
            {
                return(-1);
            }
            return(0);
        }
        public void ExternalKeyVaultTest(
            [Values(false, true)] bool withExternalKeyVault,
            [Values(false, true)] bool async)
        {
            RequireServer.Check().Supports(Feature.ClientSideEncryption);

            var clientEncryptedSchema = new BsonDocument("db.coll", JsonFileReader.Instance.Documents["external.external-schema.json"]);

            using (var client = ConfigureClient())
                using (var clientEncrypted = ConfigureClientEncrypted(clientEncryptedSchema, withExternalKeyVault))
                    using (var clientEncryption = ConfigureClientEncryption(clientEncrypted.Wrapped as MongoClient))
                    {
                        var datakeys    = GetCollection(client, __keyVaultCollectionNamespace);
                        var externalKey = JsonFileReader.Instance.Documents["external.external-key.json"];
                        Insert(datakeys, async, externalKey);

                        var coll      = GetCollection(clientEncrypted, __collCollectionNamespace);
                        var exception = Record.Exception(() => Insert(coll, async, new BsonDocument("encrypted", "test")));
                        if (withExternalKeyVault)
                        {
                            exception.InnerException.Should().BeOfType <MongoAuthenticationException>();
                        }
                        else
                        {
                            exception.Should().BeNull();
                        }

                        var encryptionOptions = new EncryptOptions(
                            algorithm: EncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic.ToString(),
                            keyId: GuidConverter.FromBytes(Convert.FromBase64String("LOCALAAAAAAAAAAAAAAAAA=="), GuidRepresentation.Standard));
                        exception = Record.Exception(() => ExplicitEncrypt(clientEncryption, encryptionOptions, "test", async));
                        if (withExternalKeyVault)
                        {
                            exception.InnerException.Should().BeOfType <MongoAuthenticationException>();
                        }
                        else
                        {
                            exception.Should().BeNull();
                        }
                    }
        }
Exemple #11
0
        public void EncryptAfterValidDate()
        {
            using Aes aes = Aes.Create();

            KeyVaultKey key = new KeyVaultKey("test")
            {
                Key        = new JsonWebKey(aes),
                Properties =
                {
                    ExpiresOn = DateTimeOffset.Now.AddDays(-1),
                },
            };

            AesCryptographyProvider provider = new AesCryptographyProvider(key.Key, key.Properties);

            byte[]         iv      = { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30, 0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 };
            EncryptOptions options = EncryptOptions.A128CbcOptions(Encoding.UTF8.GetBytes("Single block msg"), iv);

            InvalidOperationException ex = Assert.Throws <InvalidOperationException>(() => provider.Encrypt(options, default));

            Assert.AreEqual($"The key \"test\" is not valid after {key.Properties.ExpiresOn.Value:r}.", ex.Message);
        }
Exemple #12
0
        public void InitializesIv([EnumValues] EncryptionAlgorithm algorithm)
        {
            EncryptOptions options = new EncryptOptions(algorithm, Array.Empty <byte>());

            options.Initialize();

            if (algorithm.GetAesCbcEncryptionAlgorithm() != null)
            {
                byte[] iv = options.Iv;

                Assert.IsNotNull(options.Iv);
                CollectionAssert.IsNotEmpty(options.Iv);

                // Calling it again should not overwrite.
                options.Initialize();

                Assert.AreSame(iv, options.Iv);
            }
            else
            {
                Assert.IsNull(options.Iv);
            }
        }
        public void EncryptAfterValidDate()
        {
            using RSA rsa = RSA.Create();

            KeyVaultKey key = new KeyVaultKey("test")
            {
                Key        = new JsonWebKey(rsa),
                Properties =
                {
                    ExpiresOn = DateTimeOffset.Now.AddDays(-1),
                },
            };

            RsaCryptographyProvider provider = new RsaCryptographyProvider(key.Key, key.Properties);

            byte[] plaintext             = Encoding.UTF8.GetBytes("test");
            InvalidOperationException ex = Assert.Throws <InvalidOperationException>(() => provider.Encrypt(EncryptOptions.RsaOaep256Options(plaintext), default));

            Assert.AreEqual($"The key \"test\" is not valid after {key.Properties.ExpiresOn.Value:r}.", ex.Message);
        }
        public void CustomEndpointTest([Values(false, true)] bool async)
        {
            RequireServer.Check().Supports(Feature.ClientSideEncryption);

            using (var client = ConfigureClient())
                using (var clientEncryption = ConfigureClientEncryption(client.Wrapped as MongoClient))
                {
                    var testCaseMasterKey = new BsonDocument
                    {
                        { "region", "us-east-1" },
                        { "key", "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0" }
                    };
                    TestCase(testCaseMasterKey);

                    testCaseMasterKey = new BsonDocument
                    {
                        { "region", "us-east-1" },
                        { "key", "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0" },
                        { "endpoint", "kms.us-east-1.amazonaws.com" }
                    };
                    TestCase(testCaseMasterKey);

                    testCaseMasterKey = new BsonDocument
                    {
                        { "region", "us-east-1" },
                        { "key", "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0" },
                        { "endpoint", "kms.us-east-1.amazonaws.com:443" }
                    };
                    TestCase(testCaseMasterKey);

                    testCaseMasterKey = new BsonDocument
                    {
                        { "region", "us-east-1" },
                        { "key", "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0" },
                        { "endpoint", "kms.us-east-1.amazonaws.com:12345" }
                    };
                    var exception = Record.Exception(() => TestCase(testCaseMasterKey));
                    exception.InnerException.Should().BeAssignableTo <SocketException>();

                    testCaseMasterKey = new BsonDocument
                    {
                        { "region", "us-east-1" },
                        { "key", "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0" },
                        { "endpoint", "kms.us-east-2.amazonaws.com" }
                    };
                    exception = Record.Exception(() => TestCase(testCaseMasterKey));
                    exception.Should().NotBeNull();
                    exception.Message.Should().Contain("us-east-1");

                    testCaseMasterKey = new BsonDocument
                    {
                        { "region", "us-east-1" },
                        { "key", "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0" },
                        { "endpoint", "example.com" }
                    };
                    exception = Record.Exception(() => TestCase(testCaseMasterKey));
                    exception.Should().NotBeNull();
                    exception.Message.Should().Contain("parse error");

                    // additional not spec tests
                    testCaseMasterKey = new BsonDocument
                    {
                        { "region", "us-east-1" },
                        { "key", "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0" },
                        { "endpoint", "$test$" }
                    };
                    exception = Record.Exception(() => TestCase(testCaseMasterKey));
                    exception.Should().NotBeNull();
                    exception.InnerException.Should().BeAssignableTo <SocketException>();

                    void TestCase(BsonDocument masterKey)
                    {
                        var dataKeyOptions = new DataKeyOptions(masterKey: masterKey);
                        var dataKey        = CreateDataKey(clientEncryption, "aws", dataKeyOptions, async);

                        var encryptOptions = new EncryptOptions(
                            algorithm: EncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic.ToString(),
                            keyId: dataKey);
                        var value     = "test";
                        var encrypted = ExplicitEncrypt(clientEncryption, encryptOptions, value, async);
                        var decrypted = ExplicitDecrypt(clientEncryption, encrypted, async);

                        decrypted.Should().Be(BsonValue.Create(value));
                    }
                }
        }
        public void CreateDataKeyAndDoubleEncryptionTest(
            [Values("local", "aws")] string kmsProvider,
            [Values(false, true)] bool async)
        {
            RequireServer.Check().Supports(Feature.ClientSideEncryption);

            using (var client = ConfigureClient())
                using (var clientEncrypted = ConfigureClientEncrypted(BsonDocument.Parse(SchemaMap)))
                    using (var clientEncryption = ConfigureClientEncryption(clientEncrypted.Wrapped as MongoClient))
                    {
                        var dataKeyOptions = CreateDataKeyOptions(kmsProvider);
                        var dataKey        = CreateDataKey(clientEncryption, kmsProvider, dataKeyOptions, async);

                        var keyVaultCollection = GetCollection(client, __keyVaultCollectionNamespace);
                        var keyVaultDocument   =
                            Find(
                                keyVaultCollection,
                                new BsonDocument("_id", new BsonBinaryData(dataKey, GuidRepresentation.Standard)),
                                async)
                            .Single();
                        keyVaultDocument["masterKey"]["provider"].Should().Be(BsonValue.Create(kmsProvider));

                        var encryptOptions = new EncryptOptions(
                            EncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic.ToString(),
                            keyId: dataKey);

                        var encryptedValue = ExplicitEncrypt(
                            clientEncryption,
                            encryptOptions,
                            $"hello {kmsProvider}",
                            async);
                        encryptedValue.SubType.Should().Be(BsonBinarySubType.Encrypted);

                        var coll = GetCollection(clientEncrypted, __collCollectionNamespace);
                        Insert(
                            coll,
                            async,
                            new BsonDocument
                        {
                            { "_id", kmsProvider },
                            { "value", encryptedValue }
                        });

                        var findResult = Find(coll, new BsonDocument("_id", kmsProvider), async).Single();
                        findResult["value"].ToString().Should().Be($"hello {kmsProvider}");

                        encryptOptions = new EncryptOptions(
                            EncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic.ToString(),
                            alternateKeyName: $"{kmsProvider}_altname");
                        var encryptedValueWithAlternateKeyName = ExplicitEncrypt(
                            clientEncryption,
                            encryptOptions,
                            $"hello {kmsProvider}",
                            async);
                        encryptedValueWithAlternateKeyName.SubType.Should().Be(BsonBinarySubType.Encrypted);
                        encryptedValueWithAlternateKeyName.Should().Be(encryptedValue);

                        if (kmsProvider == "local") // the test description expects this assert only once for a local kms provider
                        {
                            coll = GetCollection(clientEncrypted, __collCollectionNamespace);
                            var exception = Record.Exception(() => Insert(coll, async, new BsonDocument("encrypted_placeholder", encryptedValue)));
                            exception.Should().BeOfType <MongoEncryptionException>();
                        }
                    }
        }
        public void ClientSideExplicitEncryptionAndAutoDecryptionTour()
        {
            RequireServer.Check().Supports(Feature.ClientSideEncryption);

            var localMasterKey = Convert.FromBase64String(LocalMasterKey);

            var kmsProviders = new Dictionary <string, IReadOnlyDictionary <string, object> >();
            var localKey     = new Dictionary <string, object>
            {
                { "key", localMasterKey }
            };

            kmsProviders.Add("local", localKey);

            var keyVaultNamespace     = CollectionNamespace.FromFullName("encryption.__keyVault");
            var collectionNamespace   = CollectionNamespace.FromFullName("test.coll");
            var autoEncryptionOptions = new AutoEncryptionOptions(
                keyVaultNamespace,
                kmsProviders,
                bypassAutoEncryption: true);
            var clientSettings = MongoClientSettings.FromConnectionString("mongodb://localhost");

            clientSettings.AutoEncryptionOptions = autoEncryptionOptions;
            var mongoClient = new MongoClient(clientSettings);
            var database    = mongoClient.GetDatabase(collectionNamespace.DatabaseNamespace.DatabaseName);

            database.DropCollection(collectionNamespace.CollectionName);
            var collection = database.GetCollection <BsonDocument>(collectionNamespace.CollectionName);

            var keyVaultClient   = new MongoClient("mongodb://localhost");
            var keyVaultDatabase = keyVaultClient.GetDatabase(keyVaultNamespace.DatabaseNamespace.DatabaseName);

            keyVaultDatabase.DropCollection(keyVaultNamespace.CollectionName);

            // Create the ClientEncryption instance
            var clientEncryptionSettings = new ClientEncryptionOptions(
                keyVaultClient,
                keyVaultNamespace,
                kmsProviders);

            using (var clientEncryption = new ClientEncryption(clientEncryptionSettings))
            {
                var dataKeyId = clientEncryption.CreateDataKey(
                    "local",
                    new DataKeyOptions(),
                    CancellationToken.None);

                var originalString = "123456789";
                _output.WriteLine($"Original string {originalString}.");

                // Explicitly encrypt a field
                var encryptOptions = new EncryptOptions(
                    EncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic.ToString(),
                    keyId: dataKeyId);
                var encryptedFieldValue = clientEncryption.Encrypt(
                    originalString,
                    encryptOptions,
                    CancellationToken.None);
                _output.WriteLine($"Encrypted value {encryptedFieldValue}.");

                collection.InsertOne(new BsonDocument("encryptedField", encryptedFieldValue));

                // Automatically decrypts the encrypted field.
                var decryptedValue = collection.Find(FilterDefinition <BsonDocument> .Empty).First();
                _output.WriteLine($"Decrypted document {decryptedValue.ToJson()}.");
            }
        }
Exemple #17
0
 static void AssertValues(EncryptOptions subject, string algorithm, Guid?keyId, string alternateKeyName)
 {
     subject.Algorithm.Should().Be(algorithm);
     subject.KeyId.Should().Be(keyId);
     subject.AlternateKeyName.Should().Be(alternateKeyName);
 }
 public Task <EncryptResult> EncryptAsync(EncryptOptions options, CancellationToken cancellationToken = default) => throw new CryptographicException(CRYPT_E_NO_PROVIDER);
Exemple #19
0
        public void EncryptDecryptRoundtrips(EncryptionAlgorithm algorithm)
        {
            // Use a 256-bit key which will be truncated based on the selected algorithm.
            byte[] k   = new byte[] { 0xe2, 0x7e, 0xd0, 0xc8, 0x45, 0x12, 0xbb, 0xd5, 0x5b, 0x6a, 0xf4, 0x34, 0xd2, 0x37, 0xc1, 0x1f, 0xeb, 0xa3, 0x11, 0x87, 0x0f, 0x80, 0xf2, 0xc2, 0xe3, 0x36, 0x42, 0x60, 0xf3, 0x1c, 0x82, 0xc8 };
            byte[] iv  = new byte[] { 0x89, 0xb8, 0xad, 0xbf, 0xb0, 0x73, 0x45, 0xe3, 0x59, 0x89, 0x32, 0xa0, 0x9c, 0x51, 0x74, 0x41 };
            byte[] aad = Encoding.UTF8.GetBytes("test");

            JsonWebKey key = new JsonWebKey(new[] { KeyOperation.Encrypt, KeyOperation.Decrypt })
            {
                K = k,
            };

            AesCryptographyProvider provider = new AesCryptographyProvider(key, null);

            byte[] plaintext = Encoding.UTF8.GetBytes("plaintext");

            if (algorithm.IsAesGcm())
            {
                iv = iv.Take(AesGcmProxy.NonceByteSize);
            }

            EncryptOptions encryptOptions = new EncryptOptions(algorithm, plaintext, iv, aad);
            EncryptResult  encrypted      = provider.Encrypt(encryptOptions, default);

#if !NETCOREAPP3_1
            if (algorithm.IsAesGcm())
            {
                Assert.IsNull(encrypted);
                Assert.Ignore($"AES-GCM is not supported on {RuntimeInformation.FrameworkDescription} on {RuntimeInformation.OSDescription}");
            }
#endif
            Assert.IsNotNull(encrypted);

            switch (algorithm.ToString())
            {
            // TODO: Move to new test to make sure CryptoClient and LocalCryptoClient initialize a null ICM for AES-CBC(PAD).
            case EncryptionAlgorithm.A128CbcValue:
                CollectionAssert.AreEqual(
                    new byte[] { 0x63, 0x23, 0x21, 0xaf, 0x94, 0xf9, 0xe1, 0x21, 0xc2, 0xbd, 0xb1, 0x1b, 0x04, 0x89, 0x8c, 0x3a },
                    encrypted.Ciphertext);
                CollectionAssert.AreEqual(iv, encrypted.Iv);
                Assert.IsNull(encrypted.AuthenticationTag);
                Assert.IsNull(encrypted.AdditionalAuthenticatedData);
                break;

            case EncryptionAlgorithm.A192CbcValue:
                CollectionAssert.AreEqual(
                    new byte[] { 0x95, 0x9d, 0x75, 0x91, 0x09, 0x8b, 0x70, 0x0b, 0x9c, 0xfe, 0xaf, 0xcd, 0x60, 0x1f, 0xaa, 0x79 },
                    encrypted.Ciphertext);
                CollectionAssert.AreEqual(iv, encrypted.Iv);
                Assert.IsNull(encrypted.AuthenticationTag);
                Assert.IsNull(encrypted.AdditionalAuthenticatedData);
                break;

            case EncryptionAlgorithm.A256CbcValue:
                CollectionAssert.AreEqual(
                    new byte[] { 0xf4, 0xe8, 0x5a, 0xa4, 0xa8, 0xb3, 0xff, 0xc3, 0x85, 0x89, 0x17, 0x9a, 0x70, 0x09, 0x96, 0x7f },
                    encrypted.Ciphertext);
                CollectionAssert.AreEqual(iv, encrypted.Iv);
                Assert.IsNull(encrypted.AuthenticationTag);
                Assert.IsNull(encrypted.AdditionalAuthenticatedData);
                break;

            case EncryptionAlgorithm.A128CbcPadValue:
                CollectionAssert.AreEqual(
                    new byte[] { 0xec, 0xb2, 0x63, 0x4c, 0xe0, 0x04, 0xe0, 0x31, 0x2d, 0x9a, 0x77, 0xb2, 0x11, 0xe5, 0x28, 0x7f },
                    encrypted.Ciphertext);
                CollectionAssert.AreEqual(iv, encrypted.Iv);
                Assert.IsNull(encrypted.AuthenticationTag);
                Assert.IsNull(encrypted.AdditionalAuthenticatedData);
                break;

            case EncryptionAlgorithm.A192CbcPadValue:
                CollectionAssert.AreEqual(
                    new byte[] { 0xc3, 0x4e, 0x1b, 0xe7, 0x6e, 0xa1, 0xf1, 0xc3, 0x24, 0xae, 0x05, 0x1b, 0x0e, 0x32, 0xac, 0xb4 },
                    encrypted.Ciphertext);
                CollectionAssert.AreEqual(iv, encrypted.Iv);
                Assert.IsNull(encrypted.AuthenticationTag);
                Assert.IsNull(encrypted.AdditionalAuthenticatedData);
                break;

            case EncryptionAlgorithm.A256CbcPadValue:
                CollectionAssert.AreEqual(
                    new byte[] { 0x4e, 0xbd, 0x78, 0xda, 0x90, 0x73, 0xc8, 0x97, 0x67, 0x2b, 0xa1, 0x0a, 0x41, 0x67, 0xf8, 0x99 },
                    encrypted.Ciphertext);
                CollectionAssert.AreEqual(iv, encrypted.Iv);
                Assert.IsNull(encrypted.AuthenticationTag);
                Assert.IsNull(encrypted.AdditionalAuthenticatedData);
                break;

            case EncryptionAlgorithm.A128GcmValue:
            case EncryptionAlgorithm.A192GcmValue:
            case EncryptionAlgorithm.A256GcmValue:
                Assert.IsNotNull(encrypted.Ciphertext);
                Assert.IsNotNull(encrypted.Iv);
                Assert.IsNotNull(encrypted.AuthenticationTag);
                CollectionAssert.AreEqual(aad, encrypted.AdditionalAuthenticatedData);
                break;
            }

            DecryptOptions decryptOptions = algorithm.IsAesGcm() ?
                                            new DecryptOptions(algorithm, encrypted.Ciphertext, encrypted.Iv, encrypted.AuthenticationTag, encrypted.AdditionalAuthenticatedData) :
                                            new DecryptOptions(algorithm, encrypted.Ciphertext, encrypted.Iv);

            DecryptResult decrypted = provider.Decrypt(decryptOptions, default);
            Assert.IsNotNull(decrypted);

            // AES-CBC will be zero-padded.
            StringAssert.StartsWith("plaintext", Encoding.UTF8.GetString(decrypted.Plaintext));
        }