<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Serov.eu &#187; Digest</title>
	<atom:link href="https://serov.eu/?feed=rss2&#038;tag=digest" rel="self" type="application/rss+xml" />
	<link>https://serov.eu</link>
	<description>Блог программиста</description>
	<lastBuildDate>Thu, 30 Apr 2026 12:31:53 +0000</lastBuildDate>
	<language>ru-RU</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=4.1.15</generator>
	<item>
		<title>Дайджест-аутентификация (Digest access authentication)</title>
		<link>https://serov.eu/?p=653</link>
		<comments>https://serov.eu/?p=653#comments</comments>
		<pubDate>Fri, 30 Apr 2021 08:03:18 +0000</pubDate>
		<dc:creator><![CDATA[Evgen]]></dc:creator>
				<category><![CDATA[Программирование]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[Digest]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">https://serov.eu/?p=653</guid>
		<description><![CDATA[Ранее я описывал алгоритм авторизации Digest, как самому собрать пакет данных Для  PHP все оказалось проще,  в  CURL уже есть готовый механизм, который делает 2 запроса для правильной авторизации Это параметр CURLOPT_HTTPAUTH => CURLAUTH_DIGEST, &#160; &#160; Полностью запрос: $request =[ 'SOAPAction: "http://yandex.ru/"', 'Content-Type: text/xml;charset=UTF-8', ]; $options = array( CURLOPT_URL => $url, CURLOPT_HEADER => true, CURLOPT_VERBOSE => &#8230; <a href="https://serov.eu/?p=653" class="more-link">Читать далее <span class="screen-reader-text">Дайджест-аутентификация (Digest access authentication)</span></a>]]></description>
				<content:encoded><![CDATA[<p><a href="https://serov.eu/?p=585">Ранее</a>  я описывал алгоритм авторизации Digest, как самому собрать пакет данных</p>
<p>Для  PHP все оказалось проще,  в  CURL уже есть готовый механизм, который делает 2 запроса для правильной авторизации</p>
<p>Это параметр CURLOPT_HTTPAUTH       => CURLAUTH_DIGEST,</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>Полностью запрос:</p>
<pre>

$request =[
    'SOAPAction: "http://yandex.ru/"',
    'Content-Type: text/xml;charset=UTF-8',
];


$options = array(
    CURLOPT_URL            => $url,
    CURLOPT_HEADER         => true,
    CURLOPT_VERBOSE        => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_SSL_VERIFYPEER => false,    // for https
    CURLOPT_USERPWD        => $username . ":" . $password,
    CURLOPT_HTTPAUTH       => CURLAUTH_DIGEST,
    CURLOPT_HTTPHEADER     => $request,
    CURLOPT_POST           => true,

    CURLOPT_POSTFIELDS     =>"xmlRequest=" . $input_xml // если нужно передать xml в теле POST
);

$ch = curl_init();

curl_setopt_array( $ch, $options );

try {
    $raw_response  = curl_exec( $ch );


    // validate CURL status
    if(curl_errno($ch))
        throw new Exception(curl_error($ch), 500);

    // validate HTTP status code (user/password credential issues)
    $status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    if ($status_code != 200)
        throw new Exception("Response with Status Code [" . $status_code . "].", 500);

} catch(Exception $ex) {
    if ($ch != null) curl_close($ch);
    throw new Exception($ex);
}

if ($ch != null) curl_close($ch);

echo "raw response: " . $raw_response;



</pre>
]]></content:encoded>
			<wfw:commentRss>https://serov.eu/?feed=rss2&#038;p=653</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HTTP Digest</title>
		<link>https://serov.eu/?p=585</link>
		<comments>https://serov.eu/?p=585#comments</comments>
		<pubDate>Wed, 30 Dec 2020 07:36:36 +0000</pubDate>
		<dc:creator><![CDATA[Evgen]]></dc:creator>
				<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Digest]]></category>

		<guid isPermaLink="false">https://serov.eu/?p=585</guid>
		<description><![CDATA[Документация по Digest http://www.hardline.ru/4/38/4862/ Проверка Curl curl -v &#8212;digest &#8212;user &#8216;User:Password&#8217; &#171;https://yandex.ru/MessageService/WebService.svc&#187; &#160; Система аутентификации на базе протокола HTTP Digest. Усиление модуля. В статье &#171;Система аутентификации на базе протокола HTTP Basic был рассмотрен алгоритм Basic аутентификации и с помощью него была построена система Basic аутентификации на основе ролей, работающая без специальной настройки IIS сервера и использующая базу &#8230; <a href="https://serov.eu/?p=585" class="more-link">Читать далее <span class="screen-reader-text">HTTP Digest</span></a>]]></description>
				<content:encoded><![CDATA[<p>Документация по Digest http://www.hardline.ru/4/38/4862/</p>
<p>Проверка Curl</p>
<p>curl -v &#8212;digest &#8212;user &#8216;User:Password&#8217; &#171;https://yandex.ru/MessageService/WebService.svc&#187;</p>
<p>&nbsp;</p>
<table id="table1" cellspacing="0" cellpadding="0">
<tbody>
<tr valign="top">
<td>
<h1><span id="_ctl0_Article1__ctl0_lblTitle">Система аутентификации на базе протокола HTTP Digest. Усиление модуля.</span></h1>
</td>
</tr>
<tr valign="top">
<td id="_ctl0_Article1__ctl0_HtmlHolder" class="normal">В статье &#171;Система аутентификации на базе протокола HTTP Basic был рассмотрен алгоритм Basic аутентификации и с помощью него была построена система Basic аутентификации на основе ролей, работающая без специальной настройки IIS сервера и использующая базу данных для хранения учетных записей пользователей.У Basic есть один недостаток, а именно username и password передаются по сети открыто (clear text), base64 кодировка не может считаться защитой.</p>
<h4>Аутентификация Digest</h4>
<p>В этой статье будет рассмотрен алгоритм Digest аутентификации, решающей некоторые проблемы, имеющиеся у HTTP Basic Authentication. Например эта схема не передаёт password по сети открытым текстом. Официальное название схемы &#8212; &#171;Digest Access Authentication&#187;.</p>
<p>Расширим нашу систему из предыдущей статьи.</p>
<p>К преимуществам Digest можно отнести следуещее:</p>
<ol>
<li>passwords не передаются открыто по сети</li>
<li>способность защиты от повторяющихся атак (monitoring http nc value)</li>
<li>способность создать защиту (monitoring nonce)
<ul>
<li>в определённый промежуток времени</li>
<li>от определённого client</li>
<li>от определённого request</li>
</ul>
</li>
</ol>
<p>Один сайт может одновременно использовать несколько систем защиты, например Basic и Digest</p>
<p>Пришло время рассмотреть работу алгоритма Digest аутентификации:</p>
<p>1. Первый запрос от User Agent к Http Server заголовок Authorization пустой &#8212; значит server должен возвратить запрос на аутентификацию. Например такой:</p>
<p>2. ответ сервера:</p>
<pre class="code">HTTP/1.1 401 Unauthorized
        WWW-Authenticate: <b>Digest</b>
                 realm="testrealm@host.com",
                 qop="auth",
                 nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
                 opaque="5ccc069c403ebaf9f0171e9517f40e41",
                 algorithm=MD5,
                 stale=false
</pre>
<p>Разберём заголовок WWW-Authenticate (как вы заметили, он усложнился по сравнению с заголовком Basic):</p>
<table id="table2" cellspacing="2" cellpadding="2">
<tbody>
<tr>
<td>realm</td>
<td>Строка, указывающая юзеру где он и какой пароль вводить например &#171;registered_users@gotham.news.com&#187;.</td>
</tr>
<tr>
<td>nonce</td>
<td>Уникальная строка, которая генерируется на сервере в момент ответа 401. запрещено использовать кавычку, так как внутри заголовка строка в кавычках рекомендуется также закодировать её base64, например time-stamp H(time-stamp &#171;:&#187; ETag &#171;:&#187; private-key)</td>
</tr>
<tr>
<td>opaque</td>
<td>Строка, которую юзер должен будет вернуть на сервер в неизменённом виде Рекомендуется закодировать base64</td>
</tr>
<tr>
<td>stale</td>
<td>true/false<br />
Индикатор, который показывает, что если true &#8212; запрос был правильный, username-password тоже, nonce неправильный false или любое другое значение или отсутствие stale &#8212; неправильные username, password</td>
</tr>
<tr>
<td>algorithm</td>
<td>optional, MD5 = default</td>
</tr>
<tr>
<td>qop</td>
<td>указывает &#171;quality of protection&#187;.<br />
&#171;auth&#187; указывает authentication,<br />
&#171;auth-int&#187; указывает authentication + integrity protection. могут быть оба через запятую</td>
</tr>
</tbody>
</table>
<p>3. У юзера всплывает модальное окно, предлагающее ввести username и password (обратите внимание, окно отличается от Basic окна). Происходит запрос юзера для аутентификации:</p>
<pre class="code">GET ... ... HTTP/1.1
        Authorization: Digest
                 username="Mufasa",
                 realm="testrealm@host.com",
                 nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
                 uri="/dir/index.html",
                 qop=auth,
                 nc=00000001,
                 cnonce="0a4f113b",
                 response="6629fae49393a05397450978507c4ef1",
                 opaque="5ccc069c403ebaf9f0171e9517f40e41"
</pre>
<p>Теперь разберём заголовок Authorization:</p>
<table id="table3" cellspacing="2" cellpadding="2">
<tbody>
<tr>
<td>username</td>
<td>имя юзера</td>
</tr>
<tr>
<td>realm</td>
<td>см. WWW-Authenticate</td>
</tr>
<tr>
<td>qop</td>
<td>см. WWW-Authenticate (должно совпадать с одним из списка qop WWW-Authenticate)</td>
</tr>
<tr>
<td>algorithm</td>
<td>см. WWW-Authenticate (должно совпадать)</td>
</tr>
<tr>
<td>opaque</td>
<td>см. WWW-Authenticate (должно совпадать)</td>
</tr>
<tr>
<td>uri</td>
<td>запрос (например страница)</td>
</tr>
<tr>
<td>response</td>
<td>32-character строка &#8212; именно c её помощью проверяется пароль.</td>
</tr>
<tr>
<td>nonce</td>
<td></td>
</tr>
<tr>
<td>nc</td>
<td>once count &#8212; сколько раз был использован текущий nonce</td>
</tr>
<tr>
<td>cnonce</td>
<td>уникальная строка, посылаемая браузером на сервер</td>
</tr>
</tbody>
</table>
<p>4. Последовательность обработки запроса пользователя</p>
<ol>
<li>Проверяем, существует ли заголовок Authorization</li>
<li>Проверяем, является ли он Digest</li>
<li>Отсекаем слово Digest</li>
<li>Берём username (обратите внимание &#8212; в заголовке отсутствует password &#8212; по крайней мере его не видно)</li>
<li>проверяем базу данных с этим юзером, существует ли он &#8212; запоминаем его password из базы</li>
<li>проверяем запрос по ролям против страниц с ролями, как мы уже делали в Basic.</li>
</ol>
<p>Если что-то не так &#8212; переходим к пункту 6. Если всё ok &#8212; идём дальше (это ещё далеко не всё :))</p>
<p>5. Проверка пароля пользователя</p>
<ol>
<li>создаём строку A1 вида<br />
A1 = unq(username) : unq(realm) : passwd</li>
<li>хешируем A1<br />
HA1 = MD5(A1)</li>
<li>создаём строку A2 вида<br />
A2 = Http Method &#171;:&#187; digest-uri</li>
<li>хешируем A2<br />
HA2 = MD5(A2)</li>
<li>создаём строку GENRESPONSE вида<br />
GENRESPONSE = HA1 &#171;:&#187; nonce &#171;:&#187; nc &#171;:&#187; cnonce &#171;:&#187; qop &#171;:&#187; HA2</li>
<li>хешируем GENRESPONSE<br />
HGENRESPONSE = MD5(GENRESPONSE)</li>
</ol>
<p>если HGENRESPONSE равен response в заголовке Authorization запроса юзера и nonce в порядке &#8212; всё ok, нет &#8212; переходим к пункту 6</p>
<p>6. выдаём состояние ответа сервера 401, поднимающее модальное окно как в пункте 2 иначе говоря формируем WWW-Authenticate по типу Digest</td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>https://serov.eu/?feed=rss2&#038;p=585</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
