Beispiel #1
0
        private XmlDocument CreateDocumentFromSecrets(IEnumerable <Secret> secrets)
        {
            XmlDocument document = CreateNewDocument();

            if (secrets == null)
            {
                return(document);
            }

            // Check if there are any elements in the collection, and also get hold of the first element in the collection
            IEnumerator <Secret> enumerator = secrets.GetEnumerator();

            if (!enumerator.MoveNext())
            {
                if (New <ILogging>().IsWarningEnabled)
                {
                    New <ILogging>().LogWarning($"{nameof(CreateDocumentFromSecrets)} No elements in collection");
                }
                return(document);
            }

            // This is where we sort the secret collection into a session per key.... Right now we assume the same
            // key for all....

            InternalEncryptionKey key = new InternalEncryptionKey(enumerator.Current.EncryptionKey);

            // Get some salt for the key-derivation function
            byte[] salt = New <IRandomGenerator>().Generate(16);

            SymmetricAlgorithm masterKey = DeriveMasterKey(key.DecryptPassphrase(), salt, _defaultRfc2898iterations);

            LastUpdateUtc = New <INow>().Utc;

            // Start building a session node, recording the used salt and the number of iterations
            XmlElement xecretsSession = document.CreateElement("XecretsSession");

            xecretsSession.Attributes.Append(document.CreateAttribute("KeyDerivation")).Value = "Rfc2898";
            xecretsSession.Attributes.Append(document.CreateAttribute("Salt")).Value          = System.Convert.ToBase64String(salt);
            xecretsSession.Attributes.Append(document.CreateAttribute("Iterations")).Value    = _defaultRfc2898iterations.ToString(CultureInfo.InvariantCulture);
            xecretsSession.Attributes.Append(document.CreateAttribute("LastUpdateUtc")).Value = LastUpdateUtc.ToString(CultureInfo.InvariantCulture);

            // Get the secrets collection in the form of an appropriate XML Element, suitable for encryption.
            XmlElement secretsElement = CreateSecretsElement(document, secrets);

            xecretsSession.AppendChild(secretsElement);

            // Encrypt the node, creating a named session key and embedding it in the output.
            EncryptedXml encryptedXml = new EncryptedXml();

            encryptedXml.AddKeyNameMapping(KEYNAME, masterKey);
            EncryptedData encryptedData = encryptedXml.Encrypt(secretsElement, KEYNAME);

            // Replace the encrypted element with the encrypted same
            EncryptedXml.ReplaceElement(secretsElement, encryptedData, false);

            // Finally, actually append this to the set of sessions.
            document.SelectSingleNode("AxantumXecrets/XecretsSessions").AppendChild(xecretsSession);

            return(document);
        }
Beispiel #2
0
        private static XmlDocument DecryptEncryptedData(InternalEncryptionKey internalKey, XmlElement sessionElement)
        {
            XmlElement secretsElement = sessionElement.FirstChild as XmlElement;

            if (secretsElement == null || secretsElement.Name != "EncryptedData")
            {
                throw new FormatException($"There must be an element named {nameof(EncryptedData)} here.");
            }

            SymmetricAlgorithm masterKey = GetAndDeriveMasterKey(internalKey.DecryptPassphrase(), sessionElement);

            // Decrypt the node, creating a named session key to use the embedded session key.
            EncryptedXml encryptedXml = new EncryptedXml();

            encryptedXml.AddKeyNameMapping(KEYNAME, masterKey);

            EncryptedData encryptedData = new EncryptedData();

            encryptedData.LoadXml(secretsElement);

            SymmetricAlgorithm decryptionKey;

            try
            {
                decryptionKey = encryptedXml.GetDecryptionKey(encryptedData, null);
            }
            catch (CryptographicException)
            {
                // This ok - we're not guaranteed that we actually provided the correct key.
                return(null);
            }

            // It seems mono doesn't throw, but returns a null key instead.
            if (decryptionKey == null)
            {
                return(null);
            }

            byte[] plainTextXml = encryptedXml.DecryptData(encryptedData, decryptionKey);
            string plain        = encryptedXml.Encoding.GetString(plainTextXml);

            XmlDocument decryptedSecretsDocument = new XmlDocument();

            decryptedSecretsDocument.LoadXml(plain);

            return(decryptedSecretsDocument);
        }