Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSIS 2017 are not supported when EncryptSensitiveWithPassword #25

Open
artur-tolstenco opened this issue May 4, 2018 · 2 comments
Open

Comments

@artur-tolstenco
Copy link

artur-tolstenco commented May 4, 2018

this is the error when I try to build a SSIS 2017 project with EncryptSensitiveWithPassword Protection Level:

PS C:\Users\Administrator> . $ssisbuild $prj -Configuration "Development" -Password "aaa"
SSIS Build Engine
Copyright (c) 2017 Roman Tumaykin

Executing SSIS Build with the following arguments:
Project File: c:\Users\administrator\source\repos\SSIS\SSIS\SSIS.dtproj
-Password: (hidden)
-Configuration: Development

Project parameters:
Starting build. Loading project files from c:\Users\administrator\source\repos\SSIS\SSIS\SSIS.dtproj.
ERROR: Specified initialization vector (IV) does not match the block size for this algorithm.

@artur-tolstenco
Copy link
Author

here some further investigation. on the left side the 2017 project version on the right side the 2016 project version:
image

the ssis 2017 project version has a SSIS:Algorithm but the 2016 does not!

@e2patrick
Copy link

The problem is that Visual Studio changed the encryption algorithm from TripleDES to AES256-CBC with Version 2017. I changed the encryption and decryption methods to this and it worked for my VS 2017 projects:

protected virtual void EncryptElement(XmlElement element, string password)
{
if (password == null)
throw new InvalidPaswordException();
var rgbSalt = new byte[8];
new RNGCryptoServiceProvider().GetBytes(rgbSalt);
var document = element.GetDocument();

        using (MemoryStream ms = new MemoryStream())
        {
            using (RijndaelManaged AES = new RijndaelManaged())
            {
                AES.KeySize = 256;
                AES.BlockSize = 128;

                var key = new Rfc2898DeriveBytes(password, rgbSalt, 1000);
                AES.Key = key.GetBytes(AES.KeySize / 8);
                AES.IV = key.GetBytes(AES.BlockSize / 8);
                //AES.Padding = PaddingMode.None;
                AES.Mode = CipherMode.CBC;

                using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    using (StreamWriter sw = new StreamWriter(cs))
                        sw.Write(element.OuterXml);

                }
                var array = ms.ToArray();
                foreach (XmlNode childNode in element.ChildNodes)
                    element.RemoveChild(childNode);
                element.InnerText = Convert.ToBase64String(array);
                var saltAttribute = document.CreateAttribute("Salt", XmlHelpers.Schemas.SSIS);
                saltAttribute.Value = Convert.ToBase64String(rgbSalt);
                element.SetAttribute("Salt", XmlHelpers.Schemas.SSIS, Convert.ToBase64String(rgbSalt));
                element.SetAttribute("IV", XmlHelpers.Schemas.SSIS, Convert.ToBase64String(AES.IV));
            }
        }
    }

protected virtual void DecryptElement(XmlElement element, string password)
{
var algXmlAttributeNode = XmlHelpers.GetAttributeNode(element, "Algorithm");
if (!string.IsNullOrEmpty(algXmlAttributeNode?.Value))
{

            var saltXmlAttributeNode = XmlHelpers.GetAttributeNode(element, "Salt");
            if (string.IsNullOrEmpty(saltXmlAttributeNode?.Value))
            {
                throw new InvalidXmlException($"Encrypted element {element.Name} does not contain required Attribute \"Salt\", or its contents is empty", element);
            }
            byte[] rgbSalt;
            try
            {
                rgbSalt = Convert.FromBase64String(saltXmlAttributeNode.Value);
            }
            catch (FormatException)
            {
                throw new InvalidXmlException($"Invalid value of Attribute \"Salt\" ({saltXmlAttributeNode.Value}) in encrypted element {element.Name}", element);
            }
            var ivXmlAttributeNode = XmlHelpers.GetAttributeNode(element, "IV");
            if (string.IsNullOrEmpty(ivXmlAttributeNode?.Value))
            {
                throw new InvalidXmlException($"Encrypted element {element.Name} does not contain required Attribute \"IV\", or its contents is empty", element);
            }
            byte[] iv;
            try
            {
                iv = Convert.FromBase64String(ivXmlAttributeNode.Value);
            }
            catch (FormatException)
            {
                throw new InvalidXmlException($"Invalid value of Attribute \"IV\" ({ivXmlAttributeNode.Value}) in encrypted element {element.Name} ", element);
            }
            string xml;
            byte[] buffer;
            try
            {
                buffer = Convert.FromBase64String(element.InnerText);
            }
            catch (FormatException)
            {
                throw new InvalidXmlException($"Invalid value of encrypted element {element.Name}.", element);
            }
            try
            {
                using (MemoryStream ms = new MemoryStream(buffer))
                {
                    using (RijndaelManaged AES = new RijndaelManaged())
                    {
                        AES.KeySize = 256;
                        AES.BlockSize = 128;

                        var key = new Rfc2898DeriveBytes(password, rgbSalt, 1000);
                        AES.Key = key.GetBytes(AES.KeySize / 8);
                        AES.IV = iv;

                        AES.Mode = CipherMode.CBC;
                        using (CryptoStream csDecrypt = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Read))
                        {
                            using (StreamReader srDecrypt = new StreamReader(csDecrypt))

                                // Read the decrypted bytes from the decrypting stream
                                // and place them in a string.
                                xml = srDecrypt.ReadToEnd();
                        }

                    }
                }
            }

            catch (CryptographicException)
            {
                throw new InvalidPaswordException();
            }

            var xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(xml);

            // The reason to not simply import the new node is because namespace declaration will also be imported with the node.
            element.Attributes.Remove(saltXmlAttributeNode);
            element.Attributes.Remove(ivXmlAttributeNode);

            foreach (XmlNode childNode in element.ChildNodes)
                element.RemoveChild(childNode);
            element.InnerXml = xmlDocument.DocumentElement?.InnerXml;
        }
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants