Программный модуль подготовки данных для РКС

advertisement
Приложение №5
к Правилам корпоративного электронного документооборота
«Личный кабинет. Клиент инфраструктуры обслуживания»
Программный модуль подготовки данных для РКС
Программный модуль подготовки данных для РКС представлен в виде исходного текста, предназначенного для
последующей компиляции (сборки) Исполняемого модуля подготовки данных для РКС (далее Модуль). Цель
представления Модуля в исходном виде – доказательство связи между выполняемыми Модулем операциями и
получаемым результатом.
Получение Модуля
1.
Модуль может быть получен путем компиляции исходного текста Программного модуля РКС Организатора с
использованием компилятора Microsoft C#, поставляемого в составе пакета Microsoft .NET Framework 2.0. Инструкция
по компиляции Программного модуля приводится в пункте 4 настоящего приложения.
1.1.
Условия выполнения Модуля
2.
Для выполнения Модуля и процедуры разбора конфликтной ситуации необходимо
работоспособный компьютер, удовлетворяющий следующим минимальным требованиям:
2.1.
2.2.
3.
3.1.
подготовить
2.1.1.
Процессор: Intel 512MHz;
2.1.2.
Объем оперативной памяти – 512МБ;
2.1.3.
Объем дискового пространства: 40ГБ;
2.1.4.
Порт USB 1.0;
2.1.5.
Клавиатура, Мышь.
2.1.6.
Операционная система: Microsoft Windows XP SP2 или Microsoft Windows 2003 Server Enterprise Edition SP2.
Для правильной работы модуля на компьютере должны быть установлены следующие программные продукты:
2.2.1.
Microsoft Internet Explorer версии 6.0;
2.2.2.
MSXML 6.0 Service Pack 1 (Microsoft XML Core Services);
2.2.3.
Microsoft .NET Framework 2.0.
Описание работы
Модуль применяется к одному файлу спорного документа.
В результате работы Модуля формируется (в формате HTML) файл «Перечень электронных цифровых
подписей формата XML-ЭЦП в спорном документе» (сохраняется в той же папке, что и спорный документ под
именем <файл спорного документа>-Signature.txt), и последовательность файлов (файл данных, файл ЭЦП и файл
сертификата, включенного в элемент XML-ЭЦП) для последующей передачи сертифицированному средству проверки
подлинности ЭЦП, формирующему отчеты о результате проверки согласно п.2.4.1.2 Приложения №6 Правил.
3.2.
В случае поступления на вход документа, не являющегося файлом формата XML, или файла с элементом XMLЭЦП без идентификатора (атрибут «Id» элемента Signature) Модуль создает запись в файле перечня элементов XMLЭЦП о нарушенной структуре файла спорного документа, и проверка ЭЦП в таком документе считается невозможной.
3.3.
4.
Инструкция по компиляции Модуля
Для получения Модуля следует использовать приводимую ниже схему:
4.1.
Сохранить Исходный текст в файл с именем FrsdExtractSign.cs;
4.2.
Выполнить в командной строке следующие команды, находясь в папке, где создан файл FrsdExtractSign.cs:
set cscompiler=<путь к компилятору Microsoft .NET Framework 2.0>
%cscompiler% /debug- /optimize+ /unsafe /out:FrsdExtractSign.exe FrsdExtractSign.cs
Здесь использованы следующие обозначения:
 <путь к компилятору Microsoft .NET Framework 2.0> – путь, указывающий на исполняемый модуль
компилятора языка C#, включенного в среду Microsoft .NET Framework 2.0.
1
Приложение №5
к Правилам корпоративного электронного документооборота
«Личный кабинет. Клиент инфраструктуры обслуживания»
Результатом работы компилятора является исполняемый модуль FrsdExtractSign.exe.
5.
Инструкция по выполнению Модуля
Для применения Модуля к спорному документу следует:
Скопировать файл спорного документа, имеющий имя, обозначаемое ниже <спорный документ>, в папку, где
создан Модуль FrsdExtractSign.exe;
5.1.
Применить Модуль FrsdExtractSign.exe к спорному документу, используя следующую инструкцию командной
строки (текущей папкой должна являться папка, где создан Модуль FrsdExtractSign.exe):
5.2.
FrsdExtractSign.exe <спорный документ>
6.
using
using
using
using
using
using
using
using
using
Исходный текст
System;
System.Collections;
System.Collections.Specialized;
System.IO;
System.Runtime.InteropServices;
System.Security.Cryptography;
System.Text;
System.Xml;
Frsd.Algorithms;
namespace Frsd
{
namespace Algorithms
{
/// <summary>
/// Приведение элемента XML-документа к стандартной текстовой форме.
/// </summary>
public class Alg_1_8_1
{
// ---// Вспомогательные методы
public const string XmlnsNs = "http://www.w3.org/2000/xmlns/";
public void CollectNamespaces(StringDictionary nsDict, XmlNode E)
{
CollectNamespacesForChild(nsDict, E);
}
public void CollectNamespacesForChild(StringDictionary nsDict, XmlNode E)
{
string ns = E.NamespaceURI;
nsDict[ns] = ns;
XmlAttributeCollection attributes = E.Attributes;
for (int k = 0; k < attributes.Count; ++k)
{
string nsURI1 = attributes[k].NamespaceURI;
if (nsURI1 != XmlnsNs)
nsDict[nsURI1] = nsURI1;
}
for (XmlNode node = E.FirstChild; node != null; node = node.NextSibling)
{
if (node.NodeType == XmlNodeType.Element)
{
CollectNamespaces(nsDict, node);
}
}
}
string EncodeAttribute(string attrValue)
{
string v = attrValue;
//
v = v.Replace("\"", """);
v = v.Replace("<", "<");
v = v.Replace(">", ">");
//
2
Приложение №5
к Правилам корпоративного электронного документооборота
«Личный кабинет. Клиент инфраструктуры обслуживания»
return v;
}
// ---// Преобразование к стандартной форме
public HashAlgorithm Hasher = null;
public Stream Output = null;
void AddBlock(byte[] data)
{
if (Hasher != null) Hasher.TransformBlock(data, 0, data.Length, data, 0);
if (Output != null) Output.Write(data, 0, data.Length);
}
void AddFinalBlock(byte[] data)
{
if (Hasher != null) Hasher.TransformFinalBlock(data, 0, data.Length);
if (Output != null) Output.Write(data, 0, data.Length);
}
public void Transform(XmlElement E)
{
StringDictionary nsDict = new StringDictionary();
CollectNamespaces(nsDict, E);
string[] nsArray = new string[nsDict.Keys.Count];
int j = 0;
foreach (DictionaryEntry pair in nsDict)
{
nsArray[j] = (string)pair.Value; ++j;
}
nsArray = new Alg_1_8_4().Sort(nsArray);
//
StringDictionary nsPrefixes = new StringDictionary();
for (j = 0; j < nsArray.Length; ++j)
{
nsPrefixes[nsArray[j]] = String.Format("ns{0}", j + 1);
}
//
TransformChild(E, nsPrefixes, nsDict, true);
}
public void TransformChild(XmlElement E,
StringDictionary nsPrefixes, StringDictionary nsDict,bool isRoot)
{
int i;
//
// Атрибуты
//
string ATTRIBUTES = "";
{
string[] attributes = new string[E.Attributes.Count];
int attrN = 0;
StringDictionary attrValues = new StringDictionary();
for (i = 0; i < E.Attributes.Count; ++i)
{
XmlAttribute A = E.Attributes[i];
string name = A.Name;
string localName = A.LocalName;
string nsURI = A.NamespaceURI;
if ((nsURI != XmlnsNs) &&
(!((localName == "xmlns") && (nsURI == ""))))
{
string nsPrefix = nsPrefixes[nsURI];
string attribute = nsPrefix + ":" + localName;
attributes[attrN] = attribute;
++attrN;
attrValues[attribute] = A.Value;
}
}
string[] a2 = new string[attrN];
for (i = 0; i < attrN; ++i) a2[i] = attributes[i];
attributes = new Alg_1_8_4().Sort(a2);
//
for (i = 0; i < attrN; ++i)
{
if (i > 0) ATTRIBUTES += " ";
3
Приложение №5
к Правилам корпоративного электронного документооборота
«Личный кабинет. Клиент инфраструктуры обслуживания»
string attribute = attributes[i];
string attrValue = attrValues[attribute];
ATTRIBUTES += attribute + "=\"" + EncodeAttribute(attrValue) + "\"";
}
//
attrValues.Clear();
}
//
string tagName = E.LocalName;
string EnsURI = E.NamespaceURI;
//
string head = "";
string tail = "";
//
if (isRoot)
{
string PR = "";
string[] nsArray = new string[nsPrefixes.Count];
int j = 0;
foreach (DictionaryEntry pair in nsPrefixes)
{
nsArray[j] = (string)pair.Key; ++j;
}
nsArray = new Alg_1_8_4().Sort(nsArray);
for (j = 0; j < nsArray.Length; ++j)
{
if (j > 0) PR += " ";
string ns = nsArray[j];
PR += "xmlns:" + nsPrefixes[ns] + "=\"" + nsDict[ns] + "\"";
}
//
string nsPrefix = nsPrefixes[EnsURI];
if (ATTRIBUTES == "")
{
head = "<" + nsPrefix + ":" + E.LocalName + " " + PR + ">";
tail = "</" + nsPrefix + ":" + E.LocalName + ">";
}
else
{
head = "<" + nsPrefix + ":" + E.LocalName + " " + PR + " " +
ATTRIBUTES + ">";
tail = "</" + nsPrefix + ":" + E.LocalName + ">";
}
}
else
{
string nsPrefix = nsPrefixes[EnsURI];
if (ATTRIBUTES == "")
{
head = "<" + nsPrefix + ":" + E.LocalName + ">";
tail = "</" + nsPrefix + ":" + E.LocalName + ">";
}
else
{
head = "<" + nsPrefix + ":" + E.LocalName + " " + ATTRIBUTES + ">";
tail = "</" + nsPrefix + ":" + E.LocalName + ">";
}
}
{
byte[] headData = Encoding.UTF8.GetBytes(head);
AddBlock(headData);
}
//
// Дочерние элементы и текстовые узлы
//
for (XmlNode node = E.FirstChild; node != null; node = node.NextSibling)
{
XmlNodeType nodeType = node.NodeType;
if (nodeType == XmlNodeType.Text)
{
string v1 = ((XmlText)node).Value;
v1 = v1.Trim();
string v2 = "";
for (int j = 0; j < v1.Length; ++j)
{
if ((UInt32)v1[j] > 15) v2 += new string(v1[j], 1);
}
{
4
Приложение №5
к Правилам корпоративного электронного документооборота
«Личный кабинет. Клиент инфраструктуры обслуживания»
byte[] textData;
textData = Encoding.UTF8.GetBytes(v2);
AddBlock(textData);
}
}
else if (nodeType == XmlNodeType.Element)
{
TransformChild((XmlElement)node, nsPrefixes, nsDict, false);
}
}
{
byte[] tailData;
tailData = Encoding.UTF8.GetBytes(tail);
if (isRoot)
{
AddFinalBlock(tailData);
}
else
{
AddBlock(tailData);
}
}
}
public byte[] TransformFile(string path)
{
XmlDocument doc = new XmlDocument();
doc.Load(path);
//
MemoryStream ms = new MemoryStream();
Output = ms;
Transform(doc.DocumentElement);
byte[] data = new byte[ms.Length];
ms.Position = 0;
ms.Read(data, 0, data.Length);
//
return data;
}
}
/// <summary>
/// Хеш-функция SHA1.
/// </summary>
public class Alg_1_8_2
{
public HashAlgorithm NewHashAlgorithm
{
get
{
SHA1 shaM = new SHA1Managed();
return shaM;
}
}
}
/// <summary>
/// Текстовая сортировка.
/// </summary>
public class Alg_1_8_4
{
public string[] Sort(string[] A)
{
string[] array = A;
//
for (int i = 0; i < array.Length-1; ++i)
{
string x = array[i];
//
// Находим минимальный элемент среди array[i+1],...,array[array.Length-1]
//
int min_k = i+1;
string m_y = array[i+1];
//
5
Приложение №5
к Правилам корпоративного электронного документооборота
«Личный кабинет. Клиент инфраструктуры обслуживания»
for (int k = i+2; k < array.Length; ++k)
{
if (LessThan(array[k],m_y))
{
min_k = k;
m_y = array[k];
}
}
//
if (LessThan(m_y,x))
{
array[i] = m_y;
array[min_k] = x;
}
}
//
return array;
}
public bool LessThan(string x,string y)
{
for (int i = 0; (i < x.Length) && (i < y.Length); ++i)
{
if (CharLessThan(x[i],y[i])) return true; // x < y
if (CharLessThan(y[i],x[i])) return false; // x > y
}
if (x.Length < y.Length) return true; // x < y
if (x.Length > y.Length) return false; // x > y
return false; // Строки x и y совпадают
}
public bool CharLessThan(char X,char Y)
{
string russianABC = RussianABC();
string latinABC = LatinABC();
string digits = Digits();
//
int Xclass = 0;
int Yclass = 0;
//
if (digits.IndexOf(X.ToString()) != -1) Xclass = 1;
if (latinABC.IndexOf(X.ToString()) != -1) Xclass = 2;
if (russianABC.IndexOf(X.ToString()) != -1) Xclass = 3;
//
if (digits.IndexOf(Y.ToString()) != -1) Yclass = 1;
if (latinABC.IndexOf(Y.ToString()) != -1) Yclass = 2;
if (russianABC.IndexOf(Y.ToString()) != -1) Yclass = 3;
//
if (Xclass < Yclass) return true; // X < Y
if (Xclass > Yclass) return false; // X > Y
//
if (Xclass == 1)
{
int Xpos = digits.IndexOf(X.ToString());
int Ypos = digits.IndexOf(Y.ToString());
return Xpos < Ypos;
}
else if (Xclass == 2)
{
int Xpos = latinABC.IndexOf(X.ToString());
int Ypos = latinABC.IndexOf(Y.ToString());
return Xpos < Ypos;
}
else if (Xclass == 2)
{
int Xpos = latinABC.IndexOf(X.ToString());
int Ypos = latinABC.IndexOf(Y.ToString());
return Xpos < Ypos;
}
else // (Xclass == 0)
{
long Xcode = (long)X;
long Ycode = (long)Y;
return Xcode < Ycode;
}
}
string RussianABC()
6
Приложение №5
к Правилам корпоративного электронного документооборота
«Личный кабинет. Клиент инфраструктуры обслуживания»
{
return "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯабвгдеёжзийклмнопрстуфхцчшщьыъэюя";
}
string LatinABC()
{
return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
}
string Digits()
{
return "0123456789";
}
}
/// <summary>
/// Подкотовка данных для РКС, связанной с проверкой элемента подписи XMLdsig.
/// </summary>
public class Alg_1_8_6
{
// ---// Анализ подписи XMLdsig
public enum Reason
{
SIGNATURE_OK = 0,
SIGNATURE_NOT_FOUND = 1,
BAD_SIGNATURE = 2
}
string PrepareResult(Reason reason,string description)
{
string mainResult = "";
//
if (reason == Reason.SIGNATURE_OK)
mainResult = "OK";
else if (reason == Reason.SIGNATURE_NOT_FOUND)
mainResult = "Не удалось обнаружить элемент подписи";
else if (reason == Reason.BAD_SIGNATURE)
mainResult = "Элемент подписи имеет неверный формат";
//
if (description != "" && mainResult != "OK")
mainResult += ": " + description;
//
return mainResult;
}
bool ReturnEmptyData(out byte[] data, out byte[] signature, out XmlElement extra)
{
data = new byte[0];
signature = new byte[0];
extra = null;
return false;
}
public unsafe bool AnalyzeExtractData(XmlElement Signature_E,
bool verify,
out byte[] certificate, out byte[] data, out byte[] signature,
out XmlElement extra, out string reason)
{
int k;
//
XmlNamespaceManager nsmgr =
new XmlNamespaceManager(Signature_E.OwnerDocument.NameTable);
nsmgr.AddNamespace("dsig", "http://www.w3.org/2000/09/xmldsig#");
//
// Идентификатор подписи
//
string Signature_Id = Signature_E.GetAttribute("Id");
string Signature_URI = "#" + Signature_Id;
//
XmlNodeList Property_L = Signature_E.SelectNodes("//dsig:SignatureProperty", nsmgr);
for (k = 0; k < Property_L.Count; ++k)
{
string uri = ((XmlElement)Property_L[k]).GetAttribute("Target");
if (uri != Signature_URI)
7
Приложение №5
к Правилам корпоративного электронного документооборота
«Личный кабинет. Клиент инфраструктуры обслуживания»
{
reason = "Ошибка в формате элемента подписи XMLdsig";
certificate = new byte[0];
return ReturnEmptyData(out data, out signature, out extra);
}
}
//
// Сертификат
//
certificate = System.Convert.FromBase64String(
Signature_E.SelectSingleNode("//dsig:X509Certificate", nsmgr).InnerText
);
//
// Дополнительные параметры подписи
//
extra = (XmlElement)Signature_E
.SelectSingleNode("dsig:Object/dsig:SignatureProperties", nsmgr);
//
// Проверяем узлы Refernce
//
XmlNodeList Reference_L = Signature_E
.SelectNodes("dsig:SignedInfo/dsig:Reference", nsmgr);
//
for (k = 0; k < Reference_L.Count; ++k)
{
XmlElement Reference_E = (XmlElement)Reference_L[k];
//
bool enveloped = false;
XmlNodeList Transform_L = Reference_E
.SelectNodes("dsig:Transforms/dsig:Transform", nsmgr);
for (int t_i = 0; t_i < Transform_L.Count; ++t_i)
{
string trAlgorithm = ((XmlElement)Transform_L[t_i])
.GetAttribute("Algorithm");
//
if (trAlgorithm == "http://www.w3.org/2000/09/xmldsig#enveloped-signature")
{
enveloped = true;
}
else
{
reason = "Неподдерживаемый алгоритм преобразования: " +
trAlgorithm.ToString();
return ReturnEmptyData(out data, out signature, out extra);
}
}
//
string uri = Reference_E.GetAttribute("URI");
if (!uri.StartsWith("#"))
{
reason = String.Format("Ошибка в URI: {0}", uri);
return ReturnEmptyData(out data, out signature, out extra);
}
string search = "";
if (uri.StartsWith("#xpointer"))
{
search = uri.Substring("#xpointer(".Length);
search = search.Substring(0, search.Length - 1);
}
else
{
string Id = uri.Substring(1, uri.Length - 1);
search = String.Format("//*[@Id='{0}']", Id);
}
XmlNodeList L = Signature_E.OwnerDocument.SelectNodes(search, nsmgr);
if (L.Count == 0)
{
reason = "Не найден элемент XPath='{" + search + "}' для Reference";
return ReturnEmptyData(out data, out signature, out extra);
}
if (L.Count > 1)
{
reason = "Найдено более одного элемента XPath='{" + search +
"}' для Reference";
return ReturnEmptyData(out data, out signature, out extra);
}
XmlElement E = (XmlElement)(L[0].Clone());
if (enveloped)
8
Приложение №5
к Правилам корпоративного электронного документооборота
«Личный кабинет. Клиент инфраструктуры обслуживания»
{
int j;
XmlNodeList child_L = E.SelectNodes("node()");
int tail = -1;
for (j = 0; j < child_L.Count; ++j)
{
XmlNode child = child_L[j];
if (child.NodeType == XmlNodeType.Element)
{
XmlElement child_E = (XmlElement)child;
if ((child_E.LocalName == "Signature") &&
(child_E.NamespaceURI == "http://www.w3.org/2000/09/xmldsig#"))
{
if (!child_E.HasAttribute("Id"))
{
reason = "Отсутствует атрибут Id у элемента Signature";
return ReturnEmptyData(out data, out signature, out extra);
}
if (child_E.GetAttribute("Id") == Signature_Id) tail = j;
}
}
}
if (tail != -1)
{
j = child_L.Count - 1;
while (j >= tail)
{
E.RemoveChild(child_L[j]);
--j;
}
}
}
//
Alg_1_8_1 alg = new Alg_1_8_1();
alg.Hasher = new Alg_1_8_2().NewHashAlgorithm;
alg.Transform(E);
string hash64 = Convert.ToBase64String(alg.Hasher.Hash).Trim();
//
XmlElement DigestValue_E =
(XmlElement)Reference_E.SelectSingleNode("dsig:DigestValue", nsmgr);
if (DigestValue_E.InnerText != hash64)
{
reason = "Хеш-код '" + DigestValue_E.InnerText + "' ошибочен";
return ReturnEmptyData(out data, out signature, out extra);
}
}
//
XmlElement SignatureValue_E =
(XmlElement)Signature_E.SelectSingleNode("dsig:SignatureValue", nsmgr);
//
signature = System.Convert.FromBase64String(
SignatureValue_E.InnerText
);
//
MemoryStream ms2 = new MemoryStream();
Alg_1_8_1 alg1 = new Alg_1_8_1();
alg1.Output = ms2;
alg1.Transform(
(XmlElement)Signature_E.SelectSingleNode("dsig:SignedInfo", nsmgr)
);
data = new byte[ms2.Length];
ms2.Position = 0;
ms2.Read(data, 0, data.Length);
//
string textToSign = System.Text.Encoding.UTF8.GetString(data);
//
reason = "Данные для проверки подлинности ЭЦП подготовлены";
return true;
}
public unsafe string PrepareForReferee(XmlDocument doc, string Signature_Id,
out DateTime t)
{
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("dsig", "http://www.w3.org/2000/09/xmldsig#");
nsmgr.AddNamespace("dse",
"http://cabinet.frsd.ru/schema/xmldsigext-frsd/rel-1/");
//
9
Приложение №5
к Правилам корпоративного электронного документооборота
«Личный кабинет. Клиент инфраструктуры обслуживания»
// Элемент подписи XMLdsig
//
Reason reason = Reason.SIGNATURE_OK;
//
string search = String.Format("//dsig:Signature[@Id='{0}']", Signature_Id);
XmlNodeList Signature_L = doc.SelectNodes(search, nsmgr);
if (Signature_L.Count == 0)
{
reason = Reason.SIGNATURE_NOT_FOUND;
}
if (Signature_L.Count > 1)
{
reason = Reason.SIGNATURE_NOT_FOUND;
}
if (reason != Reason.SIGNATURE_OK)
{
t = DateTime.Now;
return PrepareResult(reason,"");
}
//
// Анализируем обнаруженный элемент подписи XMLdsig
//
XmlElement Signature_E = (XmlElement)Signature_L[0];
//
byte[] certificate;
byte[] data;
byte[] signature;
XmlElement extra;
string r1;
//
bool result = false;
try
{
result = AnalyzeExtractData(Signature_E,
false, // не проверяем, передаем АРМ РКС
out certificate, out data, out signature, out extra, out r1);
//
if (!result)
{
t = DateTime.Now;
return PrepareResult(Reason.BAD_SIGNATURE, "");
}
}
catch (Exception e)
{
t = DateTime.Now;
return PrepareResult(Reason.BAD_SIGNATURE, e.ToString());
}
//
string signaturePath = Signature_Id;
if (!Directory.Exists(signaturePath)) Directory.CreateDirectory(signaturePath);
//
FileStream writer;
string path;
//
// Записываем сертификат
//
path = signaturePath + "\\author.cer";
writer = File.Open(path,FileMode.Create,FileAccess.Write);
writer.Write(certificate,0,(int)certificate.Length);
writer.Close();
//
// Записываем данные
//
path = signaturePath + "\\signed.data";
writer = File.Open(path,FileMode.Create,FileAccess.Write);
writer.Write(data,0,(int)data.Length);
writer.Close();
//
// Записываем подпись
//
path = signaturePath + "\\cms.sign";
writer = File.Open(path,FileMode.Create,FileAccess.Write);
writer.Write(signature,0,(int)signature.Length);
writer.Close();
//
string datetime_s =
((XmlElement)extra
10
Приложение №5
к Правилам корпоративного электронного документооборота
«Личный кабинет. Клиент инфраструктуры обслуживания»
.SelectSingleNode("dsig:SignatureProperty/dse:Events", nsmgr))
.GetAttribute("SignatureTime");
year = System.Convert.ToInt32(datetime_s.Substring(0,4), 10);
month = System.Convert.ToInt32(datetime_s.Substring(5, 2), 10);
day = System.Convert.ToInt32(datetime_s.Substring(8, 2), 10);
hour = System.Convert.ToInt32(datetime_s.Substring(11, 2), 10);
minute = System.Convert.ToInt32(datetime_s.Substring(14, 2), 10);
second = System.Convert.ToInt32(datetime_s.Substring(17, 2), 10);
new DateTime(year,month,day,hour,minute,second,0);
int
int
int
int
int
int
t =
//
return PrepareResult(reason,"");
}
}
/// <summary>
/// Подготовка данных для РКС, связанной с проверкой ЭЦП в спорном документе.
/// </summary>
public class Alg_1_8_7
{
public enum Reason
{
SIGNATURES_OK = 0,
BAD_SIGNATURE_FOUND = 1,
CORRUPTED_SIGNATURE_FOUND = 2,
BAD_XML = 3
}
// ---// Вспомогательные методы
static XmlDocument CurrentDoc;
static XmlNamespaceManager NsMgr
{
get
{
if (m_NsMgr == null)
{
m_NsMgr = new XmlNamespaceManager(CurrentDoc.NameTable);
m_NsMgr.AddNamespace("dsig", "http://www.w3.org/2000/09/xmldsig#");
}
return m_NsMgr;
}
}
static XmlNamespaceManager m_NsMgr;
StringDictionary Signature_Ids = new StringDictionary();
const string tab = "
";
public string PrepareReport(Reason commonReason,
StringDictionary results, StringDictionary times, string docPath)
{
string report;
//
// Элементы подписи
//
string signatureElementsPartH = "Элементы XML-ЭЦП:\n";
string signatureElementsPart = signatureElementsPartH;
//
if (commonReason == Reason.SIGNATURES_OK)
{
foreach (DictionaryEntry pair in results)
{
string Signature_Id = Signature_Ids[(string)pair.Key];
string t_s = times[Signature_Id];
//
string signaturePath = Path.GetFullPath(Signature_Id);
//
signatureElementsPart +=
tab + "Элемент XML-ЭЦП " + Signature_Id + "\n" +
tab + tab + "Время создания: " + t_s + " UTC\n" +
tab + tab + tab + "Файл подписи: " + signaturePath + "\\cms.sign\n" +
tab + tab + tab + "Файл данных: " + signaturePath + "\\signed.data\n" +
tab + tab + tab + "Файл сертификата: " +
11
Приложение №5
к Правилам корпоративного электронного документооборота
«Личный кабинет. Клиент инфраструктуры обслуживания»
signaturePath + "\\author.cer\n" +
tab + tab + tab + "Файл сертификата Удостоверяющего центра: " +
signaturePath + "\\ca.cer\n" +
tab + tab + tab + "Файл списка отозванных сертификатов: " +
signaturePath + "\\cacrl.crl\n";
}
//
if (signatureElementsPart == signatureElementsPartH)
{
signatureElementsPart = tab + "Элементы XML-ЭЦП не обнаружены\n";
}
}
else
{
signatureElementsPart = "";
}
//
// Файл документа
//
string docFileName = Path.GetFileName(docPath);
string docName = Path.GetFileNameWithoutExtension(docPath);
string docFullPath = Path.GetFullPath(docFileName);
string reportFileName = docName + "-Signatures.txt";
//
// Файл перечня подписей формата XMLdsig
//
string mainResult = "";
if (commonReason == Reason.SIGNATURES_OK)
mainResult = "";
else if (commonReason == Reason.BAD_SIGNATURE_FOUND)
mainResult = "Обнаружен элемент подписи неверного формата";
else if (commonReason == Reason.BAD_XML)
mainResult = "Структура документа нарушена";
//
string time_s = System.DateTime.Now.ToString("dd.MM.yyyy, HH:mm:ss");
report = @"
Перечень электронных цифровых подписей формата XML-ЭЦП
в спорном документе
Время создания перечня: " + time_s + @"
Спорный документ: " + docFullPath + @"
" + mainResult + @"
" + signatureElementsPart + @"
";
//
FileStream writer =
File.Open(reportFileName,FileMode.Create,FileAccess.Write);
byte[] reportText = Encoding.GetEncoding("windows-1251").GetBytes(report);
writer.Write(reportText,0,(int)reportText.Length);
writer.Close();
//
return report;
}
// ---// Подготовка спорного документа для РКС
public string AnalyzeSignatures(XmlDocument doc,string docPath)
{
CurrentDoc = doc;
//
StringDictionary results = new StringDictionary();
StringDictionary times = new StringDictionary();
//
// Перебираем элементы подписи XMLdsig
//
XmlNodeList Signature_L = doc.SelectNodes("//dsig:Signature",NsMgr);
//
for (int k = 0; k < Signature_L.Count; ++k)
{
// Анализируем элемент подписи XMLdsig
//
XmlElement Signature_E = (XmlElement)Signature_L[0];
if (! Signature_E.HasAttribute("Id"))
{
return PrepareReport(Reason.BAD_SIGNATURE_FOUND,
results, times, docPath);
}
12
Приложение №5
к Правилам корпоративного электронного документооборота
«Личный кабинет. Клиент инфраструктуры обслуживания»
string Signature_Id = Signature_E.GetAttribute("Id");
//
DateTime t;
//
string result = "";
try
{
result = new Alg_1_8_6().PrepareForReferee(doc, Signature_Id, out t);
//
if (result == "OK")
times[Signature_Id] = t.ToString("dd.MM.yyyy, HH:mm:ss");
else
times[Signature_Id] = "";
}
catch (Exception e)
{
result = "Элемент подпись имеет неверный формат: " + e.ToString();
//
times[Signature_Id] = "";
}
//
results[Signature_Id] = result;
Signature_Ids[Signature_Id] = Signature_Id;
}
//
return PrepareReport(Reason.SIGNATURES_OK, results, times, docPath);
}
public string AnalyzeFileSignatures(string docPath)
{
XmlDocument doc = new XmlDocument();
try
{
doc.Load(docPath);
}
catch (Exception)
{
return PrepareReport(Reason.BAD_XML, null, null, "");
}
//
return AnalyzeSignatures(doc, docPath);
}
}
}
}
namespace FrsdConflict
{
class FrsdConflictApp
{
public static void Main(string[] args)
{
string path = args[0];
//
new Alg_1_8_7().AnalyzeFileSignatures(path);
}
}
}
13
Download