Чтение подписанного содержимого XML-файла, подписанного несколько раз (.xml.p7m.p7m) с помощью BouncyCastle (в том числе и плохой прототип решения) - PullRequest
0 голосов
/ 30 января 2019

Я пытаюсь прочитать подписанное содержимое 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 поэтому я не могу определить конец потока (также не очень хорошо знаю потоки, это одна из причин плохого кода).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...