Example #1
0
        /// <summary>
        /// Serializes a value.
        /// </summary>
        /// <param name="context">The serialization context.</param>
        /// <param name="args">The serialization args.</param>
        /// <param name="value">The object.</param>
        protected override void SerializeValue(BsonSerializationContext context, BsonSerializationArgs args, BsonBinaryData value)
        {
            var bsonWriter = context.Writer;

            var subType = value.SubType;

            if (subType == BsonBinarySubType.UuidStandard || subType == BsonBinarySubType.UuidLegacy)
            {
                var writerGuidRepresentation = bsonWriter.Settings.GuidRepresentation;
                if (writerGuidRepresentation != GuidRepresentation.Unspecified)
                {
                    var bytes = value.Bytes;
                    var guidRepresentation = value.GuidRepresentation;

                    if (guidRepresentation == GuidRepresentation.Unspecified)
                    {
                        var message = string.Format(
                            "Cannot serialize BsonBinaryData with GuidRepresentation Unspecified to destination with GuidRepresentation {0}.",
                            writerGuidRepresentation);
                        throw new BsonSerializationException(message);
                    }
                    if (guidRepresentation != writerGuidRepresentation)
                    {
                        var guid = GuidConverter.FromBytes(bytes, guidRepresentation);
                        bytes              = GuidConverter.ToBytes(guid, writerGuidRepresentation);
                        subType            = (writerGuidRepresentation == GuidRepresentation.Standard) ? BsonBinarySubType.UuidStandard : BsonBinarySubType.UuidLegacy;
                        guidRepresentation = writerGuidRepresentation;
                        value              = new BsonBinaryData(bytes, subType, guidRepresentation);
                    }
                }
            }

            bsonWriter.WriteBinaryData(value);
        }
        public void Deserialize_binary_data_should_return_expected_result_when_guid_representation_is_specified(
            [ClassValues(typeof(GuidModeValues))]
            GuidMode mode,
            [Values(-1, GuidRepresentation.Unspecified)]
            GuidRepresentation readerGuidRepresentation,
            [Values(GuidRepresentation.CSharpLegacy, GuidRepresentation.JavaLegacy, GuidRepresentation.PythonLegacy, GuidRepresentation.Standard)]
            GuidRepresentation guidRepresentation)
        {
#pragma warning disable 618
            mode.Set();
            var discriminatorConvention = BsonSerializer.LookupDiscriminatorConvention(typeof(object));
            var subject = new ObjectSerializer(discriminatorConvention, guidRepresentation);
            var bytes   = new byte[] { 29, 0, 0, 0, 5, 120, 0, 16, 0, 0, 0, 3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0 };
            var subType = GuidConverter.GetSubType(guidRepresentation);
            bytes[11] = (byte)subType;
            var readerSettings = new BsonBinaryReaderSettings();
            if (BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2)
            {
                readerSettings.GuidRepresentation = readerGuidRepresentation == (GuidRepresentation)(-1) ? guidRepresentation : GuidRepresentation.Unspecified;
            }
            using (var memoryStream = new MemoryStream(bytes))
                using (var reader = new BsonBinaryReader(memoryStream, readerSettings))
                {
                    var context = BsonDeserializationContext.CreateRoot(reader);

                    reader.ReadStartDocument();
                    reader.ReadName("x");
                    var result = subject.Deserialize <object>(context);

                    var guidBytes      = bytes.Skip(12).Take(16).ToArray();
                    var expectedResult = GuidConverter.FromBytes(guidBytes, guidRepresentation);
                    result.Should().Be(expectedResult);
                }
#pragma warning restore 618
        }
        public void Deserializer_should_return_expected_result_when_representation_is_binary(
            GuidRepresentationMode defaultGuidRepresentationMode,
            GuidRepresentation defaultGuidRepresentation,
            GuidRepresentation serializerGuidRepresentation,
            GuidRepresentation readerGuidRepresentation,
            GuidRepresentation expectedGuidRepresentation)
        {
            GuidMode.Set(defaultGuidRepresentationMode, defaultGuidRepresentation);

            var subject         = new GuidSerializer(serializerGuidRepresentation);
            var documentBytes   = new byte[] { 29, 0, 0, 0, 5, 120, 0, 16, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0 };
            var documentSubType = GuidConverter.GetSubType(expectedGuidRepresentation);

            documentBytes[11] = (byte)documentSubType;
            var readerSettings = new BsonBinaryReaderSettings();

            if (defaultGuidRepresentationMode == GuidRepresentationMode.V2)
            {
#pragma warning disable 618
                readerSettings.GuidRepresentation = readerGuidRepresentation;
#pragma warning restore 618
            }
            var reader = new BsonBinaryReader(new MemoryStream(documentBytes), readerSettings);
            reader.ReadStartDocument();
            reader.ReadName("x");
            var context = BsonDeserializationContext.CreateRoot(reader);
            var args    = new BsonDeserializationArgs();

            var result = subject.Deserialize(context, args);

            var guidBytes    = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
            var expectedGuid = GuidConverter.FromBytes(guidBytes, expectedGuidRepresentation);
            result.Should().Be(expectedGuid);
        }
        // public methods
        /// <summary>
        /// Deserializes a value.
        /// </summary>
        /// <param name="context">The deserialization context.</param>
        /// <param name="args">The deserialization args.</param>
        /// <returns>A deserialized value.</returns>
        public override Guid Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
        {
            var    bsonReader = context.Reader;
            string message;

            var bsonType = bsonReader.GetCurrentBsonType();

            switch (bsonType)
            {
            case BsonType.Binary:
#pragma warning disable 618
                BsonBinaryData binaryData;
                if (BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2 && _guidRepresentation == GuidRepresentation.Unspecified)
                {
                    binaryData = bsonReader.ReadBinaryData();
                }
                else
                {
                    binaryData = bsonReader.ReadBinaryDataWithGuidRepresentationUnspecified();
                }
                var bytes              = binaryData.Bytes;
                var subType            = binaryData.SubType;
                var guidRepresentation = _guidRepresentation;
                if (BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2 && guidRepresentation == GuidRepresentation.Unspecified)
                {
                    guidRepresentation = binaryData.GuidRepresentation;
                }
                if (bytes.Length != 16)
                {
                    message = string.Format("Expected length to be 16, not {0}.", bytes.Length);
                    throw new FormatException(message);
                }
                if (subType != BsonBinarySubType.UuidStandard && subType != BsonBinarySubType.UuidLegacy)
                {
                    message = string.Format("Expected binary sub type to be UuidStandard or UuidLegacy, not {0}.", subType);
                    throw new FormatException(message);
                }
                if (guidRepresentation == GuidRepresentation.Unspecified)
                {
                    throw new BsonSerializationException("GuidSerializer cannot deserialize a Guid when GuidRepresentation is Unspecified.");
                }
                if (BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V3 || _guidRepresentation != GuidRepresentation.Unspecified)
                {
                    var expectedSubType = GuidConverter.GetSubType(guidRepresentation);
                    if (subType != expectedSubType)
                    {
                        throw new FormatException($"GuidSerializer cannot deserialize a Guid when GuidRepresentation is {guidRepresentation} and binary sub type is {subType}.");
                    }
                }
                return(GuidConverter.FromBytes(bytes, guidRepresentation));

#pragma warning restore 618

            case BsonType.String:
                return(new Guid(bsonReader.ReadString()));

            default:
                throw CreateCannotDeserializeFromBsonTypeException(bsonType);
            }
        }
        private string GuidToString(BsonBinarySubType subType, byte[] bytes, GuidRepresentation guidRepresentation)
        {
            if (bytes.Length != 16)
            {
                var message = string.Format("Length of binary subtype {0} must be 16, not {1}.", subType, bytes.Length);
                throw new ArgumentException(message);
            }
            if (subType == BsonBinarySubType.UuidLegacy)
            {
                if (guidRepresentation == GuidRepresentation.Standard)
                {
                    throw new ArgumentException("GuidRepresentation for binary subtype UuidLegacy must not be Standard.");
                }
            }
            if (subType == BsonBinarySubType.UuidStandard)
            {
                if (guidRepresentation == GuidRepresentation.Unspecified)
                {
                    guidRepresentation = GuidRepresentation.Standard;
                }
                if (guidRepresentation != GuidRepresentation.Standard)
                {
                    var message = string.Format("GuidRepresentation for binary subtype UuidStandard must be Standard, not {0}.", guidRepresentation);
                    throw new ArgumentException(message);
                }
            }

            if (guidRepresentation == GuidRepresentation.Unspecified)
            {
                var s     = BsonUtils.ToHexString(bytes);
                var parts = new string[]
                {
                    s.Substring(0, 8),
                    s.Substring(8, 4),
                    s.Substring(12, 4),
                    s.Substring(16, 4),
                    s.Substring(20, 12)
                };
                return(string.Format("HexData({0}, \"{1}\")", (int)subType, string.Join("-", parts)));
            }
            else
            {
                string uuidConstructorName;
                switch (guidRepresentation)
                {
                case GuidRepresentation.CSharpLegacy: uuidConstructorName = "CSUUID"; break;

                case GuidRepresentation.JavaLegacy: uuidConstructorName = "JUUID"; break;

                case GuidRepresentation.PythonLegacy: uuidConstructorName = "PYUUID"; break;

                case GuidRepresentation.Standard: uuidConstructorName = "UUID"; break;

                default: throw new BsonInternalException("Unexpected GuidRepresentation");
                }
                var guid = GuidConverter.FromBytes(bytes, guidRepresentation);
                return(string.Format("{0}(\"{1}\")", uuidConstructorName, guid.ToString()));
            }
        }
        private Guid UnwrapKeyId(RawBsonDocument wrappedKeyDocument)
        {
            var keyId = wrappedKeyDocument["_id"].AsBsonBinaryData;

            if (keyId.SubType != BsonBinarySubType.UuidStandard)
            {
                throw new InvalidOperationException($"KeyId sub type must be UuidStandard, not: {keyId.SubType}.");
            }
            return(GuidConverter.FromBytes(keyId.Bytes, GuidRepresentation.Standard));
        }
        /// <summary>
        /// Deserializes an object from a BsonReader.
        /// </summary>
        /// <param name="bsonReader">The BsonReader.</param>
        /// <param name="nominalType">The nominal type of the object.</param>
        /// <param name="options">The serialization options.</param>
        /// <returns>An object.</returns>
        public override object Deserialize(
            BsonReader bsonReader,
            Type nominalType,
            IBsonSerializationOptions options
            )
        {
            var    bsonType = bsonReader.CurrentBsonType;
            string message;

            switch (bsonType)
            {
            case BsonType.Binary:
                byte[]            bytes;
                BsonBinarySubType subType;
                bsonReader.ReadBinaryData(out bytes, out subType);
                if (bytes.Length != 16)
                {
                    message = string.Format("Expected length to be 16, not {0}.", bytes.Length);
                    throw new FileFormatException(message);
                }
                if (subType != BsonBinarySubType.UuidStandard && subType != BsonBinarySubType.UuidLegacy)
                {
                    message = string.Format("Expected binary sub type to be UuidStandard or UuidLegacy, not {0}.", subType);
                    throw new FileFormatException(message);
                }
                if (bsonReader.GuidRepresentation == GuidRepresentation.Unspecified)
                {
                    throw new BsonSerializationException("GuidSerializer cannot deserialize a Guid when GuidRepresentation is Unspecified.");
                }
                var expectedSubType = (bsonReader.GuidRepresentation == GuidRepresentation.Standard) ? BsonBinarySubType.UuidStandard : BsonBinarySubType.UuidLegacy;
                if (subType != expectedSubType)
                {
                    message = string.Format("Expected binary sub type {0}, not {1}, for GuidRepresentation {2}.", expectedSubType, subType, bsonReader.GuidRepresentation);
                    throw new FileFormatException(message);
                }
                return(GuidConverter.FromBytes(bytes, bsonReader.GuidRepresentation));

            case BsonType.String:
                return(new Guid(bsonReader.ReadString()));

            default:
                message = string.Format("Cannot deserialize Guid from BsonType {0}.", bsonType);
                throw new FileFormatException(message);
            }
        }
        /// <summary>
        /// Serializes an object to a BsonWriter.
        /// </summary>
        /// <param name="bsonWriter">The BsonWriter.</param>
        /// <param name="nominalType">The nominal type.</param>
        /// <param name="value">The object.</param>
        /// <param name="options">The serialization options.</param>
        public override void Serialize(
            BsonWriter bsonWriter,
            Type nominalType,
            object value,
            IBsonSerializationOptions options)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            var binaryData = (BsonBinaryData)value;

            var subType = binaryData.SubType;

            if (subType == BsonBinarySubType.UuidStandard || subType == BsonBinarySubType.UuidLegacy)
            {
                var writerGuidRepresentation = bsonWriter.Settings.GuidRepresentation;
                if (writerGuidRepresentation != GuidRepresentation.Unspecified)
                {
                    var bytes = binaryData.Bytes;
                    var guidRepresentation = binaryData.GuidRepresentation;

                    if (guidRepresentation == GuidRepresentation.Unspecified)
                    {
                        var message = string.Format(
                            "Cannot serialize BsonBinaryData with GuidRepresentation Unspecified to destination with GuidRepresentation {0}.",
                            writerGuidRepresentation);
                        throw new BsonSerializationException(message);
                    }
                    if (guidRepresentation != writerGuidRepresentation)
                    {
                        var guid = GuidConverter.FromBytes(bytes, guidRepresentation);
                        bytes              = GuidConverter.ToBytes(guid, writerGuidRepresentation);
                        subType            = (writerGuidRepresentation == GuidRepresentation.Standard) ? BsonBinarySubType.UuidStandard : BsonBinarySubType.UuidLegacy;
                        guidRepresentation = writerGuidRepresentation;
                        binaryData         = new BsonBinaryData(bytes, subType, guidRepresentation);
                    }
                }
            }

            bsonWriter.WriteBinaryData(binaryData);
        }
