Чистый код<>Понятный код

По мотивам время от времени попадающихся мануалов «как писать чистый код». Ну не об этом все авторы думают в большинстве своём. Не поддерживали они легаси 20-ти летней давности, не разбирали код который написал условный Вася, который уже 15 лет как покинул эту компанию. Код в первую очередь должен быть понятным. А читаемым? Да пофиг. Любой код должен разобрать понять и исправить любой выпускник ПТУ. Вот к чему нужно стремиться. А как этого достичь? Да достаточно просто:

  1. Каждая процедура-функция должна быть прокомментирована «зачем она и что делает». Что принимает на вход, и то выдает на выходе. Длинных функций следует избегать.
  2. Переменные, имена функций и процедур должны говорить сами за себя
  3. Не используйте «сахар» в коде (легализованные языком сокращения кода). Пусть будет больше конструкций, зато человек не погруженный в язык, и не знающий его особенности быстро его поймёт.
  4. Если нет борьбы за производительность, то лучше написать медленный но понятный код, используя простые алгоритмы а не сложные.
  5. Используйте систему хранения версий на подобии GIT. Так можно будет потом отследить кто чего менял, а если будут прокомментированные коммиты, то и зачем.
  6. Если используете фремворки — то используйте их без фанатизма, чтобы однажды не оказалось что какой то его компонент (а то и сам фремворк) вдруг не стал тыквой. Это для долгосрочных проектов.

1С: Сброс пароля администратора в файловой БД

Рассматриваю вариант под ОС Linux. В некотором смысле это получается даже проще чем под Windows — не нужно искать никаких дополнительных утилит типа редактора HEX- всё уже есть «базе»

1) Открываем на просмотр в mc файл 1Cv8.1CD

2) Переходим в режим просмотра HEX — F4.

3) Ищем в режиме поиска в шестнадцатеричном формате сочетание 00 09 00 75 00 73

4) Заменяем 00 09 на 01 09, сохраняем изменения

5) Ищем 56 38 55 53 45 52 53 4D , заменяем 56 на 48

6) Открываем утилиту chdbfl из папки /opt/1cv8/x86_64/8.3.25.1445 (у вас папка другая конечно), и восстанавливаем базу.

После чего запускаем конфигуратор и входим без пароля

Замена PHP Curl на Wget

Так получилось, что иногда пишу парсеры сайтов на PHP. Использую обычный PHP Curl, густо обмазанный различными вспомогательными классами. Всё было хорошо, но однажды один из скриптов перестал работать. Стал разбираться почему — PHP стал падать с ошибкой сегментирования (segmentation fault) при вызове:

$res=curl_exec($ch);        

Стал разбираться. Выяснил что перестаёт падать после комментирования строчки:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

Явно что-то не так с шифрованием. Вспомнил даже, что нечто подобное уже было. Проверил — точно сайт стал шифроваться по протоколу ГОСТ:

И собственно в тот раз проблема решилась а в этот раз таки уже нет. Когда попробовал добавить ключ с указанием версии шифрования, скрипт стал бесконечно висеть.

curl_setopt ($ch, CURLOPT_SSLVERSION , CURL_SSLVERSION_TLSv1_3);

И из консоли в том числе:

curl --insecure  --tlsv1.3  'https://кацукацук/'

Ну ладно. Пойдем другим путём. Проверив как открывается этот-же сайт при помощи wget, и убедившись, что с ним всё хорошо, понял что при помощи его работа в принципе будет даже проще. Всё свелось к комбинации сточек вида (конкретно тут для примера без обработки ошибок):

function reqwest($url,$param){
        $res=wget --save-cookies cookies.txt --keep-session-cookies --load-cookies cookies.txt '$url' -O tmp.html --post-data '$param' --header 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8';        
        $html= file_get_contents("tmp.html");
return $html
}

Javascript: удаление элемента массива

В JavaScript как мне кажется не очень удобная реализация работы с массива. Наверное слишком низкоуровневая по сравнению с другими интерпретируемыми языками программирования. Возможно это даёт большую гибкость, но лично мне не удобно, что для простое удаление элемента массива по виду:

