Example #1
0
        public static XElement?EncryptIfNecessary(this IXmlEncryptor encryptor, XElement element)
        {
            // If no encryption is necessary, return null.
            if (!DoesElementOrDescendentRequireEncryption(element))
            {
                return(null);
            }

            // Deep copy the element (since we're going to mutate) and put
            // it into a document to guarantee it has a parent.
            var doc = new XDocument(new XElement(element));

            // We remove elements from the document as we encrypt them and perform
            // fix-up later. This keeps us from going into an infinite loop in
            // the case of a null encryptor (which returns its original input which
            // is still marked as 'requires encryption').
            var placeholderReplacements = new Dictionary <XElement, EncryptedXmlInfo>();

            while (true)
            {
                var elementWhichRequiresEncryption = doc.Descendants().FirstOrDefault(DoesSingleElementRequireEncryption);
                if (elementWhichRequiresEncryption == null)
                {
                    // All encryption is finished.
                    break;
                }

                // Encrypt the clone so that the encryptor doesn't inadvertently modify
                // the original document or other data structures.
                var clonedElementWhichRequiresEncryption = new XElement(elementWhichRequiresEncryption);
                var innerDoc         = new XDocument(clonedElementWhichRequiresEncryption);
                var encryptedXmlInfo = encryptor.Encrypt(clonedElementWhichRequiresEncryption);
                CryptoUtil.Assert(encryptedXmlInfo != null, "IXmlEncryptor.Encrypt returned null.");

                // Put a placeholder into the original document so that we can continue our
                // search for elements which need to be encrypted.
                var newPlaceholder = new XElement("placeholder");
                placeholderReplacements[newPlaceholder] = encryptedXmlInfo;
                elementWhichRequiresEncryption.ReplaceWith(newPlaceholder);
            }

            // Finally, perform fixup.
            Debug.Assert(placeholderReplacements.Count > 0);
            foreach (var entry in placeholderReplacements)
            {
                // <enc:encryptedSecret decryptorType="{type}" xmlns:enc="{ns}">
                //   <element />
                // </enc:encryptedSecret>
                entry.Key.ReplaceWith(
                    new XElement(XmlConstants.EncryptedSecretElementName,
                                 new XAttribute(XmlConstants.DecryptorTypeAttributeName, entry.Value.DecryptorType.AssemblyQualifiedName !),
                                 entry.Value.EncryptedElement));
            }
            return(doc.Root);
        }
 public MyKeyEscrowSink(IServiceProvider services)
 {
     // Assuming I'm on a machine that's a member of the CONTOSO
     // domain, I can use the Domain Admins SID to generate an
     // encrypted payload that only they can read. Sample SID from
     // https://technet.microsoft.com/library/cc778824(v=ws.10).aspx.
     _escrowEncryptor = new DpapiNGXmlEncryptor(
         "SID=S-1-5-21-1004336348-1177238915-682003330-512",
         DpapiNGProtectionDescriptorFlags.None,
         services);
 }
 public MyKeyEscrowSink(IServiceProvider services)
 {
     // Assuming I'm on a machine that's a member of the CONTOSO
     // domain, I can use the Domain Admins SID to generate an
     // encrypted payload that only they can read. Sample SID from
     // https://technet.microsoft.com/en-us/library/cc778824(v=ws.10).aspx.
     _escrowEncryptor = new DpapiNGXmlEncryptor(
         "SID=S-1-5-21-1004336348-1177238915-682003330-512",
         DpapiNGProtectionDescriptorFlags.None,
         services);
 }
 public XmlKeyManager(
     [NotNull] IServiceProvider serviceProvider,
     [NotNull] IAuthenticatedEncryptorConfigurationFactory authenticatedEncryptorConfigurationFactory,
     [NotNull] ITypeActivator typeActivator,
     [NotNull] IXmlRepository xmlRepository,
     [NotNull] IXmlEncryptor xmlEncryptor)
 {
     _serviceProvider = serviceProvider;
     _authenticatedEncryptorConfigurationFactory = authenticatedEncryptorConfigurationFactory;
     _typeActivator = typeActivator;
     _xmlRepository = xmlRepository;
     _xmlEncryptor  = xmlEncryptor;
 }
Example #5
0
        public XElement ToXml([NotNull] IXmlEncryptor xmlEncryptor)
        {
            // <cbcEncryptor reader="{TYPE}">
            //   <encryption algorithm="{STRING}" provider="{STRING}" keyLength="{INT}" />
            //   <secret>...</secret>
            // </cbcEncryptor>

            return(new XElement(GcmEncryptorElementName,
                                new XAttribute("reader", typeof(CngGcmAuthenticatedEncryptorConfigurationXmlReader).AssemblyQualifiedName),
                                new XElement(EncryptionElementName,
                                             new XAttribute("algorithm", _options.EncryptionAlgorithm),
                                             new XAttribute("provider", _options.EncryptionAlgorithmProvider ?? String.Empty),
                                             new XAttribute("keyLength", _options.EncryptionAlgorithmKeySize)),
                                EncryptSecret(xmlEncryptor)));
        }
        public XElement ToXml([NotNull] IXmlEncryptor xmlEncryptor)
        {
            // <managedEncryptor reader="{TYPE}">
            //   <encryption type="{TYPE}" keyLength="{INT}" />
            //   <validation type="{TYPE}" />
            //   <secret>...</secret>
            // </managedEncryptor>

            return(new XElement(ManagedEncryptorElementName,
                                new XAttribute("reader", typeof(ManagedAuthenticatedEncryptorConfigurationXmlReader).AssemblyQualifiedName),
                                new XElement(EncryptionElementName,
                                             new XAttribute("type", _options.EncryptionAlgorithmType),
                                             new XAttribute("keyLength", _options.EncryptionAlgorithmKeySize)),
                                new XElement(ValidationElementName,
                                             new XAttribute("type", _options.ValidationAlgorithmType)),
                                EncryptSecret(xmlEncryptor)));
        }