Example #9
0
        // public methods
        /// <summary>
        /// Deserializes an object from a BsonReader.
        /// </summary>
        /// <param name="bsonReader">The BsonReader.</param>
        /// <param name="nominalType">The nominal type of the object.</param>
        /// <param name="actualType">The actual type of the object.</param>
        /// <param name="options">The serialization options.</param>
        /// <returns>An object.</returns>
        public override object Deserialize(
            BsonReader bsonReader,
            Type nominalType,
            Type actualType,
            IBsonSerializationOptions options)
        {
            VerifyTypes(nominalType, actualType, typeof(Guid));

            var    bsonType = bsonReader.GetCurrentBsonType();
            string message;

            switch (bsonType)
            {
            case BsonType.Binary:
                var binaryData         = bsonReader.ReadBinaryData();
                var bytes              = binaryData.Bytes;
                var subType            = binaryData.SubType;
                var guidRepresentation = binaryData.GuidRepresentation;
                if (bytes.Length != 16)
                {
                    message = string.Format("Expected length to be 16, not {0}.", bytes.Length);
                    throw new FileFormatException(message);
                }
                if (subType != BsonBinarySubType.UuidStandard && subType != BsonBinarySubType.UuidLegacy)
                {
                    message = string.Format("Expected binary sub type to be UuidStandard or UuidLegacy, not {0}.", subType);
                    throw new FileFormatException(message);
                }
                if (guidRepresentation == GuidRepresentation.Unspecified)
                {
                    throw new BsonSerializationException("GuidSerializer cannot deserialize a Guid when GuidRepresentation is Unspecified.");
                }
                return(GuidConverter.FromBytes(bytes, guidRepresentation));

            case BsonType.String:
                return(new Guid(bsonReader.ReadString()));

            default:
                message = string.Format("Cannot deserialize Guid from BsonType {0}.", bsonType);
                throw new FileFormatException(message);
            }
        }
        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();
                        }
                    }
        }