mass=[1,2,3,4];
delete mass[2];

Приводит на самом деле не к удалению элемента массива, а пометке, что элемент пустой. Многие пользуются командой splice:

mass=[1,2,3,4];
mass.splice(2,1)

Или даже filter:

brisks_mass=[1,2,3,4];
brisks_mass=brisks_mass.filter((number)=>number!==3) 

Но как говорится «Мне не зашло» (c), ибо есть с чем сравнивать удобство (Python, PHP и т.д.)

ГИС ЖКХ. Отправка и подпись сообщений на PHP

Ранее была статья, с реализацией подписи на Python. Переписал всё то-же самое на PHP. Ну на тот случай, если вдруг какие-то нюансы упустил в реализации. Однако нет, ошибка та-же:

<ns4:ErrorCode>AUT011005</ns4:ErrorCode>
<ns4:Description>Ошибка формата подписи запроса</ns4:Description>

Ниже описываю как формирую запрос. Он собирается из нескольких файлов xml:

in.xml

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:base="http://dom.gosuslugi.ru/schema/integration/base/" xmlns:drs="http://dom.gosuslugi.ru/schema/integration/drs/" xmlns:xd="http://www.w3.org/2000/09/xmldsig#">
   <soapenv:Header>
      <base:RequestHeader>
         <base:Date>2025-03-19T11:26:00+03:00</base:Date>
          <base:MessageGUID>${=java.util.UUID.randomUUID()}</base:MessageGUID>
		<base:orgPPAGUID>cerfwerfewrfer8</base:orgPPAGUID>
      </base:RequestHeader>
   </soapenv:Header>
<soapenv:Body xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">    
    {req}
</soapenv:Body>
</soapenv:Envelope>

req.xml — непосредственно запрос к ГИС ЖКХ. В данном случае получение списка запросов от сторонних организаций о задолженностях потребителей

<drs:exportDSRsRequest Id="{signed_id}" base:version="15.3.0.0">  
<drs:periodOfSendingRequest><base:startDate>2025-05-27</base:startDate><base:endDate>2025-06-28</base:endDate></drs:periodOfSendingRequest>
</drs:exportDSRsRequest>

xades.xml:

<ds:Signature Id="xmldsig-{signature_id}" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
   {ds:SignedInfo}
   <ds:SignatureValue Id="xmldsig-{signature_id}-sigvalue">{signature_value}</ds:SignatureValue>
   <ds:KeyInfo>
       <ds:X509Data>
         <ds:X509Certificate>{x590_cert}</ds:X509Certificate>
       </ds:X509Data>
   </ds:KeyInfo>
   <ds:Object>
      <xades:QualifyingProperties xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" Target="#xmldsig-{signature_id}">{SignedProperties}</xades:QualifyingProperties>
   </ds:Object>
</ds:Signature>

sp.xml:

<xades:SignedProperties Id="xmldsig-{signature_id}-signedprops">      
    <xades:SignedSignatureProperties>
        <xades:SigningTime>{signing_time}</xades:SigningTime>
        <xades:SigningCertificate>
         <xades:Cert>
           <xades:CertDigest>
             <ds:DigestMethod Algorithm="urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34112012-256"/>
             <ds:DigestValue>{digest2}</ds:DigestValue>
           </xades:CertDigest>
           <xades:IssuerSerial>
              <ds:X509IssuerName>{x509_issuer_name}</ds:X509IssuerName>
              <ds:X509SerialNumber>{x509_sn}</ds:X509SerialNumber>
           </xades:IssuerSerial>
         </xades:Cert>
        </xades:SigningCertificate>
      </xades:SignedSignatureProperties>
</xades:SignedProperties>      

si.xml:

