C# 如何使用特殊字符对XML文件进行签名?
我必须对XML进行签名,这将返回错误“无效CAF签名”。(CAF=Código Autorización de Folios) 我有一个XML文件:C# 如何使用特殊字符对XML文件进行签名?,c#,.net,xml,C#,.net,Xml,我必须对XML进行签名,这将返回错误“无效CAF签名”。(CAF=Código Autorización de Folios) 我有一个XML文件: <?xml version="1.0"?> <AUTORIZACION> <CAF version="1.0"> <DA> <RE>76521854-3</RE> <RS>SOCIEDAD FARMACEUTICA O"HIGGINS SPA<
<?xml version="1.0"?>
<AUTORIZACION>
<CAF version="1.0">
<DA>
<RE>76521854-3</RE>
<RS>SOCIEDAD FARMACEUTICA O"HIGGINS SPA</RS>
<TD>33</TD>
<RNG><D>101</D><H>200</H></RNG>
<FA>2020-05-28</FA>
<RSAPK><M>t6ldOQd1Mz+1tiYhaMvVCKeAyT2vQK4rqYCHtbMDWIAHBGwI3mr1mmgLUpXKfvisRl1pTY2RXWdZVd6vE12PSw==</M><E>Aw==</E></RSAPK>
<IDK>100</IDK>
</DA>
<FRMA algoritmo="SHA1withRSA">UQ85YCoqC+pBw7kjzU0g+0uufqKKg759DapDJP4Bt4LMk1mK4330cgBPpVh/iUo5oC9TxINqo0icwFYiAabskw==</FRMA>
</CAF>
<RSASK>-----BEGIN RSA PRIVATE KEY-----
MIIBOQIBAAJBALepXTkHdTM/tbYmIWjL1QingMk9r0CuK6mAh7WzA1iABwRsCN5q
9ZpoC1KVyn74rEZdaU2NkV1nWVXerxNdj0sCAQMCQHpw6NCvo3d/znluwPCH41sa
Vdt+dNXJcnEAWnkiAjr+4v/O/o8lhCUGHFaf/0B+1jp2kTnb7b/A4qrd9fxFs7sC
IQDm1L63s29TnXKNkSrlDPGRuqBa0IsmFoXM82Xp0aVhfwIhAMuv9tNUQ1vFbFM/
euaRSNk0CzSmOIanQDhiK9RHT6A1AiEAmeMpz8z04mj3CQtx7gihC9HAPIsHbrmu
iKJD8TZuQP8CIQCHyqSM4teSg52M1PyZtjCQzVzNxCWvGirQQXKNhN/AIwIgXDO7
2/zf8L8fGm6nrDl56Oiybnq0PIg67W4FJ3NBXxI=
-----END RSA PRIVATE KEY-----
</RSASK>
<RSAPUBK>-----BEGIN PUBLIC KEY-----
MFowDQYJKoZIhvcNAQEBBQADSQAwRgJBALepXTkHdTM/tbYmIWjL1QingMk9r0Cu
K6mAh7WzA1iABwRsCN5q9ZpoC1KVyn74rEZdaU2NkV1nWVXerxNdj0sCAQM=
-----END PUBLIC KEY-----
</RSAPUBK>
</AUTORIZACION>
对于反序列化,我将此方法与C#结合使用:
通过以下方式序列化TED对象时,将生成此XML文件:
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Encoding.GetEncoding("ISO-8859-1");
settings.Indent = true;
settings.IndentChars = "";
settings.OmitXmlDeclaration = false;
using (XmlWriter xmlWriter = XmlWriter.Create(tempFilePath, settings))
{
XmlSerializer s = new XmlSerializer(obj.GetType());
s.Serialize(xmlWriter, obj, ns);
}
但是,
标记是用\“
而不是”
编写的,我认为这种转换是错误的原因
未成功采取的行动:
\“
替换为”
。直接使用string.Replace()
或SecurityElement.Escape()
,即使我仍然收到此错误。有时(根据所做的替换),我会得到SOCIEDAD FARMACEUTICA O&;引用;希金斯水疗中心
“
字符被替换为\”
要签署的代码:
XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;
doc.Load(filePath); //path where is the XML file. This XML has " instead of \"
SignedXml signedXml = new SignedXml(doc);
signedXml.SigningKey = certificado.PrivateKey;
Signature XMLSignature = signedXml.Signature;
Reference reference = new Reference();
reference.Uri = "#" + referenceID;
XmlDsigC14NTransform t = new XmlDsigC14NTransform();
reference.AddTransform(t);
XMLSignature.SignedInfo.AddReference(reference);
KeyInfo keyInfo = new KeyInfo();
keyInfo.AddClause(new RSAKeyValue((RSA)certificado.PrivateKey));
keyInfo.AddClause(new KeyInfoX509Data(certificado));
XMLSignature.KeyInfo = keyInfo;
signedXml.ComputeSignature();
XmlElement xmlDigitalSignature = signedXml.GetXml();
doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, true));
doc.Save(filePath); //filepath is overwritten with \" instead of "
如何在C中保留“
而不是\”
对该文件进行签名 而不是
using (XmlWriter xmlWriter = XmlWriter.Create(tempFilePath, settings))
{
XmlSerializer s = new XmlSerializer(obj.GetType());
s.Serialize(xmlWriter, obj, ns);
}
您需要将现有的XmlWriter封装到自己的XmlWriter中,以更改“
和”
的序列化,从而使用实体引用“
和&apos代码>:
using (EscapeQuotesXmlWriter exw = new EscapeQuotesXmlWriter(XmlWriter.Create(tempFilePath, settings)))
{
XmlSerializer s = new XmlSerializer(obj.GetType());
s.Serialize(exw , obj, ns);
}
该类可以实现为XmlWrappingWriter
public class EscapeQuotesXmlWriter : XmlWrappingWriter
{
public EscapeQuotesXmlWriter(XmlWriter baseWriter) : base(baseWriter)
{
}
public override void WriteString(string text)
{
foreach (char ch in text)
{
if (ch == '"')
{
WriteEntityRef("quot");
}
else if (ch == '\'')
{
WriteEntityRef("apos");
}
else
{
base.WriteString(ch.ToString());
}
}
}
public override void WriteChars(char[] buffer, int index, int count)
{
WriteString(new String(buffer.Where((ch, pos) => pos >= index && pos < index + count).ToArray()));
}
}
我想您应该需要格式。在.NET framework API的上下文中,如果您确实需要确保元素数据中的双引号字符“
由实体引用表示”
我认为您需要使用自己的XmlWriter实现,以确保它不会写出“
按字面意思,但作为”
使用。序列化时为什么要使用编码?不需要。xml是UTF-8,不会更改任何字符(0x80除外)。使用ISO-8859-1将修改字符。要使代码正常工作,必须与创建文件时的操作相反。因此,请使用XmlReaderSettings=new XmlReaderSettings();settings.Encoding=Encoding.GetEncoding(“ISO-8859-1”);XmlReader reader=XmlReader.Create(文件名,设置)“我必须对XML进行签名,并且返回错误“无效CAF符号”的部分是否已使用.NET代码完成?能否显示该代码?@MartinHonnen我将尝试您的链接,谢谢。我收到错误“无效CAF符号”“当我将此XML发送给政府机构时,他们会通过电子邮件回复我。谢谢。太棒了,这适用于序列化!但是当我对XML签名时,字符被替换。我的问题已更新。@GonzaloBustamante,Save
方法是另一种序列化,在这种序列化中,正常的.NET框架不使用实体引用来表示元素中的双引号或单引号,因为它们是不需要的,但您当然也可以在其中使用“EscapeQuotesXmlWriter”。
using (XmlWriter xmlWriter = XmlWriter.Create(tempFilePath, settings))
{
XmlSerializer s = new XmlSerializer(obj.GetType());
s.Serialize(xmlWriter, obj, ns);
}
using (EscapeQuotesXmlWriter exw = new EscapeQuotesXmlWriter(XmlWriter.Create(tempFilePath, settings)))
{
XmlSerializer s = new XmlSerializer(obj.GetType());
s.Serialize(exw , obj, ns);
}
public class EscapeQuotesXmlWriter : XmlWrappingWriter
{
public EscapeQuotesXmlWriter(XmlWriter baseWriter) : base(baseWriter)
{
}
public override void WriteString(string text)
{
foreach (char ch in text)
{
if (ch == '"')
{
WriteEntityRef("quot");
}
else if (ch == '\'')
{
WriteEntityRef("apos");
}
else
{
base.WriteString(ch.ToString());
}
}
}
public override void WriteChars(char[] buffer, int index, int count)
{
WriteString(new String(buffer.Where((ch, pos) => pos >= index && pos < index + count).ToArray()));
}
}
using (EscapeQuotesXmlWriter exw = new EscapeQuotesXmlWriter(XmlWriter.Create(filePath)))
{
doc.Save(exw);
}