Example #11
0
        // public methods
        /// <summary>
        /// Deserializes a value.
        /// </summary>
        /// <param name="context">The deserialization context.</param>
        /// <param name="args">The deserialization args.</param>
        /// <returns>A deserialized value.</returns>
        public override Guid Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
        {
            var    bsonReader = context.Reader;
            string message;

            var bsonType = bsonReader.GetCurrentBsonType();

            switch (bsonType)
            {
            case BsonType.Binary:
                var binaryData         = bsonReader.ReadBinaryData();
                var bytes              = binaryData.Bytes;
                var subType            = binaryData.SubType;
                var guidRepresentation = binaryData.GuidRepresentation;
                if (bytes.Length != 16)
                {
                    message = string.Format("Expected length to be 16, not {0}.", bytes.Length);
                    throw new FormatException(message);
                }
                if (subType != BsonBinarySubType.UuidStandard && subType != BsonBinarySubType.UuidLegacy)
                {
                    message = string.Format("Expected binary sub type to be UuidStandard or UuidLegacy, not {0}.", subType);
                    throw new FormatException(message);
                }
                if (guidRepresentation == GuidRepresentation.Unspecified)
                {
                    throw new BsonSerializationException("GuidSerializer cannot deserialize a Guid when GuidRepresentation is Unspecified.");
                }
                return(GuidConverter.FromBytes(bytes, guidRepresentation));

            case BsonType.String:
                return(new Guid(bsonReader.ReadString()));

            default:
                throw CreateCannotDeserializeFromBsonTypeException(bsonType);
            }
        }
        public void CorpusTest(
            [Values(false, true)] bool useLocalSchema,
            [Values(false, true)] bool async)
        {
            RequireServer.Check().Supports(Feature.ClientSideEncryption);

            var corpusSchema = JsonFileReader.Instance.Documents["corpus.corpus-schema.json"];
            var schemaMap    = useLocalSchema ? new BsonDocument("db.coll", corpusSchema) : null;

            using (var client = ConfigureClient())
                using (var clientEncrypted = ConfigureClientEncrypted(schemaMap))
                    using (var clientEncryption = ConfigureClientEncryption(clientEncrypted.Wrapped as MongoClient))
                    {
                        CreateCollection(client, __collCollectionNamespace, new BsonDocument("$jsonSchema", corpusSchema));

                        var corpusKeyLocal     = JsonFileReader.Instance.Documents["corpus.corpus-key-local.json"];
                        var corpusKeyAws       = JsonFileReader.Instance.Documents["corpus.corpus-key-aws.json"];
                        var keyVaultCollection = GetCollection(client, __keyVaultCollectionNamespace);
                        Insert(keyVaultCollection, async, corpusKeyLocal, corpusKeyAws);

                        var corpus       = JsonFileReader.Instance.Documents["corpus.corpus.json"];
                        var corpusCopied = new BsonDocument
                        {
                            corpus.GetElement("_id"),
                            corpus.GetElement("altname_aws"),
                            corpus.GetElement("altname_local")
                        };

                        foreach (var corpusElement in corpus.Elements.Where(c => c.Value.IsBsonDocument))
                        {
                            var corpusValue = corpusElement.Value.DeepClone();
                            var kms         = corpusValue["kms"].AsString;
                            var abbreviatedAlgorithmName = corpusValue["algo"].AsString;
                            var identifier = corpusValue["identifier"].AsString;
                            var allowed    = corpusValue["allowed"].ToBoolean();
                            var value      = corpusValue["value"];
                            var method     = corpusValue["method"].AsString;
                            switch (method)
                            {
                            case "auto":
                                corpusCopied.Add(corpusElement);
                                continue;

                            case "explicit":
                            {
                                var            encryptionOptions = CreateEncryptOptions(abbreviatedAlgorithmName, identifier, kms);
                                BsonBinaryData encrypted         = null;
                                var            exception         = Record.Exception(() =>
                                    {
                                        encrypted = ExplicitEncrypt(
                                            clientEncryption,
                                            encryptionOptions,
                                            value,
                                            async);
                                    });
                                if (allowed)
                                {
                                    exception.Should().BeNull();
                                    encrypted.Should().NotBeNull();
                                    corpusValue["value"] = encrypted;
                                }
                                else
                                {
                                    exception.Should().NotBeNull();
                                }
                                corpusCopied.Add(new BsonElement(corpusElement.Name, corpusValue));
                            }
                            break;

                            default:
                                throw new ArgumentException($"Unsupported method name {method}.", nameof(method));
                            }
                        }

                        var coll = GetCollection(clientEncrypted, __collCollectionNamespace);
                        Insert(coll, async, corpusCopied);

                        var corpusDecrypted = Find(coll, new BsonDocument(), async).Single();
                        corpusDecrypted.Should().Be(corpus);

                        var corpusEncryptedExpected = JsonFileReader.Instance.Documents["corpus.corpus-encrypted.json"];
                        coll = GetCollection(client, __collCollectionNamespace);
                        var corpusEncryptedActual = Find(coll, new BsonDocument(), async).Single();
                        foreach (var expectedElement in corpusEncryptedExpected.Elements.Where(c => c.Value.IsBsonDocument))
                        {
                            var expectedElementValue = expectedElement.Value;
                            var expectedAlgorithm    = ParseAlgorithm(expectedElementValue["algo"].AsString);
                            var expectedAllowed      = expectedElementValue["allowed"].ToBoolean();
                            var expectedValue        = expectedElementValue["value"];
                            var actualValue          = corpusEncryptedActual.GetValue(expectedElement.Name)["value"];

                            switch (expectedAlgorithm)
                            {
                            case EncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic:
                                actualValue.Should().Be(expectedValue);
                                break;

                            case EncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Random:
                                if (expectedAllowed)
                                {
                                    actualValue.Should().NotBe(expectedValue);
                                }
                                break;

                            default:
                                throw new ArgumentException($"Unsupported expected algorithm {expectedAllowed}.", nameof(expectedAlgorithm));
                            }

                            if (expectedAllowed)
                            {
                                var actualDecryptedValue   = ExplicitDecrypt(clientEncryption, actualValue.AsBsonBinaryData, async);
                                var expectedDecryptedValue = ExplicitDecrypt(clientEncryption, expectedValue.AsBsonBinaryData, async);
                                actualDecryptedValue.Should().Be(expectedDecryptedValue);
                            }
                            else
                            {
                                actualValue.Should().Be(expectedValue);
                            }
                        }
                    }

            EncryptOptions CreateEncryptOptions(string algorithm, string identifier, string kms)
            {
                Guid?  keyId         = null;
                string alternateName = null;

                if (identifier == "id")
                {
                    switch (kms)
                    {
                    case "local":
                        keyId = GuidConverter.FromBytes(Convert.FromBase64String("LOCALAAAAAAAAAAAAAAAAA=="), GuidRepresentation.Standard);
                        break;

                    case "aws":
                        keyId = GuidConverter.FromBytes(Convert.FromBase64String("AWSAAAAAAAAAAAAAAAAAAA=="), GuidRepresentation.Standard);
                        break;

                    default:
                        throw new ArgumentException($"Unsupported kms type {kms}.");
                    }
                }
                else if (identifier == "altname")
                {
                    alternateName = kms;
                }
                else
                {
                    throw new ArgumentException($"Unsupported identifier {identifier}.", nameof(identifier));
                }

                return(new EncryptOptions(ParseAlgorithm(algorithm).ToString(), alternateName, keyId));
            }

            EncryptionAlgorithm ParseAlgorithm(string algorithm)
            {
                switch (algorithm)
                {
                case "rand":
                    return(EncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Random);

                case "det":
                    return(EncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic);

                default:
                    throw new ArgumentException($"Unsupported algorithm {algorithm}.");
                }
            }
        }
        // private methods
        private void ReadValue()
        {
            object jsonDotNetValue;

            switch (_wrappedReader.GetCurrentBsonType())
            {
            case BsonType.Array:
                _wrappedReader.ReadStartArray();
                SetCurrentToken(Newtonsoft.Json.JsonToken.StartArray);
                return;

            case BsonType.Binary:
                var bsonBinaryData = _wrappedReader.ReadBinaryData();
                switch (bsonBinaryData.SubType)
                {
                case BsonBinarySubType.UuidLegacy:
                    var guidRepresentation = GuidRepresentation.Unspecified;
                    var bsonReader         = _wrappedReader as BsonReader;
                    if (bsonReader != null)
                    {
                        guidRepresentation = bsonReader.Settings.GuidRepresentation;
                    }
                    jsonDotNetValue = GuidConverter.FromBytes(bsonBinaryData.Bytes, guidRepresentation);
                    break;

                case BsonBinarySubType.UuidStandard:
                    jsonDotNetValue = GuidConverter.FromBytes(bsonBinaryData.Bytes, GuidRepresentation.Standard);
                    break;

                default:
                    jsonDotNetValue = bsonBinaryData.Bytes;
                    break;
                }
                SetCurrentToken(Newtonsoft.Json.JsonToken.Bytes, jsonDotNetValue, bsonBinaryData);
                return;

            case BsonType.Boolean:
                var booleanValue = _wrappedReader.ReadBoolean();
                SetCurrentToken(Newtonsoft.Json.JsonToken.Boolean, booleanValue, (BsonBoolean)booleanValue);
                return;

            case BsonType.DateTime:
                var bsonDateTime = new BsonDateTime(_wrappedReader.ReadDateTime());
                if (bsonDateTime.IsValidDateTime)
                {
                    jsonDotNetValue = bsonDateTime.ToUniversalTime();
                }
                else
                {
                    jsonDotNetValue = bsonDateTime.MillisecondsSinceEpoch;
                }
                SetCurrentToken(Newtonsoft.Json.JsonToken.Date, jsonDotNetValue, bsonDateTime);
                return;

            case BsonType.Document:
                _wrappedReader.ReadStartDocument();
                SetCurrentToken(Newtonsoft.Json.JsonToken.StartObject);
                return;

            case BsonType.Double:
                var bsonDouble = new BsonDouble(_wrappedReader.ReadDouble());
                switch (FloatParseHandling)
                {
                case Newtonsoft.Json.FloatParseHandling.Decimal:
                    jsonDotNetValue = Convert.ToDecimal(bsonDouble);
                    break;

                case Newtonsoft.Json.FloatParseHandling.Double:
                    jsonDotNetValue = bsonDouble.Value;
                    break;

                default:
                    throw new NotSupportedException(string.Format("Unexpected FloatParseHandling value: {0}.", FloatParseHandling));
                }
                SetCurrentToken(Newtonsoft.Json.JsonToken.Float, jsonDotNetValue, bsonDouble);
                return;

            case BsonType.Int32:
                var bsonInt32 = (BsonInt32)_wrappedReader.ReadInt32();
                SetCurrentToken(Newtonsoft.Json.JsonToken.Integer, (long)bsonInt32.Value, bsonInt32);
                return;

            case BsonType.Int64:
                var bsonInt64 = (BsonInt64)_wrappedReader.ReadInt64();
                SetCurrentToken(Newtonsoft.Json.JsonToken.Integer, bsonInt64.Value, bsonInt64);
                return;

            case BsonType.JavaScript:
            {
                var code           = _wrappedReader.ReadJavaScript();
                var bsonJavaScript = new BsonJavaScript(code);
                SetCurrentToken(Newtonsoft.Json.JsonToken.String, code, bsonJavaScript);
            }
                return;

            case BsonType.JavaScriptWithScope:
            {
                var code    = _wrappedReader.ReadJavaScriptWithScope();
                var context = BsonDeserializationContext.CreateRoot(_wrappedReader);
                var scope   = BsonDocumentSerializer.Instance.Deserialize <BsonDocument>(context);
                var bsonJavaScriptWithScope = new BsonJavaScriptWithScope(code, scope);
                SetCurrentToken(Newtonsoft.Json.JsonToken.String, code, bsonJavaScriptWithScope);
            }
                return;

            case BsonType.MaxKey:
                _wrappedReader.ReadMaxKey();
                SetCurrentToken(Newtonsoft.Json.JsonToken.Undefined, null, BsonMaxKey.Value);
                return;

            case BsonType.MinKey:
                _wrappedReader.ReadMinKey();
                SetCurrentToken(Newtonsoft.Json.JsonToken.Undefined, null, BsonMinKey.Value);
                return;

            case BsonType.Null:
                _wrappedReader.ReadNull();
                SetCurrentToken(Newtonsoft.Json.JsonToken.Null, null, BsonNull.Value);
                return;

            case BsonType.ObjectId:
                var bsonObjectId = new BsonObjectId(_wrappedReader.ReadObjectId());
                SetCurrentToken(Newtonsoft.Json.JsonToken.Bytes, bsonObjectId.Value.ToByteArray(), bsonObjectId);
                return;

            case BsonType.RegularExpression:
                var bsonRegularExpression = _wrappedReader.ReadRegularExpression();
                var pattern = bsonRegularExpression.Pattern;
                var options = bsonRegularExpression.Options;
                jsonDotNetValue = "/" + pattern.Replace("/", "\\/") + "/" + options;
                SetCurrentToken(Newtonsoft.Json.JsonToken.String, jsonDotNetValue, bsonRegularExpression);
                return;

            case BsonType.String:
                var stringValue = _wrappedReader.ReadString();
                SetCurrentToken(Newtonsoft.Json.JsonToken.String, stringValue, (BsonString)stringValue);
                return;

            case BsonType.Symbol:
                var bsonSymbol = BsonSymbolTable.Lookup(_wrappedReader.ReadSymbol());
                SetCurrentToken(Newtonsoft.Json.JsonToken.String, bsonSymbol.Name, bsonSymbol);
                return;

            case BsonType.Timestamp:
                var bsonTimestamp = new BsonTimestamp(_wrappedReader.ReadTimestamp());
                SetCurrentToken(Newtonsoft.Json.JsonToken.Integer, bsonTimestamp.Value, bsonTimestamp);
                return;

            case BsonType.Undefined:
                _wrappedReader.ReadUndefined();
                SetCurrentToken(Newtonsoft.Json.JsonToken.Undefined, null, BsonUndefined.Value);
                return;

            default:
                var message = string.Format("Unexpected BsonType: {0}.", _wrappedReader.GetCurrentBsonType());
                throw new Newtonsoft.Json.JsonReaderException(message);
            }
        }