<ds:SignedInfo>
    <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
      <ds:SignatureMethod Algorithm="urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34102012-gostr34112012-256"/>
      <ds:Reference Id="xmldsig-{signature_id}-ref0" URI="#{signed_id}">
          <ds:Transforms>
             <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
             <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
          </ds:Transforms>
         <ds:DigestMethod Algorithm="urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34112012-256"/>
         <ds:DigestValue>{digest1}</ds:DigestValue>
     </ds:Reference>
     <ds:Reference Type="http://uri.etsi.org/01903#SignedProperties" URI="#xmldsig-{signature_id}-signedprops">
        <ds:DigestMethod Algorithm="urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34112012-256"/>
        <ds:DigestValue>{digest3}</ds:DigestValue>
     </ds:Reference>
</ds:SignedInfo>

Т.е. общий алгоритм следующий — заполняем в каждом файлике значения в фигурных скобках, а затем склеиваем всё в единый файл out.xml, который уже непосредственно отправляем по SOAP через туннель с ГИС ЖКХ.

Для начала понадобятся следующие функции:

Вычисление хэш строки по алгоритму ГОСТ Р 34.11-2012 256 бит:

function md_gost($text){
  file_put_contents("tmp.xml", $text);
  $res=cat tmp.xml | openssl dgst -binary -md_gost12_256 | base64 -w 0;
  $res= str_replace("\n", "", $res);
  return trim($res);
};

Получается строка вида: JSO1ALXjmpWXGkdQAs4RcEroYUnXOdbp5j4tbG8bNN8= в формате base64

Получение эмитента сертификата:

function get_issuer($cert_file){
  $res=openssl x509 -in $cert_file -issuer -nameopt sep_multiline,utf8 -noout;
  $res= str_replace("issuer=\n", "", $res);
  $res= str_replace("emailaddress", "1.2.840.113549.1.9.1", $res);
  $res= str_replace("inn", "1.2.643.100.4", $res);
  $res= str_replace("ogrn", "1.2.643.100.1", $res);
  $res= str_replace('"', "\\", $res);
  $res= str_replace(',', "\,", $res);
  $res= explode("\n", $res);
  $result="";
  for ($index = count($res)-1; $index > 0; $index--) {
    if (trim($res[$index])!=""){
        $prop= explode("=",$res[$index]);
        $result=$result.strtolower(trim($prop[0]))."=".trim($prop[1]);
        if ($index>1){
            $result=$result.",";
        };
    };
  };
  return trim($result);
}

Особенностью является «перевертывание» информации, нормализация отображения, а так-же замена ИНН, ОГРН и email на цифровые коды. Согласно рекомендации из «Альбом ТФФ». У меня получилась строка вида:

cn=Федеральная налоговая служба,o=Федеральная налоговая служба,street=ул. Неглинная\, д. 23,l=г. Москва,st=77 Москва,c=RU,ogrn=1047707030513,emailaddress=uc@tax.gov.ru

Получение серийного номера сертификата:

function get_serial($cert_file){
    $res=openssl x509 -in $cert_file -serial -nameopt sep_multiline,utf8 -noout;
    $res= str_replace("serial=", "", $res);
    $res= str_replace("\n", "", $res);
    return base_convert(trim($res),16,10);
}

Согласно Альбому ТФФ, он должен быть в десятичном формате. Вида:

778141053723503123230066408008688602

Канонинализация XML:

Для того чтобы в XML не было лишних и не значащих символов, данные перед подписанием и вычислением хэша необходимо канонинализировать:

function CanonicalXML($xml_text){
    $xml = new DOMDocument( "1.0", "utf-8" );
    @$xml->loadXML($xml_text);
    $xml = @$xml->C14N();
    return $xml;
}

Получение сертификата в формате Base64:

function X590($cert_file){
  $crt= file_get_contents($cert_file);  
  $crt= str_replace("-----BEGIN CERTIFICATE-----", "", $crt);
  $crt= str_replace("-----END CERTIFICATE-----", "", $crt);
  $crt= str_replace("\n", "", $crt);
  $crt= str_replace("\r", "", $crt);
  return trim($crt);
}

Получение подписи текста:

