/// <summary> /// Отсылает файл по пути /// </summary> /// <param name="filename">Путь файла</param> /// <returns>Путь файла-ответа</returns> private string sendXml(string filename) { if (externalFileEncryption) // Если задан флаг внешнего шифрования - грузим файл. { OpenFileDialog ofd = new OpenFileDialog(); ofd.InitialDirectory = Path.GetTempPath(); ofd.Filter = "*.xml|*.xml"; string f = null; while (f == null) { ofd.ShowDialog(); f = ofd.FileName; } filename = f; } if (!File.Exists(filename)) { throw new Exception("Шаг 4. Файл не найден!\r\nПуть:" + filename); } string filename4 = filename + ".getted.xml"; try { // Создаем и обрабатываем обычный http запрос метод POST HttpWebRequest request = (HttpWebRequest)WebRequest.Create((TEST) ? UrlTest : Url); request.ContentType = "text/xml;charset=utf-8"; request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.79 Safari/537.36"; request.Method = "POST"; string postData = File.ReadAllText(filename); // Пишем файл прямо в тело запроса request.GetRequestStream().Write(Encoding.UTF8.GetBytes(postData), 0, postData.Length); // Получаем ответ. Тут может вывалиться исключение при отстутствии соединения с серверами ФСС WebResponse response = request.GetResponse(); // Получаем тело ответа XmlDocument getted = new XmlDocument(); getted.Load(response.GetResponseStream()); // Сохраняем getted.Save(filename4); // Отображаем файл если требуется для дебага if (DEBUG_STEP < 4) { foView view = new foView(); view.Text = filename4; view.xmlFileName = filename4; view.Show(); } } catch (Exception ex) { MessageBox.Show("GetElnList", "Возникла ошибка в функции sendXml:\r\n" + ex.Message); } return(filename4); }
/// <summary> /// Создает заполненный XML-файл в папке tempFolder из ресурса Source1 /// </summary> /// <param name="ds">DataSet объект, который надо ввести в файл</param> /// <returns>Путь созданного файла</returns> private string createXml(DataSet ds) { if (!Directory.Exists(tempFolder)) // Если нет директории { // Спрашиваем "хотим ли создать ее?" if (MessageBox.Show("GetElnList", "Директория \"" + tempFolder + "\" отсутствует. Создать?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { Directory.CreateDirectory(tempFolder); // Создаем } else { throw new Exception("Шаг 1. Требуемая папка отсутствует."); // Либо выбиваем исключение } } string filename1 = tempFolder + "FSS_" + DateTime.Now.Ticks.ToString() + ".xml"; // Создаем временный файл // Создаем xml из ресурса XmlDocument document = new XmlDocument(); document.LoadXml(Properties.Resources.Source1.Replace("{OGRN}", ds.regNum)); // Заполняем его if (TEST) { // Если выставлен флаг теста document.DocumentElement.GetElementsByTagName("fil:regNum").Item(0).InnerText = ds.regNum; document.DocumentElement.GetElementsByTagName("fil:lnCode").Item(0).InnerText = "306767144098"; document.DocumentElement.GetElementsByTagName("fil:snils").Item(0).InnerText = "00000000001"; } else { // Флаг теста не выставлен, обращаемся к ФСС напрямую document.DocumentElement.GetElementsByTagName("fil:regNum").Item(0).InnerText = ds.regNum; document.DocumentElement.GetElementsByTagName("fil:lnCode").Item(0).InnerText = ds.lnCode; document.DocumentElement.GetElementsByTagName("fil:snils").Item(0).InnerText = ds.snils; } // Сохраняем документ в файле document.Save(filename1); // Отображаем файл если требуется дебаг if (DEBUG_STEP < 1) { foView view = new foView(); // Создаем форму просмотра view.Text = filename1; // Говорим что выводить в шапке view.xmlFileName = filename1; // Что потребуется загрузить view.Show(); // Показываем } return(filename1); // Возвращаем имя созданного файла }
/// <summary> /// Расшифровывает ответ ФСС по пути /// </summary> /// <param name="filename">Путь к зашифрованному файлу</param> /// <returns>Путь к расшифрованному файлу</returns> public string decryptResponse(string filename) { if (!File.Exists(filename)) { throw new Exception("Шаг 5. Файл не найден!\r\nПуть:" + filename); } string filename5 = filename + ".decrypted.xml"; // Создаем объект XmlDocument. XmlDocument xmlDoc = new XmlDocument(); // Загружаем XML файл в объект XmlDocument. xmlDoc.PreserveWhitespace = true; xmlDoc.Load(filename); // Ищем все зашифрованные данные. XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable); nsmgr.AddNamespace("xenc", "http://www.w3.org/2001/04/xmlenc#"); XmlNodeList list = xmlDoc.SelectNodes("//xenc:EncryptedData", nsmgr); // Создаем объект EncryptedXml. EncryptedXml exml = new EncryptedXml(xmlDoc); if (list != null) { // Для всех зашифрованных данных. foreach (XmlNode node in list) { XmlElement element = node as XmlElement; EncryptedData encryptedData = new EncryptedData(); encryptedData.LoadXml(element); // Находим подходящий ключ для расшифрования. SymmetricAlgorithm decryptionKey = GetDecryptionKey(exml, encryptedData); if (decryptionKey == null) { throw new Exception("Ключ для расшифрования сообщения не найден"); } // И на нем расшифровываем данные. byte[] decryptedData = exml.DecryptData(encryptedData, decryptionKey); exml.ReplaceData(element, decryptedData); } } xmlDoc.Save(filename5); // Отображаем файл если требуется для дебага if (DEBUG_STEP < 5) { foView view = new foView(); view.Text = filename5; view.xmlFileName = filename5; view.Show(); } return(filename5); }
/// <summary> /// Шифрует XML файл по пути /// </summary> /// <param name="filename">Путь файла</param> /// <returns>Путь зашифрованного файла</returns> public string encryptXml(string filename) { if (externalFileSign) // Если выставлен флаг подписи внешними средствами - грузим его. { OpenFileDialog ofd = new OpenFileDialog(); ofd.InitialDirectory = Path.GetTempPath(); ofd.Filter = "*.xml|*.xml"; string f = null; while (f == null) { ofd.ShowDialog(); f = ofd.FileName; } filename = f; } if (!File.Exists(filename)) { throw new Exception("Шаг 3. Файл не найден!\r\nПуть:" + filename); } string filename3 = filename + ".encrypted.xml"; // Открываем файл для шифрования XmlDocument xmlDoc = new XmlDocument(); xmlDoc.PreserveWhitespace = true; xmlDoc.Load(filename); // Шифруем по методу создания ключа обмена EncryptedXml eXml = new EncryptedXml(); EncryptedData edElement = eXml.Encrypt(xmlDoc.DocumentElement, certFss); edElement.Type = CPEncryptedXml.XmlEncGost28147Url; XmlElement xe = edElement.GetXml(); XmlDocument xmlDocEnc = new XmlDocument(); xmlDocEnc.LoadXml(Properties.Resources.Source2); // "Правильная" замена сертификата на наш, и вставка прочих данных xmlDocEnc.DocumentElement.GetElementsByTagName("ds:X509Certificate").Item(0).InnerText = Convert.ToBase64String(certOur.RawData); xmlDocEnc.DocumentElement.GetElementsByTagName("xenc:CipherValue").Item(0).InnerText = xe.GetElementsByTagName("CipherValue").Item(0).InnerText; xmlDocEnc.DocumentElement.GetElementsByTagName("xenc:CipherValue").Item(1).InnerText = xe.GetElementsByTagName("CipherValue").Item(1).InnerText; // Сохраняем зашифрованный документ в файле xmlDocEnc.Save(filename3); // Отображаем файл если требуется для дебага if (DEBUG_STEP < 3) { foView view = new foView(); view.Text = filename3; view.xmlFileName = filename3; view.Show(); } return(filename3); }
/// <summary> /// Подписывает XML файл по пути /// </summary> /// <param name="filename">Путь к файлу для подписи</param> /// <returns>Путь подписанного файла</returns> public string signXml(string filename) { if (!File.Exists(filename)) { throw new Exception("Шаг 2. Файл не найден!\r\nПуть:" + filename); } string filename2 = filename + ".signed.xml"; // Открываем файл для подписи XmlDocument xmlDoc = new XmlDocument(); xmlDoc.PreserveWhitespace = true; // Всякие пробелы обязательно оставляем xmlDoc.Load(filename); // Создаем особый XML для подписи взятый с сайта http://cryptopro.ru/blog/2012/05/16/podpis-soobshchenii-soap-dlya-smev-s-ispolzovaniem-kriptopro-net SmevSignedXml signedXml = new SmevSignedXml(xmlDoc); signedXml.SigningKey = certOur.PrivateKey; // Подписываем нашим закрытым ключом // Дальше идет магия, особо мне непонятная Reference reference = new Reference(); // Создаем ссылку для файла reference.Uri = "#REGNO_1603774817"; // Ее УРИ reference.DigestMethod = CPSignedXml.XmlDsigGost3411UrlObsolete; // Указываем устаревший метод описания. Обязательно этот устаревший XmlDsigExcC14NTransform c14 = new XmlDsigExcC14NTransform(); // Создаем метод канонизации reference.AddTransform(c14); // Подключаем ссылку signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl; // Подключаем метод канонизации к нашему файлу signedXml.SignedInfo.SignatureMethod = CPSignedXml.XmlDsigGost3410UrlObsolete; // Опять указываем устаревший метод подписи signedXml.AddReference(reference); // Добавляем ссылку KeyInfo keyInfo = new KeyInfo(); // Создаем инфо о ключе keyInfo.AddClause(new KeyInfoX509Data(certOur)); // О нашем ключе signedXml.KeyInfo = keyInfo; // Указываем ее signedXml.ComputeSignature(); // Вычисляем подпись XmlElement xmlDigitalSignature = signedXml.GetXml(); // Получаем xml // Перетасовываем всю инфу в файл для сохранения xmlDoc.GetElementsByTagName("ds:Signature")[0].PrependChild(xmlDoc.ImportNode(xmlDigitalSignature.GetElementsByTagName("SignatureValue")[0], true)); xmlDoc.GetElementsByTagName("ds:Signature")[0].PrependChild(xmlDoc.ImportNode(xmlDigitalSignature.GetElementsByTagName("SignedInfo")[0], true)); xmlDoc.GetElementsByTagName("wsse:BinarySecurityToken")[0].InnerText = Convert.ToBase64String(certOur.RawData); xmlDoc.Save(filename2); // Сохраняем подписанный документ в файле // Отображаем файл если требуется для дебага if (DEBUG_STEP < 2) { foView view = new foView(); view.Text = filename2; view.xmlFileName = filename2; view.Show(); } return(filename2); }