Example #14
0
        /// <summary>
        /// Writes BSON binary data to the writer.
        /// </summary>
        /// <param name="bytes">The binary data.</param>
        /// <param name="subType">The binary data subtype.</param>
        /// <param name="guidRepresentation">The representation for Guids.</param>
        public override void WriteBinaryData(
            byte[] bytes,
            BsonBinarySubType subType,
            GuidRepresentation guidRepresentation)
        {
            if (Disposed)
            {
                throw new ObjectDisposedException("JsonWriter");
            }
            if (State != BsonWriterState.Value && State != BsonWriterState.Initial)
            {
                ThrowInvalidState("WriteBinaryData", BsonWriterState.Value, BsonWriterState.Initial);
            }

            if (_jsonWriterSettings.OutputMode == JsonOutputMode.Shell)
            {
                WriteNameHelper(Name);
                switch (subType)
                {
                case BsonBinarySubType.UuidLegacy:
                case BsonBinarySubType.UuidStandard:
                    if (bytes.Length != 16)
                    {
                        var message = string.Format("Length of binary subtype {0} must be 16, not {1}.", subType, bytes.Length);
                        throw new ArgumentException(message);
                    }
                    if (subType == BsonBinarySubType.UuidLegacy && guidRepresentation == GuidRepresentation.Standard)
                    {
                        throw new ArgumentException("GuidRepresentation for binary subtype UuidLegacy must not be Standard.");
                    }
                    if (subType == BsonBinarySubType.UuidStandard && guidRepresentation != GuidRepresentation.Standard)
                    {
                        var message = string.Format("GuidRepresentation for binary subtype UuidStandard must be Standard, not {0}.", guidRepresentation);
                        throw new ArgumentException(message);
                    }
                    if (_jsonWriterSettings.ShellVersion >= new Version(2, 0, 0))
                    {
                        if (guidRepresentation == GuidRepresentation.Unspecified)
                        {
                            var s     = BsonUtils.ToHexString(bytes);
                            var parts = new string[]
                            {
                                s.Substring(0, 8),
                                s.Substring(8, 4),
                                s.Substring(12, 4),
                                s.Substring(16, 4),
                                s.Substring(20, 12)
                            };
                            _textWriter.Write("HexData({0}, \"{1}\")", (int)subType, string.Join("-", parts));
                        }
                        else
                        {
                            string uuidConstructorName;
                            switch (guidRepresentation)
                            {
                            case GuidRepresentation.CSharpLegacy: uuidConstructorName = "CSUUID"; break;

                            case GuidRepresentation.JavaLegacy: uuidConstructorName = "JUUID"; break;

                            case GuidRepresentation.PythonLegacy: uuidConstructorName = "PYUUID"; break;

                            case GuidRepresentation.Standard: uuidConstructorName = "UUID"; break;

                            default: throw new BsonInternalException("Unexpected GuidRepresentation");
                            }
                            var guid = GuidConverter.FromBytes(bytes, guidRepresentation);
                            _textWriter.Write("{0}(\"{1}\")", uuidConstructorName, guid.ToString());
                        }
                    }
                    else
                    {
                        _textWriter.Write("new BinData({0}, \"{1}\")", (int)subType, Convert.ToBase64String(bytes));
                    }
                    break;

                default:
                    _textWriter.Write("new BinData({0}, \"{1}\")", (int)subType, Convert.ToBase64String(bytes));
                    break;
                }
            }
            else
            {
                WriteStartDocument();
                WriteString("$binary", Convert.ToBase64String(bytes));
                WriteString("$type", ((int)subType).ToString("x2"));
                WriteEndDocument();
            }

            State = GetNextState();
        }