Example #7
0
        private XElement EncryptSecret(IXmlEncryptor encryptor)
        {
            // First, create the inner <secret> element.
            XElement secretElement;

            byte[] plaintextSecret = new byte[_secret.Length];
            try
            {
                _secret.WriteSecretIntoBuffer(new ArraySegment <byte>(plaintextSecret));
                secretElement = new XElement(SecretElementName, Convert.ToBase64String(plaintextSecret));
            }
            finally
            {
                Array.Clear(plaintextSecret, 0, plaintextSecret.Length);
            }

            // Then encrypt it and wrap it in another <secret> element.
            var encryptedSecretElement = encryptor.Encrypt(secretElement);

            CryptoUtil.Assert(!String.IsNullOrEmpty((string)encryptedSecretElement.Attribute("decryptor")),
                              @"TODO: <secret> encryption was invalid.");

            return(new XElement(SecretElementName, encryptedSecretElement));
        }
Example #8
0
        internal KeyValuePair <IXmlRepository, IXmlEncryptor> GetFallbackKeyRepositoryEncryptorPair()
        {
            IXmlRepository repository = null;
            IXmlEncryptor  encryptor  = null;

            // If we're running in Azure Web Sites, the key repository goes in the %HOME% directory.
            var azureWebSitesKeysFolder = _keyStorageDirectories.GetKeyStorageDirectoryForAzureWebSites();

            if (azureWebSitesKeysFolder != null)
            {
                _logger.UsingAzureAsKeyRepository(azureWebSitesKeysFolder.FullName);

                // Cloud DPAPI isn't yet available, so we don't encrypt keys at rest.
                // This isn't all that different than what Azure Web Sites does today, and we can always add this later.
                repository = new FileSystemXmlRepository(azureWebSitesKeysFolder, _loggerFactory);
            }
            else
            {
                // If the user profile is available, store keys in the user profile directory.
                var localAppDataKeysFolder = _keyStorageDirectories.GetKeyStorageDirectory();
                if (localAppDataKeysFolder != null)
                {
                    if (OSVersionUtil.IsWindows())
                    {
                        Debug.Assert(RuntimeInformation.IsOSPlatform(OSPlatform.Windows)); // Hint for the platform compatibility analyzer.

                        // If the user profile is available, we can protect using DPAPI.
                        // Probe to see if protecting to local user is available, and use it as the default if so.
                        encryptor = new DpapiXmlEncryptor(
                            protectToLocalMachine: !DpapiSecretSerializerHelper.CanProtectToCurrentUserAccount(),
                            loggerFactory: _loggerFactory);
                    }
                    repository = new FileSystemXmlRepository(localAppDataKeysFolder, _loggerFactory);

                    if (encryptor != null)
                    {
                        _logger.UsingProfileAsKeyRepositoryWithDPAPI(localAppDataKeysFolder.FullName);
                    }
                    else
                    {
                        _logger.UsingProfileAsKeyRepository(localAppDataKeysFolder.FullName);
                    }
                }
                else
                {
                    // Use profile isn't available - can we use the HKLM registry?
                    RegistryKey regKeyStorageKey = null;
                    if (OSVersionUtil.IsWindows())
                    {
                        Debug.Assert(RuntimeInformation.IsOSPlatform(OSPlatform.Windows)); // Hint for the platform compatibility analyzer.
                        regKeyStorageKey = RegistryXmlRepository.DefaultRegistryKey;
                    }
                    if (regKeyStorageKey != null)
                    {
                        Debug.Assert(RuntimeInformation.IsOSPlatform(OSPlatform.Windows)); // Hint for the platform compatibility analyzer.
                        regKeyStorageKey = RegistryXmlRepository.DefaultRegistryKey;

                        // If the user profile isn't available, we can protect using DPAPI (to machine).
                        encryptor  = new DpapiXmlEncryptor(protectToLocalMachine: true, loggerFactory: _loggerFactory);
                        repository = new RegistryXmlRepository(regKeyStorageKey, _loggerFactory);

                        _logger.UsingRegistryAsKeyRepositoryWithDPAPI(regKeyStorageKey.Name);
                    }
                    else
                    {
                        // Final fallback - use an ephemeral repository since we don't know where else to go.
                        // This can only be used for development scenarios.
                        repository = new EphemeralXmlRepository(_loggerFactory);

                        _logger.UsingEphemeralKeyRepository();
                    }
                }
            }

            return(new KeyValuePair <IXmlRepository, IXmlEncryptor>(repository, encryptor));
        }