我有一个基于MSDN文章http://msdn.microsoft.com/en-us/library/sb7w85t6.aspx
的XML加密例程我的代码在这里
public static void Encrypt(XmlDocument Doc, string ElementName, SymmetricAlgorithm Key)
{
////////////////////////////////////////////////
// Check the arguments.
////////////////////////////////////////////////
if (Doc == null || (Doc.ToString() == string.Empty))
throw new ArgumentNullException("The XML document was not given or it is empty");
if (ElementName == null || ElementName == string.Empty)
throw new ArgumentNullException("The XML element was not given or it is empty");
if (Key == null || Key.ToString() == string.Empty)
throw new ArgumentNullException("The encryption algorithm was not given or it is empty");
try
{
////////////////////////////////////////////////
// Find the specified element in the XmlDocument
// object and create a new XmlElemnt object.
////////////////////////////////////////////////
foreach (XmlElement elementToEncrypt in Doc.GetElementsByTagName("schema"))
{
//XmlElement elementToEncrypt = Doc.GetElementsByTagName("schema")[0] as XmlElement;
// Throw an XmlException if the element was not found.
if (elementToEncrypt == null || elementToEncrypt.ToString() == string.Empty)
{
throw new XmlException("The specified element was not found or it is empty");
}
//////////////////////////////////////////////////
// Create a new instance of the EncryptedXml class
// and use it to encrypt the XmlElement with the
// symmetric key.
//////////////////////////////////////////////////
EncryptedXml eXml = new EncryptedXml();
byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, Key, false);
////////////////////////////////////////////////
// Construct an EncryptedData object and populate
// it with the desired encryption information.
////////////////////////////////////////////////
EncryptedData edElement = new EncryptedData();
edElement.Type = EncryptedXml.XmlEncElementUrl;
////////////////////////////////////////////////
// Create an EncryptionMethod element so that the
// receiver knows which algorithm to use for decryption.
// Determine what kind of algorithm is being used and
// supply the appropriate URL to the EncryptionMethod element.
////////////////////////////////////////////////
string encryptionMethod = null;
if (Key is TripleDES)
{
encryptionMethod = EncryptedXml.XmlEncTripleDESUrl;
}
else if (Key is DES)
{
encryptionMethod = EncryptedXml.XmlEncDESUrl;
}
if (Key is Rijndael)
{
switch (Key.KeySize)
{
case 128:
encryptionMethod = EncryptedXml.XmlEncAES128Url;
break;
case 192:
encryptionMethod = EncryptedXml.XmlEncAES192Url;
break;
case 256:
encryptionMethod = EncryptedXml.XmlEncAES256Url;
break;
}
}
else
{
// Throw an exception if the transform is not in the previous categories
throw new CryptographicException("The specified algorithm is not supported for XML Encryption.");
}
edElement.EncryptionMethod = new EncryptionMethod(encryptionMethod);
////////////////////////////////////////////////
// Add the encrypted element data to the
// EncryptedData object.
////////////////////////////////////////////////
edElement.CipherData.CipherValue = encryptedElement;
////////////////////////////////////////////////////
// Replace the element from the original XmlDocument
// object with the EncryptedData element.
////////////////////////////////////////////////////
EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
}
}
catch (XmlException xexc)
{
throw new Exception(xexc.Message);
}
catch (Exception exc)
{
throw new XmlException("The XML document could not be used to encrypt the elements given: " + exc.Message);
}
finally
{
////////////////////////////////////////////////////
// Replace the XML file with the encrypted version
////////////////////////////////////////////////////
Doc.Save("testMIPS.config");
}
}
这适用于它找到的第一个“schema”元素,我可以看到显示已加密的第一个元素的Doc.XML字符串。
但是当循环遍历到所谓的加密下一个“schema”元素时,程序会抛出此异常...
“元素列表已更改。枚举操作无法继续。”
但我还没有真正保存过Doc.XML文件。
为什么会这样?
提前感谢您的时间。
答案 0 :(得分:0)
Doc.GetElementsByTagName("schema")
返回节点的迭代器,它也是一个惰性求值器。当更改XmlElement
迭代变为无效bcz时,您已经更改了迭代器正在工作的数据。尝试在GetElementsByTagName()
中添加List<XmlElement>
中的结果元素,然后枚举该列表并加密每个元素。
如果你有列表
,这很简单 List<int> n =new List<int>(new int{1,2,3});
//now if iterate it
foreach(int i in n){
n.Add(i)
}
循环正在更改其枚举的列表,因此它将给出类似于您的情况中给出的错误。您可以通过执行
来解决问题 foreach(int i in n.ToArray()){
n.Add(i)
}
因为在这种情况下,n的静止图像是在循环之前捕获的,我可以在循环内自由地改变它。当你枚举它时,你的循环在树上迭代。那不对,会给你例外。您必须首先收集要在List中更改的所有元素,然后枚举此列表并加密它们。这也将更新原始的xml文档。
答案 1 :(得分:0)
我遇到了同样的问题,并提出了以下代码。它对我有用。
的test.xml:
$mysql = mysqli_connect($host, $user, $password, $databaseName);
C#:
<root>
<creditcard id="1">
<number>19834209</number>
<expiry>02/02/2002</expiry>
</creditcard>
<creditcard id="2">
<number>34834210</number>
<expiry>03/03/2003</expiry>
</creditcard>
<creditcard id="3">
<number>34834211</number>
<expiry>04/04/2003</expiry>
</creditcard>
</root>