Example #15
0
        public void SerializeValue_should_convert_representation_when_required(
            [ClassValues(typeof(GuidModeValues))] GuidMode mode,
            [Values(
                 GuidRepresentation.CSharpLegacy,
                 GuidRepresentation.JavaLegacy,
                 GuidRepresentation.PythonLegacy,
                 GuidRepresentation.Standard,
                 GuidRepresentation.Unspecified)] GuidRepresentation writerGuidRepresentation,
            [Values(
                 GuidRepresentation.CSharpLegacy,
                 GuidRepresentation.JavaLegacy,
                 GuidRepresentation.PythonLegacy,
                 GuidRepresentation.Standard,
                 GuidRepresentation.Unspecified)] GuidRepresentation valueGuidRepresentation)
        {
            mode.Set();

#pragma warning disable 618
            var subject = new BsonBinaryDataSerializer();

            var mockWriter     = new Mock <IBsonWriter>();
            var writerSettings = new BsonBinaryWriterSettings();
            if (BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2)
            {
                writerSettings.GuidRepresentation = writerGuidRepresentation;
            }
            mockWriter.SetupGet(m => m.Settings).Returns(writerSettings);
            var context = BsonSerializationContext.CreateRoot(mockWriter.Object);
            var args    = new BsonSerializationArgs();
            var bytes   = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
            var subType = valueGuidRepresentation == GuidRepresentation.Unspecified ? BsonBinarySubType.UuidLegacy : GuidConverter.GetSubType(valueGuidRepresentation);
            var value   = BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2
                ? new BsonBinaryData(bytes, subType, valueGuidRepresentation)
                : new BsonBinaryData(bytes, subType);

            var isExceptionExpected =
                BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2 &&
                writerGuidRepresentation != GuidRepresentation.Unspecified &&
                valueGuidRepresentation == GuidRepresentation.Unspecified;

            if (!isExceptionExpected)
            {
                subject.Serialize(context, args, value);

                var shouldConvertRepresentation =
                    BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2 &&
                    writerGuidRepresentation != GuidRepresentation.Unspecified &&
                    valueGuidRepresentation != GuidRepresentation.Unspecified &&
                    valueGuidRepresentation != writerGuidRepresentation;

                var writtenValue = value;
                if (shouldConvertRepresentation)
                {
                    var guid             = GuidConverter.FromBytes(bytes, valueGuidRepresentation);
                    var convertedBytes   = GuidConverter.ToBytes(guid, writerGuidRepresentation);
                    var convertedSubType = GuidConverter.GetSubType(writerGuidRepresentation);
                    writtenValue = new BsonBinaryData(convertedBytes, convertedSubType, writerGuidRepresentation);
                }

                mockWriter.Verify(m => m.WriteBinaryData(writtenValue), Times.Once);
            }
#pragma warning restore 618
        }