Пример #1
0
        public static (OuterContainer Container, byte[] Key) CreateOuterContainer(string password)
        {
            string outerVersion = "1.0";

            int saltLength = 32;             // critical security parameter

            int iterationCount = 100000;     // critical security parameter

            string hashAlgorithm = "SHA512"; // critical security parameter

            int keyLength = 32;              // critical security parameter

            byte[] salt = GenerateSalt(saltLength);

            byte[] key = Pbkdf2DeriveKeyFromPassword(password, salt, iterationCount, hashAlgorithm, keyLength);

            OuterContainer outerContainer = new OuterContainer();

            outerContainer.Version       = outerVersion;
            outerContainer.KeyDerivation = new KeyDerivation();
            outerContainer.KeyDerivation.DerivationAlgorithm = "PBKDF2";
            outerContainer.KeyDerivation.HashAlgorithm       = hashAlgorithm;
            outerContainer.KeyDerivation.Salt           = salt;
            outerContainer.KeyDerivation.IterationCount = iterationCount;
            outerContainer.KeyDerivation.KeyLength      = keyLength;
            outerContainer.EncryptedDataPlaceholder     = "placeholder";

            return(outerContainer, key);
        }
Пример #2
0
        public static byte[] EncryptOuterContainer(OuterContainer outerContainer, InnerContainer innerContainer, byte[] key)
        {
            XmlDocument outerContainerXml = SerializeOuterContainer(outerContainer);

            XmlDocument innerContainerXml = SerializeInnerContainer(innerContainer);

            XmlElement encryptedDataPlaceholder = outerContainerXml.GetElementsByTagName("EncryptedDataPlaceholder")[0] as XmlElement;

            XmlElement plaintextInnerContainer = innerContainerXml.GetElementsByTagName("InnerContainer")[0] as XmlElement;

            EncryptedData encryptedData = new EncryptedData();

            encryptedData.Type             = EncryptedXml.XmlEncElementUrl;
            encryptedData.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url);

            EncryptedXml encryptedXml = new EncryptedXml();

            using (AesCryptoServiceProvider aesCsp = new AesCryptoServiceProvider())
            {
                aesCsp.KeySize = 256;            // critical security parameter
                aesCsp.Key     = key;            // critical security parameter
                aesCsp.Mode    = CipherMode.CBC; // critical security parameter
                aesCsp.GenerateIV();             // critical security parameter

                encryptedData.CipherData.CipherValue = encryptedXml.EncryptData(plaintextInnerContainer, aesCsp, false);
            }

            EncryptedXml.ReplaceElement(encryptedDataPlaceholder, encryptedData, false);

            byte[] outerContainerBytes = Encoding.UTF8.GetBytes(outerContainerXml.OuterXml);

            byte[] fileBytes = Shared.Utility.Compress(outerContainerBytes);

            return(fileBytes);
        }
Пример #3
0
        public static XmlDocument SerializeOuterContainer(OuterContainer outerContainer)
        {
            XmlDocument    doc            = new XmlDocument();
            XmlDeclaration xmlDeclaration = doc.CreateXmlDeclaration("1.0", "UTF-8", null);

            doc.InsertBefore(xmlDeclaration, doc.DocumentElement);
            XPathNavigator nav = doc.CreateNavigator();

            using (XmlWriter w = nav.AppendChild())
            {
                XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
                ns.Add(string.Empty, string.Empty); // remove xsd and xsi attributes
                XmlSerializer s = new XmlSerializer(typeof(OuterContainer));
                s.Serialize(w, outerContainer, ns);
            }
            return(doc);
        }