function get_signature($text, $private_file){
    file_put_contents("for_sign.xml", $text);    
    $res=cat for_sign.xml | openssl dgst -md_gost12_256 -sign $private_file -binary | base64 -w 0;
    $res= str_replace("\n", "", $res);
    return trim($res);
}

Возвращается в формате base64

Получение UUID:

function guidv4($data = null) {
    $data = $data ?? random_bytes(16);
    assert(strlen($data) == 16);
    $data[6] = chr(ord($data[6]) & 0x0f | 0x40);
    $data[8] = chr(ord($data[8]) & 0x3f | 0x80);
    return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}

Далее идет уже непосредственно уже вычисление необходимых блоков и формирование выходного файла:

$in_file='in/in.xml';           // xml - главный шаблон, откуда осуществляем сборку
$req_file='in/req.xml';         // запрос в ГИС ЖКХ
$xades_file='in/xades.xml';     // Рыба подписи
$sp_file='in/sp.xml';           // Свойства подписи
$si_file='in/si.xml';           // Непосредственно подписываемый блок
$cert_file='keys/cert.key';     // Сертификат формата X590
$private_file='keys/priv.key';  // Закрытый ключ

$signed_id=guidv4();

$in_xml=file_get_contents($in_file);
$req_xml=CanonicalXML(file_get_contents($req_file));
$req_xml= str_replace("{signed_id}", $signed_id, $req_xml);

$xades_xml=file_get_contents($xades_file);


$digest1=md_gost($req_xml);
echo "digest1=$digest1\n";
$digest2= md_gost(base64_decode(X590($cert_file)));
echo "digest2=$digest2\n";

$dt=new DateTime();
$signing_time=$dt->format(DateTime::ATOM);
$signature_id=guidv4();


$sp_xml=CanonicalXML(file_get_contents($sp_file));
$sp_xml= str_replace("{signing_time}", $signing_time, $sp_xml);
$sp_xml= str_replace("{digest2}", $digest2, $sp_xml);
$sp_xml= str_replace("{x509_issuer_name}", get_issuer($cert_file), $sp_xml);
$sp_xml= str_replace("{x509_sn}", get_serial($cert_file), $sp_xml);
$digest3=md_gost($sp_xml);
echo "digest3=$digest3\n";

$si_xml=CanonicalXML(file_get_contents($si_file));
$si_xml= str_replace("{digest3}", $digest3, $si_xml);
$si_xml= str_replace("{digest1}", $digest1, $si_xml);
$si_xml= str_replace("{signature_id}", $signature_id, $si_xml);
$si_xml= str_replace("{signed_id}", $signed_id, $si_xml);

$signature_value=get_signature($si_xml,$private_file);
echo "signature_value=$signature_value\n";
$xades_xml= str_replace("{signature_value}", $signature_value, $xades_xml);
$xades_xml= str_replace("{x590_cert}", X590($cert_file), $xades_xml);
$xades_xml= str_replace("{SignedProperties}",$sp_xml, $xades_xml);
$xades_xml= str_replace("{ds:SignedInfo}",$si_xml, $xades_xml);
$xades_xml= str_replace("{signature_id}", $signature_id, $xades_xml);

//$in_xml= str_replace("{xades}",$xades_xml, $in_xml);
var_dump($req_xml);

$pz= strpos($req_xml, ">");
$req_1= trim(substr($req_xml,0,$pz+1));
$req_2= trim(substr($req_xml,$pz+1, strlen($req_xml)-$pz));

$req_xml=$req_1.$xades_xml.$req_2;

$in_xml= str_replace("{req}",$req_xml, $in_xml);

file_put_contents("out/out.xml",$in_xml);

Далее полученный файлик можно вставить например в SOAP UI, и попробовать отправить.

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:base="http://dom.gosuslugi.ru/schema/integration/base/" xmlns:drs="http://dom.gosuslugi.ru/schema/integration/drs/" xmlns:xd="http://www.w3.org/2000/09/xmldsig#">
   <soapenv:Header>
      <base:RequestHeader>
         <base:Date>2025-03-19T11:26:00+03:00</base:Date>
          <base:MessageGUID>${=java.util.UUID.randomUUID()}</base:MessageGUID>
		<base:orgPPAGUID>укепуепукепукеп</base:orgPPAGUID>
      </base:RequestHeader>
   </soapenv:Header>
