Я пытаюсь прочитать подписанное содержимое XML-файла, подписанного несколько раз.
Я написал этот код для чтения подписанного содержимого, и оно работает, если файл подписан один раз:
public static MyType LoadFromSignedFile(string fileName)
{
using (FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
CmsSignedData signedFile = new CmsSignedData(fileStream);
XmlSerializer serializer = new XmlSerializer(typeof(MyType));
using (MemoryStream memStream = new MemoryStream())
{
signedFile.SignedContent.Write(memStream);
memStream.Position = 0;
using (StreamReader sr = new StreamReader(memStream))
return serializer.Deserialize(sr) as MyType;
}
}
}
Десериализация выдаст ошибку, если файл подписан два или более раз (ошибка в документе XML (1,1)), это нормально, потому что SignedContent содержит другую подпись с другим SignedContent.
Я пытаюсь перебирать подписывающих (с помощью GetSigners ()), чтобы читать подписанное содержимое в каждом цикле, но GetSigners () возвращает 1, даже если файл подписан дважды.
Десериализация идетхорошо, если все сделано «вручную», например:
Stream st = parser.GetSignedContent().ContentStream;
CmsSignedDataParser p = new CmsSignedDataParser(st);
Stream st2 = p.GetSignedContent().ContentStream;
using (StreamReader sr = new StreamReader(st2))
return serializer.Deserialize(sr) as MyType;
Итак, вот мой плохой прототип решения, использующий объект DataParser:
public static MyType LoadInvoiceFromSignedFile(string fileName)
{
using (FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
CmsSignedDataParser parser = new CmsSignedDataParser(fileStream);
XmlSerializer serializer = new XmlSerializer(typeof(MyType));
CmsSignedData data = new CmsSignedData(new FileStream(fileName, FileMode.Open, FileAccess.Read));
Stream internalStream = null;
// --> try to deserialize the XML hoping there is only 1 signature
bool isError = false;
try
{
using (MemoryStream memStream = new MemoryStream())
{
CmsSignedData signedFile = new CmsSignedData(new FileStream(fileName, FileMode.Open, FileAccess.Read));
signedFile.SignedContent.Write(memStream);
memStream.Position = 0;
using (StreamReader sr = new StreamReader(memStream))
return serializer.Deserialize(sr) as MyType;
}
}catch(Exception ex)
{
isError = true;
}
// <--
// --> signed multiple times, trying with a loop
if (isError)
{
for (int i = 0; i < data.GetSignerInfos().GetSigners().Count; i++)
{
internalStream = parser.GetSignedContent().ContentStream;
try
{
parser = new CmsSignedDataParser(internalStream);
}
catch (Exception ex)
{
using (MemoryStream memStream = new MemoryStream())
{
CmsSignedData signedFile = new CmsSignedData(new FileStream(fileName, FileMode.Open, FileAccess.Read));
signedFile.SignedContent.Write(memStream);
memStream.Position = 0;
using (StreamReader sr = new StreamReader(memStream))
return serializer.Deserialize(sr) as MyType;
}
}
}
using (StreamReader sr = new StreamReader(parser.GetSignedContent().ContentStream))
return serializer.Deserialize(sr) as MyType;
}
// <--
return null;
}
}
CmsTypeStream
не поддерживает seek
ни position
поэтому я не могу определить конец потока (также не очень хорошо знаю потоки, это одна из причин плохого кода).