Open artur-tolstenco opened 6 years ago
here some further investigation. on the left side the 2017 project version on the right side the 2016 project version:
the ssis 2017 project version has a SSIS:Algorithm but the 2016 does not!
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;
}
}
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.