Пример #4
0
        public static (OuterContainer ContainerOuter, InnerContainer ContainerInner, byte[] Key) DecryptOuterContainer(byte[] fileBytes, string password)
        {
            byte[] outerContainerBytes;

            try
            {
                outerContainerBytes = Shared.Utility.Decompress(fileBytes);
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("failed to decompress (corrupted or not a valid container file): {0}", ex.Message));
            }

            XmlDocument outerContainerXml = new XmlDocument();

            outerContainerXml.LoadXml(Encoding.UTF8.GetString(outerContainerBytes));

            string version;

            try
            {
                version = outerContainerXml.SelectSingleNode("/OuterContainer/@version").Value;
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("unable to read /OuterContainer/@version: {0}", ex.Message));
            }

            Version parsedVersion = new Version(version);

            if (parsedVersion.Major != 1)
            {
                throw new Exception(string.Format("outer container version too new (this container was written on a newer software version) - expected 1, got {0}", parsedVersion.Major));
            }

            OuterContainer outerContainer = new OuterContainer();

            string outerVersion = "1.0";

            outerContainer.Version       = outerVersion;
            outerContainer.KeyDerivation = new KeyDerivation();

            byte[] key;

            string derivationAlgorithm;

            try
            {
                derivationAlgorithm = outerContainerXml.SelectSingleNode("/OuterContainer/KeyDerivation/DerivationAlgorithm").InnerText;
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("invalid KeyDerivation DerivationAlgorithm: {0}", ex.Message));
            }

            outerContainer.KeyDerivation.DerivationAlgorithm = derivationAlgorithm;

            if (derivationAlgorithm == "PBKDF2")
            {
                string hashAlgorithm;

                try
                {
                    hashAlgorithm = outerContainerXml.SelectSingleNode("/OuterContainer/KeyDerivation/HashAlgorithm").InnerText;
                }
                catch (Exception ex)
                {
                    throw new Exception(string.Format("invalid KeyDerivation HashAlgorithm: {0}", ex.Message));
                }

                outerContainer.KeyDerivation.HashAlgorithm = hashAlgorithm;

                byte[] salt;

                try
                {
                    salt = Convert.FromBase64String(outerContainerXml.SelectSingleNode("/OuterContainer/KeyDerivation/Salt").InnerText);
                }
                catch (Exception ex)
                {
                    throw new Exception(string.Format("invalid KeyDerivation Salt: {0}", ex.Message));
                }

                outerContainer.KeyDerivation.Salt = salt;

                int iterationCount;

                try
                {
                    iterationCount = Convert.ToInt32(outerContainerXml.SelectSingleNode("/OuterContainer/KeyDerivation/IterationCount").InnerText);
                }
                catch (Exception ex)
                {
                    throw new Exception(string.Format("invalid KeyDerivation IterationCount: {0}", ex.Message));
                }

                outerContainer.KeyDerivation.IterationCount = iterationCount;

                int keyLength;

                try
                {
                    keyLength = Convert.ToInt32(outerContainerXml.SelectSingleNode("/OuterContainer/KeyDerivation/KeyLength").InnerText);
                }
                catch (Exception ex)
                {
                    throw new Exception(string.Format("invalid KeyDerivation KeyLength: {0}", ex.Message));
                }

                outerContainer.KeyDerivation.KeyLength = keyLength;

                key = Pbkdf2DeriveKeyFromPassword(password, salt, iterationCount, hashAlgorithm, keyLength);
            }
            else
            {
                throw new Exception(string.Format("unsupported KeyDerivation DerivationAlgorithm: {0}", derivationAlgorithm));
            }

            outerContainer.EncryptedDataPlaceholder = "placeholder";

            XmlElement encryptedDataElement = outerContainerXml.GetElementsByTagName("EncryptedData")[0] as XmlElement;

            if (encryptedDataElement == null)
            {
                throw new Exception("unable to find EncryptedData");
            }

            EncryptedData encryptedData = new EncryptedData();

            encryptedData.LoadXml(encryptedDataElement);

            EncryptedXml encryptedXml = new EncryptedXml();

            byte[] innerContainerBytes;

            using (AesCryptoServiceProvider aesCsp = new AesCryptoServiceProvider())
            {
                aesCsp.KeySize = 256;            // critical security parameter
                aesCsp.Key     = key;            // critical security parameter
                aesCsp.Mode    = CipherMode.CBC; // critical security parameter
                aesCsp.GenerateIV();             // critical security parameter

                try
                {
                    innerContainerBytes = encryptedXml.DecryptData(encryptedData, aesCsp);
                }
                catch (Exception ex)
                {
                    throw new Exception(string.Format("unable to decrypt InnerContainer (check password): {0}", ex.Message));
                }
            }

            XmlDocument innerContainerXml = new XmlDocument();

            try
            {
                innerContainerXml.LoadXml(Encoding.UTF8.GetString(innerContainerBytes));
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("unable to parse InnerContainer (check password): {0}", ex.Message));
            }

            string innerReadVersion;

            try
            {
                innerReadVersion = innerContainerXml.SelectSingleNode("/InnerContainer/@version").Value;
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("unable to read /InnerContainer/@version: {0}", ex.Message));
            }

            Version innerReadVersionParsed = new Version(innerReadVersion);

            if (innerReadVersionParsed.Major != 1)
            {
                throw new Exception(string.Format("inner container version too new (this container was written on a newer software version) - expected 1, got {0}", innerReadVersionParsed.Major));
            }

            InnerContainer innerContainer;

            using (XmlReader xmlReader = new XmlNodeReader(innerContainerXml))
            {
                try
                {
                    innerContainer = (InnerContainer) new XmlSerializer(typeof(InnerContainer)).Deserialize(xmlReader);
                }
                catch (Exception ex)
                {
                    throw new Exception(string.Format("unable to deserialize InnerContainer: {0}", ex.Message));
                }
            }

            return(outerContainer, innerContainer, key);
        }