<soapenv:Body xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">    
    <drs:exportDSRsRequest Id="938803c1-341c-41c5-8d24-10fa15dde654" base:version="15.3.0.0"><ds:Signature Id="xmldsig-51a19c5a-7c25-432c-9340-dd7582d4d3ef" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
   <ds:SignedInfo>
    <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod>
      <ds:SignatureMethod Algorithm="urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34102012-gostr34112012-256"></ds:SignatureMethod>
      <ds:Reference Id="xmldsig-51a19c5a-7c25-432c-9340-dd7582d4d3ef-ref0" URI="#938803c1-341c-41c5-8d24-10fa15dde654">
          <ds:Transforms>
             <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform>
             <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform>
          </ds:Transforms>
         <ds:DigestMethod Algorithm="urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34112012-256"></ds:DigestMethod>
         <ds:DigestValue>324к234к234к234к/6dgGHM4k52/RDm855aKazGXEeK4=</ds:DigestValue>
     </ds:Reference>
     <ds:Reference Type="http://uri.etsi.org/01903#SignedProperties" URI="#xmldsig-51a19c5a-7c25-432c-9340-dd7582d4d3ef-signedprops">
        <ds:DigestMethod Algorithm="urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34112012-256"></ds:DigestMethod>
        <ds:DigestValue>34к34к234к234к3</ds:DigestValue>
     </ds:Reference>
</ds:SignedInfo>
   <ds:SignatureValue Id="xmldsig-51a19c5a-7c25-432c-9340-dd7582d4d3ef-sigvalue">mWUI++9N1uEe/234к234к/укеаукепуке</ds:SignatureValue>
   <ds:KeyInfo>
       <ds:X509Data>
         <ds:X509Certificate>укепукепкуепк/укепукепуке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</ds:X509Certificate>
       </ds:X509Data>
   </ds:KeyInfo>
   <ds:Object>
      <xades:QualifyingProperties xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" Target="#xmldsig-51a19c5a-7c25-432c-9340-dd7582d4d3ef"><xades:SignedProperties Id="xmldsig-51a19c5a-7c25-432c-9340-dd7582d4d3ef-signedprops">      
    <xades:SignedSignatureProperties>
        <xades:SigningTime>2025-06-17T10:31:13+03:00</xades:SigningTime>
        <xades:SigningCertificate>
         <xades:Cert>
           <xades:CertDigest>
             <ds:DigestMethod Algorithm="urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34112012-256"></ds:DigestMethod>
             <ds:DigestValue>кепукепук</ds:DigestValue>
           </xades:CertDigest>
           <xades:IssuerSerial>
              <ds:X509IssuerName>cn=Федеральная налоговая служба,o=Федеральная налоговая служба,street=ул. Неглинная\, д. 23,l=г. Москва,st=77 Москва,c=RU,ogrn=1047707030513,emailaddress=uc@tax.gov.ru</ds:X509IssuerName>
              <ds:X509SerialNumber>45е34е5354е43е</ds:X509SerialNumber>
           </xades:IssuerSerial>
         </xades:Cert>
        </xades:SigningCertificate>
      </xades:SignedSignatureProperties>
</xades:SignedProperties></xades:QualifyingProperties>
   </ds:Object>
</ds:Signature><drs:periodOfSendingRequest><base:startDate>2025-05-27</base:startDate><base:endDate>2025-06-28</base:endDate></drs:periodOfSendingRequest>
</drs:exportDSRsRequest>
</soapenv:Body>
</soapenv:Envelope>

В ответ получим номер идентификатора запроса. Далее его используем в запросе getState.. И получаем ошибку которая в самом начале статьи. Что не так — пока не понятно.

Update: тут немножко не верная реализация подписи. Нужно подписывать хэш данных, а у меня подписываются данные. Но пока без разницы — ошибка так и осталась.

1 2 3 4 71